2012年2月21日 星期二

[TQC+ Android] 2-7 密碼鎖





設計密碼鎖 , 可自行設定密碼進行比對並更新 , 以下是程式碼。


package COM.TQC.GDD02;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class GDD02 extends Activity
{
 
 private String btnAdd = "Add";
 private String btnLogin = "Login";
 private String btnUpdate = "Update";
 private String FileName = "MY_PASSWORD";
 private FileInputStream fileInputStream = null; 
 private Button Button01;
 private EditText EditText01;
    
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        EditText01 = (EditText) findViewById(R.id.EditText01);
        Button01 = (Button) findViewById(R.id.Button01);
        
  try 
  {
   fileInputStream = openFileInput(FileName+".txt");
   //如果檔案不存在的話及會發生 FileNotFoundException 
   Button01.setText(btnLogin);
   
   fileInputStream.close();
   //已經確定檔案存在了, Closes this stream
   
  }catch (FileNotFoundException e)
  {
   // TODO Auto-generated catch block
   if(fileInputStream==null)
   {
    Button01.setText(btnAdd);
   }
   e.printStackTrace();
  } catch (IOException e)
  {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
  Button01.setOnClickListener(new View.OnClickListener()
  {
   @Override
   public void onClick(View arg0)
   {
    // TODO Auto-generated method stub
    if(Button01.getText().equals(btnAdd))
    {
     String text = ""+EditText01.getText();
     if(!text.equals(""))     
     {
      writeFile(text);      
      showToast("新增成功!請重新登入!"); 
      Button01.setText(btnLogin);
      EditText01.setText("");
     }
     else showToast("請輸入密碼!");      
    }
    else if(Button01.getText().equals(btnLogin))
    {
     String text = EditText01.getText().toString();
     
     if(text.equals(readFile()))
     {
      showToast("登入成功!");
      Button01.setText(btnUpdate);
      EditText01.setText("");
     }
     else
     {
      showToast("登入失敗!");
      EditText01.setText("");
     }     
    }
    else if(Button01.getText().equals(btnUpdate))
    {
     String text = ""+EditText01.getText();
     if(!text.equals(""))
     {
      writeFile(text);
      showToast("修改成功!請重新登入!");
      Button01.setText(btnLogin);
      EditText01.setText("");
     }
     else showToast("請輸入密碼!");     
    }
   }});
    }
    
    private void writeFile(String data)
    {   
  try
  {
   StringBuffer SBuffer = new StringBuffer(data);
   SBuffer.append('\n');
   //使用\n字元做為字串結尾
   FileOutputStream fos = openFileOutput(FileName+".txt", MODE_PRIVATE);
      fos.write(SBuffer.toString().getBytes());
      fos.close();
  }catch (FileNotFoundException e)
  {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
    }
    
    private String readFile()
    {    
     byte[] byteArray = new byte[1024];
     
  try
  {
   fileInputStream = this.openFileInput(FileName+".txt");
   fileInputStream.read(byteArray);
   fileInputStream.close();   
   
  } catch (FileNotFoundException e)
  {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } 
  String data = new String(byteArray);
  int index = data.indexOf("\n");
  return data.substring(0, index);
  /*
          由於byteArray長度為1024 , 將byteArray轉為字串後長度為1024
          因為字串補了空白字元所以長度才會到1024 , 所以當初在writeFile的時候
          才會在最後面補上\n作為結尾 , 現在取開頭到\n中間的部分做為回傳的字串 
   */
  
    }
    
    private void showToast(String message)
    {
     Toast t = Toast.makeText(this, message, Toast.LENGTH_LONG);
        t.show();
    }
}



以及簡單的 Layout檔


 
 
 












                                   
檔案儲存的地方在/data/data/PackageName/FileName.txt


P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



2012年2月18日 星期六

[TQC+ Android] 2-6 資料庫讀取 Use SQLiteDatabase, Custom BaseAdapter





可顯示資料庫內的資料於頁面 , 進行勾選後顯示於表單標題上 , 這題的重點在DataBase的存取 , 還有為了要讓嵌在List RowView內的CheckBox能引發事件 , 我們還要額外去Custom Adapter , 這個做法是去 extends Adapter , 程式碼如下。


package COM.TQC.GDD02;

import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;


public class GDD02 extends Activity
{
 SQLiteDatabase dataBase;
 Cursor cursor;
 Button exitButton , okButton;
 ListView listview;
 boolean[] CB = new boolean[3];
 
 String DATABASENAME = "MyDB";
 String TABLENAME = "MyTB";
 String FIELD01_ID = "_id";
 String FIELD02_NOTE = "note";
 String FIELD03_CREATED = "created";
 
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        dataBase =  this.openOrCreateDatabase(DATABASENAME, MODE_PRIVATE, null);
        
        try
        {
         cursor = dataBase.rawQuery("SELECT * FROM "+TABLENAME, null);
            
        }catch(SQLiteException SQLiteException)
        {
         //如果Table MyTB 不存在的話 , 新增Table , 新增資料
         String create = "create table if not exists "+TABLENAME+" ("+FIELD01_ID+" integer primary key autoincrement, "+FIELD02_NOTE+" varchar not null, "+FIELD03_CREATED+" INTEGER)";
            dataBase.execSQL(create);
                
            dataBase.execSQL("INSERT INTO "+TABLENAME+" ("+FIELD02_NOTE+","+FIELD03_CREATED+") values ('BOOK',10)");
            dataBase.execSQL("INSERT INTO "+TABLENAME+" ("+FIELD02_NOTE+","+FIELD03_CREATED+") values ('FOOD',10)");
            dataBase.execSQL("INSERT INTO "+TABLENAME+" ("+FIELD02_NOTE+","+FIELD03_CREATED+") values ('TOOL',10)");
            cursor = dataBase.rawQuery("SELECT * FROM "+TABLENAME, null);
            Log.d("Test", "SQLiteException");         
        }        
                  
        exitButton = (Button) this.findViewById(R.id.button2);
        exitButton.setOnClickListener(BOnClickListener);
        okButton = (Button) this.findViewById(R.id.button1);
        okButton.setOnClickListener(BOnClickListener);
        
        listview = (ListView) this.findViewById(R.id.listView1);
        myAdapter adapter = new myAdapter(cursor , CB);
        listview.setAdapter(adapter);       
    }
    
    public Button.OnClickListener BOnClickListener = new Button.OnClickListener()
    {
  @Override
  public void onClick(View v)
  {
   String temp="";
   int count=0;
   
      switch(v.getId())
      {
       case R.id.button1:
       for(int i=0;i<3;i++)
       {
        if(CB[i])
        {
         count++;
         cursor.moveToPosition(i);
         temp+=cursor.getString(1)+" ";
        }
       }
       if(count>0) GDD02.this.setTitle("{"+temp+"}");
       else GDD02.this.setTitle(R.string.app_name);
       break;
       
       case R.id.button2:
       finish();
       break;
      }
  }     
    };
    
    public class myAdapter extends BaseAdapter
    {        
     Cursor myAdapterCursor;       
     boolean[] myAdapterCB;     
     
     public myAdapter(Cursor c , boolean[] cb)
     {      
      myAdapterCB = cb;
      myAdapterCursor = c;
      myAdapterCursor.moveToFirst();
     }
         
        public View getView(final int position, View convertView, ViewGroup parent)
        {
            View rowview = convertView;
           
            if (rowview == null)
            {
                    LayoutInflater inflater = getLayoutInflater();
                    rowview = inflater.inflate(R.layout.list, parent, false);
                    //為了要把xml所描述的Layout轉變為View , 也就是我們要的rowview
                    //所以必須使用LayoutInflater來轉化 , 而要取得LayoutInflater的Instance方式還包括
                    //LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    //接著再使用inflate (int resource, ViewGroup root, boolean attachToRoot)
                    //傳回我們要的rowview
            }
            
            TextView notes = (TextView) rowview.findViewById(R.id.textView1);
            
            myAdapterCursor.moveToPosition(position);
            notes.setText(myAdapterCursor.getString(1));
            
            CheckBox checkBox = (CheckBox) rowview.findViewById(R.id.checkBox1);
            checkBox.setChecked(false);
            
             /*
         每個list rowview都有擺放一個CheckBox,為了當我們按下CheckBox的時候要做出
         事件反應 , 所以針對每個rowview上的CheckBox我們都將他設定 onClick(View arg0)的事件宣告
             */
            
            checkBox.setOnClickListener(new CheckBox.OnClickListener()
            {             
             @Override
    public void onClick(View arg0)
    {                           
              if(((CheckBox) arg0).isChecked()) myAdapterCB[position]= true;
     else myAdapterCB[position] = false;              
    }             
            });
            return rowview;
        }

  @Override
  public int getCount()
  {
   // TODO Auto-generated method stub   
   return myAdapterCursor.getCount();
  }

  @Override
  public Object getItem(int position) {
   // TODO Auto-generated method stub
    myAdapterCursor.moveToPosition(position);
    return myAdapterCursor.getString(1);
  }

  @Override
  public long getItemId(int position)
  {
   // TODO Auto-generated method stub
   myAdapterCursor.moveToPosition(position);
   return myAdapterCursor.getLong(0);
  }
     }

 @Override
 protected void onDestroy()
 {
  // TODO Auto-generated method stub
  
  if(dataBase.isOpen()) dataBase.close();
  
  super.onDestroy();
 }
    
}



再來是List RowView的 Layout檔

    
    




接著是main.xml檔



    
    
    










P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



2012年2月15日 星期三

[NBA] Linsanity 關於林書豪 About Jeremy Lin (HD Game highlights update to 3/03)





近日台灣甚至美國都捲起了一股林氏炫風 , 這是一位台裔哈佛小子林書豪 Jeremy Lin , 他在NBA打拚的故事 , 歷經未在選秀會被選上 , 然後被勇士隊簽下但是球季結束就被解約 , 輾轉到了火箭隊又被揮棄 , 在球隊的角色是替補中的替補 , 沒想到尼克隊簽下了他 , 但是尼克隊( New York Knicks )並不是馬上就重用他 , 一直到了總教練 Mike D'Antoni , 因為球隊戰績太差準備要丟了飯碗 , 在2 / 5號那天尼克對上籃網的時候 , Mike D'Antoni啟用了林書豪 , 林書豪那場以替補出賽卻打了35分鐘拿下25分7助功的成績 , 那晚他優異的表現也帶領尼克隊擊敗了籃網 , 幾次的關鍵得分更是拯救了球隊。

截至今天為止(2012/02/15) , 林書豪不僅帶領球隊取得六連勝 , 而且還創下前五場先發共得136分的紀錄為NBA歷史上得第一人打破了Shaquille O'Neal所保持的129分 , 真是不簡單 , 在這天時地利人和的情況下 , 林書豪掀起了林氏炫風 , Linsanity (林氏狂熱) , 就像童話故事灰姑娘。

在他剛加入NBA的時候雖然沒在選秀會上被選中 , 但是還是有和勇士隊簽下了合約 , 在對上湖人的比賽我看到他上場了 , 那時候對他的感覺是一個防守很積極很有活力的球員 , 一上場就有抄截 , 但是他那時還是替補中的替補 , 所以上場的時間很少 , 攻擊和組織球隊的部分他的參與程度很少 , 現在到了尼克隊發光發熱 , 除了他本身的實力和努力之外 , 有時候機運也是造就了一個人能不能發光發熱的因素。

剛好 Mike D'Antoni 的進攻戰術著重在後衛的發動 , 而林書豪的求烽和打球的觀念相當適合教練的進攻體系 , 如魚得水的他大量的取分 , 也透過組織和傳球讓隊友發揮得更出色 , 他也因為這優異的表現獲選為東區單週最佳球員的殊榮。


以下是一些林書豪相關的整理和花絮



    早在一週前,人們就已經通過各種渠道知道了林書豪是躺在其哥哥的一張沙
    發上睡覺的,而且也睡過其隊友蘭德里-菲爾茲(Landry Fields)的沙發。菲爾茲就在早些時候通過推特的方式,秀出這張讓很多人都想看一眼的沙發。這張「沙發」便成為了林書豪曾經困苦時期的見證,也被賦予了神奇的色彩,因為,正是睡過這張沙發,小林才一步登天,瞬間找到了靈感,同時也找到了通往成功的道路。菲爾茲在推特中也開玩笑地聲稱:「女士們和先生們,這就是林書豪所睡過的那張沙發,現在可以開始出價了。 (轉自PTT_NBA 板友 rfr (Mali)的文章)





在菲爾茲公佈這張照片僅僅三個小時以後,瀏覽數就達到了26000,簡直堪稱
是本年度最熱的沙發。



林書豪的HD Games Highlight




2012/02/05 New York Knicks vs New Jersey Nets Jeremy Lin 25 points Highlights
第一場 尼克對籃網 , 他爆發掘起的一場 , 從這場以後他開始先發 , 也帶著尼克走向連勝之旅~~








2012/02/07 New York Knicks vs Utah Jazz Jeremy Lin 28 points Highlights
第二場尼克對爵士 , 這場林書豪打滿下半場有點體力不濟








2012/02/08 New York Knicks vs Washington Wizards Jeremy Lin 23 points Highlights 
第三場尼克對巫師 , 這場的焦點在和去年選秀狀元John wall的對決









2012/02/11 New York Knicks vs Los Angeles Lakers Jeremy Lin 38 points Highlights
第四場尼克對湖人 , 這場的焦點是和Kobe的對決 , 雖然兩人打的位置不同但是媒體還是相當得關注兩人的互動 , 這場林書豪帶領尼克擊敗湖人 , 賽後Kobe對林書豪不禁印象深刻還對讚賞了一番。









2012/02/11 New York Knicks vs Minnesota Timberwolves Jeremy Lin 20 points Highlights
第五場尼克對灰狼 , 這場是和西班牙金童Ricky Rubio的對決 , 下半場灰狼對林書豪採取包夾 , 造成他的命中率下降 , 所幸最後靠著罰球險勝了灰狼。









Lin plays hero for Knicks 2012 02 15 New York Knicks vs Toronto Raptors 
第六場比賽尼克對暴龍 , 堪稱林書豪最精采的一場 , 在最後讀秒階段靠著三分球逆轉了暴龍 , 這場尼克一路落後靠著第四節林書豪帶起的反攻 , 最後90-87擊敗了爆龍 , 林書豪也因為這場比賽打破了歐尼爾的記錄









林書豪真是有英雄命 , 最後致勝的三分球短片 , 關於這個play有個小插曲 , 賽後林書豪表示他轉過頭向教練要求要隊友清開空間給他單打 , 真是心臟大顆的男人 , 最後也靠著這顆三分球擊敗了暴龍啦!!!!!








第七場尼克對國王 , 這場林書豪以策應分球為主 , 也創下生涯新高的13次的助功 , 尼克在第三節結束就以大筆分領先國王 , 所以第四節林書豪沒有上場





2/19尼克對上去年總冠軍小牛 , 林書豪和Jason Kidd的對決受到矚目。







這場對上騎士, 對方控球後衛是今年的選秀狀元, Kyrie Iriving 也是今年新秀對抗賽的MVP




下面分享林書豪和他的好隊友Landry Fields的招牌打氣方式 , 有人說這是"書呆子打氣" , 因為兩人的學歷都相當的高 , 林書豪是哈佛經濟系畢業的 , Landry Fields則是史丹佛大學畢業的 , 堪稱NBA最聰明的後場組合了~












林書豪教你如何進入哈佛 , 搞笑的KUSO影片

















林書豪的狂熱也席捲NBA球員 , 老鷹隊在和魔術隊比賽完畢之後 , 老鷹隊的球員關注著林書豪的表現 , 並在更衣室官看林書豪對灰狼隊的比賽。其他球隊的主力球員,對都關心林書豪的戰況,當他投進今天對暴龍隊的絕殺時,湖人休息室大爆發,World Peace還跑出來大喊「Linsanity」!繼日前對明尼蘇達灰狼用罰球逆轉勝之後,林書豪又連續拿下6分,包括最後一記三分球,把尼克從鬼門關里拉了回來。

除了世界和平之外,許多頂級球星都對這球有極高評價,洛杉磯快艇隊「CP3」保羅
(Chris Paul)在推特上說,「我正在看尼克對暴龍的比賽,林書豪那球真是太巨大啦!」
從尼克隊轉至金州勇士隊的大衛李(David Lee)說,「林書豪那一射棒極了。」


2012年2月12日 星期日

[TQC+ Android] 2-5 圖檔讀取




分別讀取存在/res/drawable資料夾和手機檔案系統 /data/data/COM.TQC.GDD02/png001.PNG 的圖檔後 , 顯示在畫面上 , /res/drawable資料夾內的png002.PNG檔用 setImageResource(R.drawable.png002) 即可 , 而/png001.PNG由於存在手機系統內的資料夾所以使用setImageDrawable(Drawable.createFromPath(filePath)讀取 , 以下是如何載入檔案至/data/data/COM.TQC.GDD02/的方法和程式碼。






請注意紅色框框的部分 , 這是在DDMS視窗下操作的 , 將檔案匯入你程式packageName資料夾裡。


package COM.TQC.GDD02;


import java.io.File;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class GDD02 extends Activity
{
  
  private ImageView mImageView;
  private Button mButton;
  private TextView mTextView;
  private String fileName="/data/data/COM.TQC.GDD02/png001.PNG";
  
  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    
    setContentView(R.layout.main);
    
    mImageView = (ImageView)findViewById(R.id.mImageView);    
    mImageView.setImageResource(R.drawable.png002);
    
    mTextView=(TextView)findViewById(R.id.mTextView);
    
    mButton = (Button)findViewById(R.id.mButton);
    mButton.setOnClickListener(new Button.OnClickListener()
    {
      public void onClick(View v)
      {
     
        File f = new File(fileName);   
        if(f.exists()) //檢查檔案是否存在
        { 
         /* 產生Bitmap物件,並放入mImageView中 */
            Drawable drawable = Drawable.createFromPath(fileName);
         mImageView.setImageDrawable(drawable);
         mTextView.setText(fileName);         
        } 
        else 
        {  
          mTextView.setText("檔案不存在"); 
        } 
      } 
    });
  }
}




再來是單純的Layout檔

    
    
    







P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



[TQC+ Android] 2-4 SQLite 與 MENU 作業 Use SQLiteDatabase , SQLiteOpenHelper , SimpleCursorAdapter





提示使用者按MENU鍵 , 畫面會顯示MENU供使用者新增修改和刪除所選取的List item , 並且我們繼承SQLiteOpenHelper這個類別並override 其中幾個method , 幫助我們管理database和Table的操作 , 以下為程式碼。


package COM.TQC.GDD02;

import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

public class GDD02 extends Activity
{
  private mySQLiteOpenHelper gaaSQLiteOpenHelper;
  private Cursor myCursor;
  private ListView myListView;
  private EditText myEditText;
  private int _id;
  protected final static int MENU_ADD = Menu.FIRST;
  protected final static int MENU_EDIT = Menu.FIRST + 1;
  protected final static int MENU_DELETE = Menu.FIRST + 2;

  @Override
  public boolean onOptionsItemSelected(MenuItem item)
  {
    super.onOptionsItemSelected(item);
    
    switch (item.getItemId())
    {
      case MENU_ADD:
        this.addTodo();
        break;
      case MENU_EDIT:
        this.editTodo();
        break;
      case MENU_DELETE:
        this.deleteTodo();
        break;
    }
    return true;
  }

  @Override
  public boolean onCreateOptionsMenu(Menu menu)
  {
    super.onCreateOptionsMenu(menu);
    
    menu.add(0, MENU_ADD, 1, R.string.strAddButton);
    menu.add(0, MENU_EDIT, 2, R.string.strEditButton);
    menu.add(0, MENU_DELETE, 3, R.string.strDeleteButton);
    
    return true;
  }

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    myListView = (ListView) this.findViewById(R.id.myListView);
    myEditText = (EditText) this.findViewById(R.id.myEditText);

    gaaSQLiteOpenHelper = new mySQLiteOpenHelper(this); 

    updateAdapter();
    
    myListView.setOnItemClickListener(new AdapterView.OnItemClickListener()
    {
      public void onItemClick(AdapterView arg0, View arg1, int postion,
          long rowID)
      {        
        myCursor.moveToPosition(postion);        
        _id = myCursor.getInt(0); // 取出所選物件的rowID
        //_id = (int) rowID;  rowID is the row id of the item that was clicked.
        myEditText.setText(myCursor.getString(1));
        //Log.d("Test", "postion:"+postion+" rowID:"+rowID+" _id:"+_id);
      }
    });
  }

  private void addTodo()
  {   
   gaaSQLiteOpenHelper.insert(myEditText.getText().toString());
   updateAdapter();
   myEditText.setText("");    
  }

  private void editTodo()
  {  
   gaaSQLiteOpenHelper.update(_id, myEditText.getText().toString());
   updateAdapter();
   myEditText.setText(""); 
  }

  private void deleteTodo()
  {
   gaaSQLiteOpenHelper.delete(_id);
   updateAdapter();
   myEditText.setText(""); 
  }
  
  private void updateAdapter()
  {
   myCursor = gaaSQLiteOpenHelper.select();
   SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.list,
          myCursor, new String[]
          {mySQLiteOpenHelper.FIELD_TEXT }, new int[]
          {R.id.listTextView1});
   /*
           使用SimpleCursorAdapter將我們所要的資料顯示在ListView中
     myCursor為我們query的結果 , 他可能有許多row
           而我們只需要顯示其中 FIELD_TEXT欄位的資料
           並且每行row的資料使用 我們事先在R.layout.list中定義好的rowView來顯示
           而FIELD_TEXT這欄資料對應到listTextView1 所定義的方式呈現
    */
   myListView.setAdapter(adapter);
  }
}




接下來是我們繼承SQLiteOpenHelper的類別。

package COM.TQC.GDD02;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class mySQLiteOpenHelper extends SQLiteOpenHelper
{
  private final static String DATABASE_NAME = "todo_db";
  private final static int DATABASE_VERSION = 1;
  private final static String TABLE_NAME = "todo_table";
  public final static String FIELD_id = "_id";
  public final static String FIELD_TEXT = "todo_text";

  public mySQLiteOpenHelper(Context context)
  {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
  }

  @Override
  public void onCreate(SQLiteDatabase db)
  {    
    String sql = "CREATE TABLE " + TABLE_NAME + " (" + FIELD_id
        + " INTEGER primary key autoincrement, " + " " + FIELD_TEXT + " text)";
    db.execSQL(sql);    
  }

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
  {
    String sql = "DROP TABLE IF EXISTS " + TABLE_NAME;
    db.execSQL(sql);
    onCreate(db);
  }

  public Cursor select()
  {
    SQLiteDatabase db = this.getReadableDatabase();
    Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, null);
    //query的結果顯示所有欄位的資料
    return cursor;
  }

  public long insert(String text)
  {
    SQLiteDatabase db = this.getWritableDatabase();
    db.execSQL("INSERT INTO "+TABLE_NAME+" ("+FIELD_TEXT+") values ('"+text+"')");
    Cursor cursor = db.rawQuery("SELECT "+FIELD_id+" FROM "+TABLE_NAME+" WHERE "+FIELD_TEXT+"='"+text+"';", null);
    //rawQuery(String) 為另一種query的方法 , string內容為一般的 SQL語法
    cursor.moveToLast();
    /*
                也許有很多筆結果 , 因為text可能重複 , 但是FIELD_id是不會重複的
                跳置最後一個可以保證是剛剛所Insert的物件
     */
    return  cursor.getInt(0);    
  }

  public void delete(int id)
  {
    SQLiteDatabase db = this.getWritableDatabase();
    
    String where = FIELD_id + " = ?";
    String[] whereValue = { Integer.toString(id) };
    
    db.delete(TABLE_NAME, where, whereValue);
    
    // 或者使用 db.execSQL("DELETE FROM "+TABLE_NAME+" WHERE "+FIELD_id+"="+id);    
  }

  public void update(int id, String text)
  {
    SQLiteDatabase db = this.getWritableDatabase();
    db.execSQL("UPDATE "+TABLE_NAME+" SET "+FIELD_TEXT+"='"+text+"' WHERE "+FIELD_id+"="+id);
  }
}




main.xml


  
    
  
  
  
     




再來是主程式GDD02.java中 , 在updateAdapter()時所用到的R.layout.list也就是 res/layout/list.xml


  
  






P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....

2012年2月11日 星期六

[TQC+ Android] 2-3 匯率換算 Use SharedPreferences





當程式開啟 , 畫面要求使用者輸入匯率與台幣金額 , 輸入完成按下按鈕 , 即可在下方顯示計算結果 , 當下次開啟程式時會顯示上一次所輸入的匯率 , 這題使用 SharedPreferences類別將我們所輸入的資料儲存在 /data/data/package name/SharedPreferences_Name 下 , 記得在onPause()儲存 , onResume()取出就可以了 , 以下是程式碼。


package COM.TQC.GDD02;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class GDD02 extends Activity
{
 public static final String PREF_ExchangeRate = "Exchange_Rate" ;
    
 private Button calcbutton ;
 private EditText fieldExchangeRate ;
 private EditText fieldNTD ;
 private TextView tv;
 
 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {     
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        fieldExchangeRate = (EditText) this.findViewById(R.id.editText1);
        fieldNTD = (EditText) this.findViewById(R.id.editText2);
        tv = (TextView) this.findViewById(R.id.usd_result);
        calcbutton = (Button) this.findViewById(R.id.calc_btn);
        calcbutton.setOnClickListener(BOnClickListener);   
    }
    
    public Button.OnClickListener BOnClickListener = new Button.OnClickListener()
    {
  @Override
  public void onClick(View v)
  {   
   // TODO Auto-generated method stub
      try
      {   double NTD= Double.parseDouble(fieldNTD.getText().toString());
       double ExchangeRate= Double.parseDouble(fieldExchangeRate.getText().toString());
      
          NumberFormat NF = new DecimalFormat(".##");
       tv.setText(getText(R.string.usd_result) + NF.format(NTD / ExchangeRate));
   
      }catch(Exception e)
      {
       e.printStackTrace();
      }
  }     
    };  
    
    public void onResume()
    {
     super.onResume();
     SharedPreferences settings = getSharedPreferences(PREF_ExchangeRate, 0);
     fieldExchangeRate.setText(settings.getString(PREF_ExchangeRate, ""));   
     }
    
    public void onPause()
    {
     super.onPause();
     SharedPreferences settings = getSharedPreferences(PREF_ExchangeRate, 0);
     settings.edit().putString(PREF_ExchangeRate, fieldExchangeRate.getText().toString()).commit();
    }    
}




接下來是 main.xml檔

    
    
        
    
    
    
    


P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....

[TQC+ Android] 2-2 公尺與英呎轉換 Use MenuInflater , onPrepareOptionsMenu





設計一個單位轉換程式 , 在輸入要轉換的數值後 , 按下轉換的按鈕 , 即可在下方顯示轉換後的數值 , 這題有幾個重點 , 關於menu元件的配置 , 不像所使用的方法: [TQC+ Android] 1-5 MENU 功能選單使用 menu.add來加入 , 取而代之的是我們使用res/menu資料夾所提供的menu.xml來配置 , 關鍵的method就是使用 MenuInflater這個類別來處理 , 而題目還提到要在menu出現前先判斷EditText內有沒有內容 , 沒有內容的話就把 menu選單的重設item invisible , 在這邊就要override Activity 下的 boolean onPrepareOptionsMenu (Menu menu) , 另外題目事先宣告了幾個變數 , 但是依照題意卻用不到....以下是程式碼。 


package COM.TQC.GDD02;
/*
題目說明:
英呎 = 公尺 * 3.28
公尺 = 英呎 * 0.3048
*/

import java.text.DecimalFormat;
import java.text.NumberFormat;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;


public class GDD02 extends Activity
{

 protected String PREF_M = "pref_m";
 protected String PREF_FT = "pref_ft";
 protected String pref_m;
 protected String pref_ft;
 
 EditText et;
 TextView tv; 
 Button etom , mtoe;
 NumberFormat NFTwoDigital;
 
 final int RESET = 0;
 
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        et = (EditText) this.findViewById(R.id.editText1);
        tv = (TextView) this.findViewById(R.id.result);
        etom = (Button) this.findViewById(R.id.etom);
        mtoe = (Button) this.findViewById(R.id.mtoe);
        
        etom.setOnClickListener(BOnClickListener);
        mtoe.setOnClickListener(BOnClickListener);         
       
        NFTwoDigital = new DecimalFormat(".00");       
    }
    
    Button.OnClickListener BOnClickListener = new Button.OnClickListener()
    {
  @Override
  public void onClick(View v)
  {
   // TODO Auto-generated method stub
   
   double inputNumber = Double.parseDouble((et.getText().toString()));        
   switch(v.getId())
   {
    case R.id.etom:
     tv.setText(inputNumber+"公尺="+NFTwoDigital.format(inputNumber * 3.28)+"英呎");
    break;
    
    case R.id.mtoe:
     tv.setText(inputNumber+"英呎="+NFTwoDigital.format(inputNumber * 0.3048)+"公尺");    
    break;
   }   
  }     
    };
    
    @Override 
    public boolean onCreateOptionsMenu(Menu menu) 
    {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu, menu);
        
        return true;
    }
    
    @Override 
    public boolean onPrepareOptionsMenu (Menu menu)
    {
  if(et.getText().equals("")) menu.getItem(RESET).setVisible(false);
  else menu.getItem(RESET).setVisible(true);
     return true;     
    }
    
    @Override 
    public boolean onOptionsItemSelected(MenuItem item)
    {        
         ResetValue();
         item.setVisible(false);         
         return true;
    }
    
    private void ResetValue()
    {
     et.setText("");
     tv.setText("");
    } 

}


Layout檔
    
    
        
    
    
    
        


再來是 res/menu/menu.xml

    






P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....

2012年2月10日 星期五

[TQC+ Android] 2-1 猜數字遊戲





輸入三個不重複的數字 , 按下"送出猜測數字"的按鈕 , 即可在下方使用Toast來顯示猜測狀況 , 以下是程式碼。


package COM.TQC.GDD02;


import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;


public class GDD02 extends Activity
{
    /** Called when the activity is first created. */

    Button submit;
    TextView respond;
    EditText input;
    
    int[] num = new int[3];
    int count , a , b;
    String inputString , randomString , wrongString = "輸入錯誤! 請輸入三個不重複的數字";
 
 @Override
    public void onCreate(Bundle savedInstanceState)
 {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        submit = (Button) this.findViewById(R.id.button1);
        respond = (TextView) this.findViewById(R.id.respond) ;
        input = (EditText) this.findViewById(R.id.input);
        
        do
        {
         randomString = String.valueOf((int)(Math.random()*1000));
        }while(!checkNumber(randomString));
        
        submit.setOnClickListener(BOnClickListener);
        
        Log.d("Test", "randomString:"+randomString);
       
    }
 
 public Button.OnClickListener BOnClickListener = new Button.OnClickListener()
 {
  @Override
  public void onClick(View v)
  {
   // TODO Auto-generated method stub
   
   inputString = input.getText().toString();
   if(inputString.length()==3 && checkNumber(inputString))
   {
    if(matchNumber()) showToast("INPUT的數字:"+inputString+"  恭喜你!答對囉~");
    else
    {
     showToast("INPUT的數字:"+inputString+"="+a+"A"+b+"B");
     a=0;
     b=0;
    }
   }
   else
   {
    showToast(wrongString);
    input.setText("");
   }   
  }
  
 };
 
 public boolean checkNumber(String number)
 {
  boolean pass = true;
  
  for(int i=0;i<2;i++)
        {
         for(int j=i+1;j<3;j++)
         {
          if(number.charAt(i)==number.charAt(j))
          {
           pass = false;
          }
         }
        }
  
  return pass;
 }
 
 public boolean matchNumber()
 {
  // TODO Auto-generated method stub
        boolean pass = true;
  
        for(int i=0;i<3;i++)
        {
         for(int j=0;j<3;j++)
         {
          if(inputString.charAt(i)==randomString.charAt(j))
          {
           if(i==j) a++;
           else b++;
          }
         }
        }
        if(a!=3) pass = false;
  return pass;
 }
 
 public void showToast(String Text)
 {
  Toast t = Toast.makeText(GDD02.this, "", Toast.LENGTH_LONG);
  t.setText(Text);
  t.show();
 } 
}


很簡單的Layout



    
    
        
    
    


P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



[TQC+ Android] 1-10 動態密碼顯示 Visible PassWord




此程式欄位包含輸入帳號與輸入密碼的EditText元件 , 以及設定顯示密碼的CheckBox元件 , 輸入帳號的欄位預設只能輸入數字 , 輸入密碼的欄位預設以密碼方式顯示 , 當顯示密碼的CheckBox被勾選後 , 則將所輸入的密碼直接以明碼顯示出來 , 這題藉由更改EditText的inputType屬性來改變PassWord是否可視 , 以下是程式碼。



package COM.TQC.GDD01;

import android.app.Activity;
import android.os.Bundle;
import android.text.InputType;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;

public class GDD01 extends Activity
{  
  EditText et1 , et2;
  CheckBox cb;
 
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    et1 = (EditText) this.findViewById(R.id.mAccount);
    et2 = (EditText) this.findViewById(R.id.mPassword);
    
    cb = (CheckBox) this.findViewById(R.id.mCheck);
    cb.setChecked(false);     
    cb.setOnCheckedChangeListener(OCCListener);
    
  }
  
  public CheckBox.OnCheckedChangeListener OCCListener = new CheckBox.OnCheckedChangeListener()
  {
 @Override
 public void onCheckedChanged(CompoundButton arg0, boolean arg1)
 {
  // TODO Auto-generated method stub
  if(arg0.isChecked()) et2.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
  else et2.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
 }  
  };
}




以下是main.xml

  
  
  







P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



[TQC+ Android] 1-9 AlertDialog 顯示結果





一個簡單的表單 , 內含姓名 , 性別及興趣欄位 , 當使用者填寫完表單內的資料後 , 按下顯示結果按鈕 , 此時程是會收集表單內填寫的資訊 , 已跳出AlertDialg 的方式呈現表單輸入結果 , 這題只是單純的AlertDialog顯示我們選擇的資料 , 以下是程式碼。


package COM.TQC.GDD01;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.RadioButton;

public class GDD01 extends Activity

{
  private EditText et;
  private RadioButton rb1;
  private RadioButton rb2;
  private CheckBox cb1;
  private CheckBox cb2;
  private CheckBox cb3;
  private Button button;
  private AlertDialog.Builder AB;
  private String content;
  
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    et = (EditText) findViewById(R.id.name);
    rb1 = (RadioButton) findViewById(R.id.rButton1);
    rb2 = (RadioButton) findViewById(R.id.rButton2);
    
    cb1 = (CheckBox) findViewById(R.id.cBox1);
    cb2 = (CheckBox) findViewById(R.id.cBox2);
    cb3 = (CheckBox) findViewById(R.id.cBox3);
    
    button = (Button) findViewById(R.id.button1);
    
    AB = new AlertDialog.Builder(this);
    AB.setTitle("結果");
    AB.setPositiveButton("離開", new OnClickListener()
    {
  @Override
  public void onClick(DialogInterface arg0, int arg1)
  {
   // TODO Auto-generated method stub
   // 作用為關閉AlertDialog  
  }     
    }
    );
        
    button.setOnClickListener(new Button.OnClickListener()
    {
      @Override
      public void onClick(View v)
      { 
         if(et.getText().toString().trim().length()==0) content = "姓名:未填\n";
         //防止使用者鍵入空白 , 考試時使用 getText().equals("") 即可
         else content = "姓名:"+et.getText()+"\n";
      
         if(rb1.isChecked()) content+="性別:帥哥\n興趣:";
         else content+="性別:美女\n興趣:";
         
         if(cb1.isChecked()==false&&cb2.isChecked()==false&&cb3.isChecked()==false)
          content+="未選擇";
         else
         {
          if(cb1.isChecked()) content+="吃飯 ";
             if(cb2.isChecked()) content+="睡覺 ";
             if(cb3.isChecked()) content+="上網 ";
         }         
         AB.setMessage(content).show();
      }
    });
  }
}

以下是 main.xml

  
    
      
      
    
    
      
      
        
        
      
    
    
      
      
        
        
        
      
    
  
  






P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



2012年2月7日 星期二

[TQC+ Android] 1-8 選擇手機型號 Use Spinner






將Spinner元件預設為"請選擇" , 當選擇了某一手機型號時 , 將此型號接續顯示於"選擇手機型號"的TextView中 , 如選取的選項惟請選擇時(即不選擇任何型號) , TextView後方步顯示任何文字 , 一般來說在設定下拉選單的呈現樣式 , 我們都是使用Android 提供的 , 就像下面那行程式碼 setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) , 而這題要求我們使用自製的TextView去替換 , 其實Android所提供的 android.R.layout.simple_spinner_dropdown_item , 裡面放的就是一個TextView , 而自製的TextView題目也做好了存放在res/layout/myspinner_layout , 以下是程式碼。


package COM.TQC.GDD01;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;

public class GDD01 extends Activity
{
  private String[] types={"請選擇","HTC HERO","HTC MAGIC","HTC TATTOO",
      "NEXUS ONE","SONY X10","MOTO MILESTONE"};
  
  Spinner spinner; 
  TextView textView;
  
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    textView = (TextView) this.findViewById(R.id.text1);
    
    ArrayAdapter AB = new ArrayAdapter(this, android.R.layout.simple_spinner_item, types);
    AB.setDropDownViewResource(R.layout.myspinner_layout);
       
    spinner = (Spinner) this.findViewById(R.id.mySpinner);    
    spinner.setAdapter(AB);   
    spinner.setOnItemSelectedListener(SOnItemSelectedListener);    
  }
  
  public Spinner.OnItemSelectedListener SOnItemSelectedListener = new Spinner.OnItemSelectedListener()
  {
 @Override
 public void onItemSelected(AdapterView arg0, View arg1, int arg2,
   long arg3)
 {
  // TODO Auto-generated method stub
  if(arg2 == 0) textView.setText(getText(R.string.str1));
  
  else textView.setText(getText(R.string.str1)+types[arg2]);
 }

 @Override
 public void onNothingSelected(AdapterView arg0)
 {
  // TODO Auto-generated method stub  
 }   
  };  
}


main.xml

  
  


myspinner_layout.xml











P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



2012年2月6日 星期一

[TQC+ Android] 1-7 驗證 Activity Use Log





程式內有兩個Activity , 於Activity1按下按鈕"Go To Activity2" 時 , Activity 會被開啟 , 點選Activty2的Back to Activity1按鈕時 , 則會將Activity2關閉 , 同時回傳訊息 , 而題目希望透過Log來驗證Activity的生命週期 , 這題用意在測驗考生清不清楚 Activity Lifecycle , 如果清楚的話這題是相當簡單的 , 再配合Log顯示Activity的當前狀態即可 , 另外兩個Activity之間的資料往返 , 在記得要在AndroidManifest.xml 宣告另一支Activity , 以下是程式碼。


package COM.TQC.GDD01;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class GDD01 extends Activity
{
  private static final String TAG = "Android_Log";
  private TextView tv;
  private Button b1;
  private Button b2;
  
  final int ACT1 = 1;
  private Intent intent;
  
  @Override
  public void onCreate(Bundle savedInstanceState)
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    tv=(TextView) findViewById(R.id.text1);;
    b1 = (Button) findViewById(R.id.button1);
    b2 = (Button) findViewById(R.id.button2);
    
    intent = new Intent();
    intent.setClass(this, GDD1_2.class);
    
    b1.setOnClickListener(new Button.OnClickListener()
    {
      public void onClick(View v)
      {
       startActivityForResult(intent,ACT1);
      }      
    });
    
    b2.setOnClickListener(new Button.OnClickListener()
    {
      public void onClick(View v)
      {
       finish();
      }
    });    
    Log.i(TAG, "onCreate()");    
  }
  
  @Override
  public void onActivityResult (int requestCode, int resultCode, Intent data)
  {
   tv.setText(""+resultCode);
  }  
  
  @Override
  public void onStart()
  {
    super.onStart();
    Log.i(TAG, "onStart()");
  }
  @Override
  public void onResume()
  {
    super.onResume();
    Log.i(TAG, "onResume()");
  }
  @Override
  public void onPause()
  {
    super.onPause();
    Log.i(TAG, "onPause()");
  }
  @Override
  public void onStop()
  {
    super.onStop();
    Log.i(TAG, "onStop()");
  }
  @Override
  public void onRestart()
  {
    super.onRestart();
    Log.i(TAG, "onRestart()");
  }
  @Override
  public void onDestroy()
  {
    super.onDestroy();
    Log.i(TAG, "onDestroy()");
  }
}

package COM.TQC.GDD01;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;


public class GDD1_2 extends Activity
{ 
 Button backButton;
 
 @Override
 public void onCreate(Bundle savedInstanceState)
 {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.mylayout);
     
     backButton = (Button) findViewById(R.id.button2);
     backButton.setOnClickListener(new Button.OnClickListener()
     {
       public void onClick(View v)
       {
        GDD1_2.this.setResult(99);
        finish();
       }
     });     
 }  
}


接下來是簡單的Layout



    


    




不要忘記AndroidManifest.xml 的宣告

    
        
            
                
                
            
        
        

    
    
 







P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....

[TQC+ Android] 1-6 畫廊展示 Use Gallery





可藉由游標的左右移動瀏覽照片 , 並顯示照片資料 , 這題使用到的類別 Gallery 和 Toast提示 , 另外這題所提供了10張png檔 , 而程式安裝到模擬器時會發現10張圖檔要上傳很久 , 所以我只使用6張png 以下是程式碼。


package COM.TQC.GDD01;

import android.app.Activity;
import android.os.Bundle;
import android.content.Context;
import android.content.res.TypedArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.Toast;


public class GDD01 extends Activity 
{
  
  Gallery gallery;
  int[] drawableResID = {R.drawable.png001 , R.drawable.png002 , R.drawable.png003
                   , R.drawable.png004 , R.drawable.png005 , R.drawable.png006};
    
  @Override  
  
  public void onCreate(Bundle savedInstanceState) 
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    gallery = (Gallery) this.findViewById(R.id.mygallery);
    
    ImageAdapter imageAadapter = new ImageAdapter(this);
    
    gallery.setAdapter(imageAadapter);
    gallery.setOnItemSelectedListener(OISlistener);
  }
  
  Gallery.OnItemSelectedListener OISlistener = new Gallery.OnItemSelectedListener()
  {
 @Override
 public void onItemSelected(AdapterView arg0, View arg1, int arg2,
   long arg3)
 {
  Toast t = Toast.makeText(GDD01.this, getText(R.string.my_gallery_text_pre).toString() 
    + arg2 + getText(R.string.my_gallery_text_post).toString(), Toast.LENGTH_SHORT);
     t.show();
  
 }

 @Override
 public void onNothingSelected(AdapterView arg0) {
  // TODO Auto-generated method stub
  
 }
    
  };
  
  public class ImageAdapter extends BaseAdapter 
  {   
 int backgroundID;
   
   //建構子只有一個參數,即要儲存的Context
   public ImageAdapter(Context c) 
    {
    TypedArray arr = c.obtainStyledAttributes(R.styleable.Gallery);
    backgroundID = arr.getResourceId(R.styleable.Gallery_android_galleryItemBackground , 0);
    arr.recycle();
 }     
  
   //回傳所有已定義的圖片總數量
   public int getCount() 
   {
    return drawableResID.length;
   }  
  
   public Object getItem(int position) 
   {
    return drawableResID[position];
   }
  
   //取得圖片編號
   public long getItemId(int position) 
   {
    return position;
   }

   @Override
   public View getView(int arg0, View arg1, ViewGroup arg2)
   {
    // TODO Auto-generated method stub
    ImageView imageView = new ImageView(GDD01.this);
    imageView.setImageResource(drawableResID[arg0]);
    imageView.setBackgroundResource(backgroundID);
    imageView.setScaleType(ScaleType.FIT_XY);
    imageView.setLayoutParams(new Gallery.LayoutParams(236,188));
    return imageView;
   }
  
  }  
    
    //使用android.R.drawable裡的圖片當成圖庫來源
}


這題的Layout也很單純 , 只要擺一個Gallery就可以了。




由於Gallery元件不支援循環播放 , 所以如果要讓圖片一直循環下去的話 , 我們要自己動手實作 , 以下是程式碼。


package COM.TQC.GDD01;

import android.app.Activity;
import android.os.Bundle;
import android.content.Context;
import android.content.res.TypedArray;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.Toast;


public class GDD01 extends Activity 
{
  
  Gallery gallery;
  int[] drawableResID = {R.drawable.png001 , R.drawable.png002 , R.drawable.png003
                   , R.drawable.png004 , R.drawable.png005 , R.drawable.png006};
    
  @Override  
  
  public void onCreate(Bundle savedInstanceState) 
  {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    
    gallery = (Gallery) this.findViewById(R.id.mygallery);
    
    ImageAdapter imageAadapter = new ImageAdapter(this);
    
    gallery.setAdapter(imageAadapter);
    gallery.setOnItemSelectedListener(OISlistener);
  }
  
  Gallery.OnItemSelectedListener OISlistener = new Gallery.OnItemSelectedListener()
  {
 @Override
 public void onItemSelected(AdapterView arg0, View arg1, int arg2,
   long arg3)
 {
  Toast t = Toast.makeText(GDD01.this, getText(R.string.my_gallery_text_pre).toString() 
    + arg2 % drawableResID.length + getText(R.string.my_gallery_text_post).toString(), Toast.LENGTH_SHORT);
     t.show();
  
 }

 @Override
 public void onNothingSelected(AdapterView arg0) {
  // TODO Auto-generated method stub
  
 }
    
  };
  
  public class ImageAdapter extends BaseAdapter 
  {   
 int backgroundID;
   
   //建構子只有一個參數,即要儲存的Context
   public ImageAdapter(Context c) 
    {
    TypedArray arr = c.obtainStyledAttributes(R.styleable.Gallery);
    backgroundID = arr.getResourceId(R.styleable.Gallery_android_galleryItemBackground , 0);
    arr.recycle();
 }     
  
   //回傳所有已定義的圖片總數量
   public int getCount() 
   {
    return Integer.MAX_VALUE;
    
    //設定圖片數量為系統最大整數
   }  
  
   public Object getItem(int position) 
   {
    return drawableResID[position % drawableResID.length];
   }
  
   //取得圖片編號
   public long getItemId(int position) 
   {
    return position % drawableResID.length;
   }

   @Override
   public View getView(int arg0, View arg1, ViewGroup arg2)
   {
    // TODO Auto-generated method stub
    ImageView imageView = new ImageView(GDD01.this);
    imageView.setImageResource(drawableResID[arg0 % drawableResID.length]);
    imageView.setBackgroundResource(backgroundID);
    imageView.setScaleType(ScaleType.FIT_XY);
    imageView.setLayoutParams(new Gallery.LayoutParams(236,188));
    return imageView;
   }
  
  }  
    
    //使用android.R.drawable裡的圖片當成圖庫來源
}



P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....

2012年2月5日 星期日

[TQC+ Android] 1-5 MENU 功能選單





使用者按MENU按鈕 , 顯示MENU選單 , 這題也相當簡單 , 只是要考在menu加上items的使用和AlertDialog的設定按鈕及事件 , 以下是程式碼。




package COM.TQC.GDD01;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;

public class GDD01 extends Activity {
 
 
 final int ADD = Menu.FIRST , DELETE = Menu.FIRST+1 , 
           ABOUT = Menu.FIRST+2 , QUIT = Menu.FIRST+3 ;
 // ...
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
    @Override
    //建立menu選單的項目
    public boolean onCreateOptionsMenu(Menu menu)
    {
     super.onCreateOptionsMenu(menu);
     
     //新增menu選單,再利用onOptionsItemSelected擷取選單選擇項目,處理相對應的事件
     menu.add(0, ADD, 0, R.string.menu_add);
     menu.add(0, DELETE, 1, R.string.menu_delete);
     menu.add(0, ABOUT, 2, R.string.menu_about);
     menu.add(0, QUIT, 3, R.string.menu_exit);
          
     return true ; 
    }
    //menu被選擇執行後的事件處理
    public boolean onOptionsItemSelected(MenuItem item)
    {
     //點選menu,出現四個選擇,以switch區分點選何項,設定title並繫結至其功能
     switch(item.getItemId())
     {
        case ADD:
        case DELETE:
         this.setTitle(item.getTitle());
         break;
        case ABOUT:
         openAboutDialog();
         break;
        case QUIT:
         openExitDialog();
         break;      
     }
     return super.onOptionsItemSelected(item) ;
    }
    
    //點選「關於」功能
    public void openAboutDialog()
    {     
     AlertDialog.Builder AB = new AlertDialog.Builder(this);
     AB.setMessage(R.string.menu_about_msg)
     .setTitle(R.string.menu_about)
     .setPositiveButton(R.string.str_ok, 
        new OnClickListener()
     {
   @Override
   public void onClick(DialogInterface dialog, int which)
   {
    // TODO Auto-generated method stub
    // 按下確認後會關閉Dialog即可
   }          
     }     
     )
     .show();
    }
    //點選「離開」功能
    public void openExitDialog()
    {
        //開啟視窗詢問【是否確認離開系統?】,於訊息視窗點選「確認」後,關閉程式
     //於訊息視窗點選「取消」,則關閉此詢問視窗,則回到MENU功能選單畫面
     
     AlertDialog.Builder AB = new AlertDialog.Builder(this);
     AB.setMessage(R.string.menu_exit_msg)
     .setTitle(R.string.menu_exit)
     .setPositiveButton(this.getText(R.string.str_ok), 
        new OnClickListener()
     {
   @Override
   public void onClick(DialogInterface dialog, int which)
   {
    // TODO Auto-generated method stub
    GDD01.this.finish();
   }          
     }     
     )
     .setNegativeButton(this.getText(R.string.str_cancel), 
        new OnClickListener()
     {
   @Override
   public void onClick(DialogInterface dialog, int which)
   {
    // TODO Auto-generated method stub
    // 取消關閉程式
   }          
     }     
     )
     .show();    
    }
}


這題不用額外配置layout , 所以不附上main.xml







P.S. 題目中所要求的Variable和Method皆會保留 , 也會根據題目所要求的流程去實作 , 縱使題目要求繞遠路....



Google Analytics