分類
Uncategorized

如何製作上鎖功能(EditText + SharedPreferences)

上鎖功能相當簡單,基本上只需要 EditText 和 SharedPreferences(也可以使用其它的儲存類別如 fileoutputstream,SQLite) 就能完成,,不過為了操作的方便,我還加上了 button 和 textview ,基本介面如下
開鎖畫面

 
 
 
 
 
 
 
 
 
 
輸入密碼畫面

 
 
 
 
 
 
 
 
 
 
 
而實作原理也相當簡單,為了不把主流程複雜化,我把解鎖(UnLock_Flow.java)和加鎖(Lock_Flow.java)分開成2個類別,首先在主流程開始前先判斷是否有密碼鎖,有就先進解鎖,沒有就直接開始主流程,而在主流程中會有個選項是加入密碼鎖的選擇,點選進入 Lock_Flow.java,相當簡單吧
首先在主流程中判斷的方法如下

      void lock() {
          // get data for accountdetail
          SharedPreferences sp = getSharedPreferences("bcn", 0);
   
          // get accountdetail count
          String passstr = sp.getString("adlock", "");
          // no lock
          if(passstr.equals("")){
          }
          //lock exist
          else {
          //call Lock_Flow
              Intent inte = new Intent();
              inte.setClass(All_List.this, UnLock_Flow.class);
              startActivityForResult(inte, 3);
              overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit);
          }
      }

其中 SharedPreferences 的用法請參考這篇,本篇不再多加詳述
第 9 行判斷內容是否為空,是的話代表沒有密碼鎖直接進入主流程,否的話就呼叫解鎖類別(16 ~ 20 行)
解鎖類別(UnLock_Flow.java)如下

  package com.example.helloworld;
   
  import FoXxLib.FP;
  import android.annotation.SuppressLint;
  import android.app.Activity;
  import android.app.AlertDialog;
  import android.content.DialogInterface;
  import android.content.SharedPreferences;
  import android.os.Bundle;
  import android.view.KeyEvent;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.widget.Button;
  import android.widget.EditText;
  import android.widget.TextView;
  import android.widget.Toast;
   
  @SuppressLint("NewApi")
  public class UnLock_Flow extends Activity {
   
      EditText et;
      Button byes;
      Button bno;
   
      TextView tv;
   
      int tryNum = 2;
   
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
   
          initXml();
   
      }
   
      void initXml() {
          setContentView(R.layout.unlockflow);
   
          tv = (TextView) findViewById(R.id.textView1);
   
          tv.setText("請輸入密碼解鎖");
   
          et = (EditText) findViewById(R.id.username_edit);
          et.setHint("輸入密碼");
   
          byes = (Button) findViewById(R.id.buttonYes);
          byes.setOnClickListener(new OnClickListener() {
   
              @Override
              public void onClick(View v) {
                  // TODO Auto-generated method stub
   
                  checkPassWord();
              }
          });
   
          bno = (Button) findViewById(R.id.buttonNo);
          bno.setOnClickListener(new OnClickListener() {
   
              @Override
              public void onClick(View v) {
                  // TODO Auto-generated method stub
   
                  // use AlertDialog
                  AlertDialog ad = new AlertDialog.Builder(UnLock_Flow.this,
                          AlertDialog.THEME_TRADITIONAL).create();
                  ad.setTitle("警告!!");// 設定警告標題
                  ad.setMessage("確定離開程序??");
   
                  ad.setButton2("確定", new DialogInterface.OnClickListener() {// 設定按鈕2
   
                              @Override
                              public void onClick(DialogInterface dialog,
                                      int which) {
   
                                  // 點選按鈕2後執行的動作
                                  finishEdit(1);
                              }
                          });
                  ad.setButton("取消", new DialogInterface.OnClickListener() {// 設定按鈕2
   
                              @Override
                              public void onClick(DialogInterface dialog,
                                      int which) {
   
                                  // 點選按鈕2後執行的動作
   
                              }
                          });
   
                  ad.setCanceledOnTouchOutside(true);// 當警告提示出現後,點選提示以外範圍,是否會取消提示,預設是true
   
                  ad.setCancelable(true);// 當警告提示出現後,點選其他實體按鈕(backkey等等),是否會取消提示,預設是true
   
                  ad.show();
   
              }
          });
      }
   
      void checkPassWord() {
   
          if (et.getText() == null) {
              // use Toast
              tryNum--;
              Toast.makeText(UnLock_Flow.this, "未輸入密碼!!!" + "還剩" + tryNum + "次",
                      Toast.LENGTH_SHORT).show();
   
              et.setText("");
          } else {
   
              String tempstr = et.getText().toString();
   
              // get data for accountdetail
              SharedPreferences sp = getSharedPreferences("bcn", 0);
   
              // get accountdetail count
              String passstr = sp.getString("adlock", "");
   
              if (tempstr.equals(passstr)) {
                  Toast.makeText(UnLock_Flow.this, "密碼正確!!!", Toast.LENGTH_SHORT)
                          .show();
                  finishEdit(0);
              } else {
                  Toast.makeText(UnLock_Flow.this,
                          "密碼錯誤!!!" + "還剩" + tryNum + "次", Toast.LENGTH_SHORT)
                          .show();
                  tryNum--;
              }
   
          }
   
          if (tryNum < 0) {
   
              finishEdit(1);
          }
      }
   
      public boolean onKeyDown(int keycode, KeyEvent event) {
   
          FP.p("keycode:" + keycode);
          FP.p("event:" + event.getAction());
   
          finishEdit(1);
   
          switch (keycode) {
   
          // menu key
          case 82:
   
              break;
          }
   
          return super.onKeyDown(keycode, event);
      }
   
      /**
       *
       * @param result
       *            0 ok
       */
      void finishEdit(int result) {
   
          if (result == 0) {
              UnLock_Flow.this.setResult(0);
   
              UnLock_Flow.this.finish();
   
              overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit);
          } else if (result == 1) {
   
              UnLock_Flow.this.setResult(1);
   
              UnLock_Flow.this.finish();
   
          }
      }
   
  }

其中比較重要的為 101 行的 checkPassWord() 方法,會取得 在 et 中輸入的字串內容並與 passstr 字串做比較(120行),相同則解鎖成功(finishEdit(0)),失敗則嘗試次數減少,當嘗試次數減為 0 ,那麼會直接回到主程序再結束 (finishEdit(1))

以上是解鎖的部分,接下來是上鎖的部分,在主程序中會有個按鈕,用來觸發加鎖動作,如下

//call Lock_Flow
Intent inte = new Intent();
inte.setClass(All_List.this, Lock_Flow.class);
startActivityForResult(inte, 4);
overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit);

接著是 Lock_Flow.java的內容,必須注意在沒有上鎖的情況下,可以直接設定密碼,完成上鎖,但相反的若已經有上鎖過,則必須先輸入原先的密碼以解鎖,再上鎖,如下

  package com.example.helloworld;
   
  import FoXxLib.FP;
  import android.annotation.SuppressLint;
  import android.app.Activity;
  import android.app.AlertDialog;
  import android.content.DialogInterface;
  import android.content.SharedPreferences;
  import android.os.Bundle;
  import android.view.KeyEvent;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.widget.Button;
  import android.widget.EditText;
  import android.widget.TextView;
  import android.widget.Toast;
   
  @SuppressLint("NewApi")
  public class Lock_Flow extends Activity{
   
      EditText et;
      Button byes;
      Button bno;
      TextView tv;
      int tryNum =2;
      //0:lock exist 1:no lock
      int flow =0;
      public void onCreate(Bundle savedInstanceState){
          super.onCreate(savedInstanceState);
          initXml();
      }
      void initXml(){
          setContentView(R.layout.lockflow);
          tv = (TextView)findViewById(R.id.textView1);
          // get data for accountdetail
          SharedPreferences sp = getSharedPreferences("bcn", 0);
   
          // get accountdetail count
          String passstr = sp.getString("adlock", "");
          //no lock
          if(passstr.equals("")){
              flow =1;
              tv.setText("請輸入密碼:");
          }
          //lock exist
          else{
              flow =0;
              tv.setText("請輸入原始密碼:");
          }
          et = (EditText)findViewById(R.id.username_edit);
          et.setHint("輸入密碼");
          byes = (Button)findViewById(R.id.buttonYes);
          byes.setOnClickListener(new OnClickListener() {
              @Override
              public void onClick(View v) {
                  // TODO Auto-generated method stub
                  checkPassWord();
              }
          });
          bno = (Button)findViewById(R.id.buttonNo);
          bno.setOnClickListener(new OnClickListener() {
              @Override
              public void onClick(View v) {
                  // TODO Auto-generated method stub
                  //use AlertDialog
                  AlertDialog ad = new AlertDialog.Builder(Lock_Flow.this,AlertDialog.THEME_TRADITIONAL).create();
                  ad.setTitle("警告!!");//設定警告標題
                  ad.setMessage("未上鎖,確定返回程序??");
                  ad.setButton2("確定", new DialogInterface.OnClickListener() {// 設定按鈕2
   
                              @Override
                              public void onClick(DialogInterface dialog, int which) {
   
                                  // 點選按鈕2後執行的動作
                                  finishEdit(1);
                              }
                          });
                  ad.setButton("取消", new DialogInterface.OnClickListener() {// 設定按鈕2
   
                      @Override
                      public void onClick(DialogInterface dialog, int which) {
   
                          // 點選按鈕2後執行的動作
                      }
                  });
                  ad.setCanceledOnTouchOutside(true);//當警告提示出現後,點選提示以外範圍,是否會取消提示,預設是true
                  ad.setCancelable(true);//當警告提示出現後,點選其他實體按鈕(backkey等等),是否會取消提示,預設是true
                  ad.show();
              }
          });
      }
      void checkPassWord(){
          if(flow==0){
              if(et.getText().toString().equals("")){
                  // use Toast
                  Toast.makeText(Lock_Flow.this, "未輸入密碼!!!"+"還剩"+tryNum+"次",Toast.LENGTH_SHORT).show();
                  tryNum--;
                  et.setText("");
              }
              else{
                  String tempstr = et.getText().toString();
                  // get data for accountdetail
                  SharedPreferences sp = getSharedPreferences("bcn", 0);
   
                  // get accountdetail count
                  String passstr = sp.getString("adlock","");
                  if(tempstr.equals(passstr)){
                      Toast.makeText(Lock_Flow.this, "密碼正確!!!",Toast.LENGTH_SHORT).show();
                      flow =1;
                      tv.setText("輸入新密碼:");
                  }
                  else{
                      Toast.makeText(Lock_Flow.this, "密碼錯誤!!!"+"還剩"+tryNum+"次",Toast.LENGTH_SHORT).show();
                      tryNum--;
                  }
              }
              if(tryNum<0){
                  //use AlertDialog
                  AlertDialog ad = new AlertDialog.Builder(Lock_Flow.this,AlertDialog.THEME_TRADITIONAL).create();
                  ad.setTitle("更改密碼失敗!!");//設定警告標題
                  ad.setMessage("原始密碼不正確");
                  ad.setButton("返回", new DialogInterface.OnClickListener() {// 設定按鈕2
   
                      @Override
                      public void onClick(DialogInterface dialog, int which) {
                          finishEdit(0);
                      }
                  });
                  ad.setCanceledOnTouchOutside(false);//當警告提示出現後,點選提示以外範圍,是否會取消提示,預設是true
                  ad.setCancelable(false);//當警告提示出現後,點選其他實體按鈕(backkey等等),是否會取消提示,預設是true
                  ad.show();
              }
          }
          else if(flow==1){
              if(et.getText().toString().equals("")){
                  // use Toast
                  Toast.makeText(Lock_Flow.this, "未輸入密碼!!!",Toast.LENGTH_SHORT).show();
                  et.setText("");
              }
              else{
                  String tempstr = et.getText().toString();
                  // get data for accountdetail
                  SharedPreferences sp = getSharedPreferences("bcn", 0);
                  SharedPreferences.Editor spe = sp.edit();
                  spe.putString("adlock", tempstr);// for more putXXX
                  spe.commit();
   
                  //use AlertDialog
                  AlertDialog ad = new AlertDialog.Builder(Lock_Flow.this,AlertDialog.THEME_TRADITIONAL).create();
                  ad.setTitle("上鎖完成!!");//設定警告標題
                  ad.setMessage("密碼為"+tempstr);
                  ad.setButton("返回", new DialogInterface.OnClickListener() {// 設定按鈕2
   
                      @Override
                      public void onClick(DialogInterface dialog, int which) {
                          finishEdit(1);
                      }
                  });
                  ad.setCanceledOnTouchOutside(false);//當警告提示出現後,點選提示以外範圍,是否會取消提示,預設是true
                  ad.setCancelable(false);//當警告提示出現後,點選其他實體按鈕(backkey等等),是否會取消提示,預設是true
                  ad.show();
              }
          }
      }
      public boolean onKeyDown(int keycode, KeyEvent event){
          FP.p("keycode:"+keycode);
          FP.p("event:"+event.getAction());
          finishEdit(1);
          switch(keycode){
          // menu key
          case 82:
              break;
          }
          return super.onKeyDown(keycode, event);
      }
      /**
       *
       * @param result 0 ok
       */
      void finishEdit(int result){
          if(result==0){
              Lock_Flow.this.setResult(0);
              Lock_Flow.this.finish();
              overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit);
          }
          else if(result==1){
              Lock_Flow.this.setResult(1);
              Lock_Flow.this.finish();
              overridePendingTransition(R.anim.zoom_enter, R.anim.zoom_exit);
          }
      }
  }

 

第 30 行 flow=0代表已經有鎖, 必須先解鎖,而flow=1,代表沒有鎖,可以直接輸入密碼上鎖
結果為

分類
Uncategorized

排序比較的實用(Comparable & Comparator )

在 Collections 有許多排序比較等等的方法已經寫好,基本類型的比較可以直接使用,如

    ArrayList al = new ArrayList();
    for(int i=0; i<10; i++){
        Random r = new Random();
        al.add(r.nextInt(1000));
    }
    Collections.sort(al);

在 al 中的元素將會由小到大排好,但是如果 al 中的元素並不是基本類型,而是自創類別,而想比較的是自創類別中的某個屬性值,那麼可以實作 Comparable 介面,再覆寫 compareTo 方法,如下

  package com.example.helloworld;
   
  import java.util.Comparator;
   
  public class AccountDetail implements Comparable<Object>{
   
      static int dataCount;
      public String time;
      public String money;
      public String remark;
      public AccountDetail(){
          dataCount++;
          time = "0000/00/00";
          money = "0";
          remark = "0";
      }
      public AccountDetail(String time,String money,String type){
          dataCount++;
          this.time = time;
          this.money = money;
          this.remark = type;
      }
   
      @Override
      public int compareTo(Object another) {
          AccountDetail adAnother = (AccountDetail)another;
          if(Integer.valueOf(this.money)>Integer.valueOf(adAnother.money))
          {
              return 1;// move element back
          }
          else if(Integer.valueOf(this.money)<Integer.valueOf(adAnother.money)){
              return -1;//move element forward
          }
          else{
              return 0;
          }
      }
  }
   

AccountDetail 裡面有 3 個屬性,分別為 time , money , remark , 在第 5 行實作 Comparable 介面, 接著第 27 行覆寫 compareTo 方法, 方法裡面就寫出自訂的比較規則, 只要注意回傳值,1 代表往前排, -1 代表往後排,這段程式碼就代表比較 money 並由小排到大,最後使用的方式如下

          ArrayList<AccountDetail> al = new ArrayList<AccountDetail>();
                
               for(int i=0; i<10 ;i++){
              Random r = new Random();
              al.add(new AccountDetail("testtime",""+r.nextInt(1000)+i,"testremark"));
          }
          Collections.sort(al);

 

第 1 ~ 6 行建立 ArrayList al, 最後第 8 行排序,就這麼簡單,不過使用 Comparable 介面的缺點是只能使用單種排序,如果還想針對 time , remark 做排序,可以使用 Comparator 介面,好處除了可對多種數值做排序外,也不必綁定在 AccountDetail 類別中,你可以把它封裝出來(不過我還是寫在一起)

  package com.example.helloworld;
  import java.util.Comparator;
  import FoXxLib.FP;
  public class AccountDetail
  {
      static int dataCount;
      public String time;
      public String money;
      public String remark;
      public AccountDetail(){
          dataCount++;
          time = "0000/00/00";
          money = "0";
          remark = "0";
      }
      public AccountDetail(String time,String money,String type){
          dataCount++;
          this.time = time;
          this.money = money;
          this.remark = type;
      }
      public MoneyComparator moneyComp(){
          MoneyComparator mc = new MoneyComparator();
          return mc;
      }
      public TimeComparator timeComp(){
          TimeComparator tc = new TimeComparator();
          return tc;
      }
  }
  class MoneyComparator implements Comparator<Object>{
      @Override
      public int compare(Object lhs, Object rhs) {
          AccountDetail ad1 = (AccountDetail)lhs;
          AccountDetail ad2 = (AccountDetail)rhs;
          if(Integer.valueOf(ad1.money)>Integer.valueOf(ad2.money)){
              return 1;
          }
          else if(Integer.valueOf(ad1.money)<Integer.valueOf(ad2.money)){
              return -1;
          }
          else{
              return 0;
          }
      }
  }
  class TimeComparator implements Comparator<Object>{
      @Override
      public int compare(Object lhs, Object rhs) {
          int tempReturn =0;
          AccountDetail ad1 = (AccountDetail)lhs;
          AccountDetail ad2 = (AccountDetail)rhs;
          String[] tempstr1 = ad1.time.split("[/]");
          int[] tempint1 = new int[tempstr1.length];
          for(int i=0; i<tempstr1.length; i++){
              tempint1[i] = Integer.valueOf(tempstr1[i]);
          }
          String[] tempstr2 = ad2.time.split("[/]");
          int[] tempint2 = new int[tempstr2.length];
          for(int i=0; i<tempstr2.length; i++){
              tempint2[i] = Integer.valueOf(tempstr2[i]);
          }
          for(int i=0; i<tempint1.length; i++){
              if(tempint1[i]>tempint2[i]){
                  tempReturn = -1;
                  break;
              }
              else if(tempint1[i]<tempint2[i]){
                  tempReturn = 1;
                  break;
              }
              else if(tempint1[i]==tempint2[i])
              {
                  tempReturn =0;
              }
          }
              return tempReturn;
      }
  }

 

先把原先使用 Comparator 介面 的部分註解掉(第 8 行, 第 30 ~ 49 行)
第 51 ~ 56 行建立並回傳 money 的比較器
第 58 ~ 63 行建立並回傳 time 的比較器
第 66 ~ 84 行為 money 比較器的定義, 先實作 Comparator 介面
第 69 行覆寫 compare 方法, lhs 和 rhs 各為比較的物件,至於 compare 的內容就自己定義了
第 86 ~ 129 行為 time 比較器的定義,由於 time 包含了年月日,必須先切割字串,再放入陣列中等待比較,第 109 ~ 123 行為比較的方法
最後使用的方式如下

Collections.sort(al, al.get(0).timeComp());

第 1 個參數為比較的內容,第 2 個參數為比較器, timeComp 會回傳 time 比較器,當然你也可以改為 al.get(0).moneyComp() , 來比較 money
注意事項:
1.如果使用 Comparator 介面,且和要比較的容器類別綁在一起(就是上述的 AccountDetail.java),必須注意當沒有產生任何元素,還要排序時,會出現錯誤,所以排序類別還是拆開比較好如下

 package com.example.helloworld;
  import java.util.Comparator;
  public abstract class AD_Sort implements Comparator<Object>{
  }
  class MoneyComparator extends AD_Sort{
      @Override
      public int compare(Object lhs, Object rhs) {
          AccountDetail ad1 = (AccountDetail)lhs;
          AccountDetail ad2 = (AccountDetail)rhs;
          if(Integer.valueOf(ad1.money)>Integer.valueOf(ad2.money)){
              return -1;
          }
          else if(Integer.valueOf(ad1.money)<Integer.valueOf(ad2.money)){
              return 1;
          }
          else{
              return 0;
          }
      }
  }
  class TimeComparator extends AD_Sort{
      @Override
      public int compare(Object lhs, Object rhs) {
          int tempReturn =0;
          AccountDetail ad1 = (AccountDetail)lhs;
          AccountDetail ad2 = (AccountDetail)rhs;
          String[] tempstr1 = ad1.time.split("[/]");
          int[] tempint1 = new int[tempstr1.length];
          for(int i=0; i<tempstr1.length; i++){
              tempint1[i] = Integer.valueOf(tempstr1[i]);
          }
          String[] tempstr2 = ad2.time.split("[/]");
          int[] tempint2 = new int[tempstr2.length];
          for(int i=0; i<tempstr2.length; i++){
              tempint2[i] = Integer.valueOf(tempstr2[i]);
          }
          for(int i=0; i<tempint1.length; i++){
              if(tempint1[i]>tempint2[i]){
                  tempReturn = -1;
                  break;
              }
              else if(tempint1[i]<tempint2[i]){
                  tempReturn = 1;
                  break;
              }
              else if(tempint1[i]==tempint2[i])
              {
                  tempReturn =0;
              }
          }
              return tempReturn;
      }
  }

然後使用的方式為

          AD_Sort ads;
          ads = new MoneyComparator();
          Collections.sort(al, ads);

 

分類
Uncategorized

EditText 的使用

EditText 用來輸入編輯資料,它繼承自 TextView,許多在 TextView中的方法也可以在這使用, 可藉由 xml 來定義, 其中參數可以調整輸入資料格式,長度等等,一個 EditText 在 xml 中定義如下

      <EditText
          android:id="@+id/editTextTime"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:ems="10"
          android:inputType="date" >
          <requestFocus />
      </EditText>

第 5 行限制字數為 10 個字元
第 6 行限制輸入格式為 date
也有一些常用的方法如下

          //get EditText
          EditText etMoney = (EditText) findViewById(R.id.editTextMoney);
          etMoney.setText("0000");
          etMoney.getText().toString();
          etMoney.setHint("提示");
          etMoney.setInputType(InputType.TYPE_NULL);// disappear keyboard

特殊方法
1.
點擊 EditText 關閉原本的 keyboard, 並跳出調整日期選項,調整完再設定到 EditText 中

          //get edTime
          etTime = (EditText) findViewById(R.id.editTextTime);
          //get now date
          final Calendar cal = Calendar.getInstance();
          String dateStr = "" + cal.get(Calendar.YEAR) // 2012
                  + "/" + (cal.get(Calendar.MONTH) + 1) // 12 (add 1 because it start from 0)
                  + "/" + cal.get(Calendar.DATE);// 24
                                                  // ....
          //now date set to etTime
          etTime.setText(dateStr);
          // set keyboard disappear
          etTime.setInputType(InputType.TYPE_NULL);
          // touch etTime will show datePickDialog
          etTime.setOnClickListener(new OnClickListener()
          {
              @Override
              public void onClick(View v) {
                  // TODO Auto-generated method stub
                  new DatePickerDialog(ADEdit_Flow.this, new DatePickerDialog.OnDateSetListener()
                  {
                      @Override
                      public void onDateSet(DatePicker view, int year, int monthOfYear,
                              int dayOfMonth) {
                          // TODO Auto-generated method stub
                          etTime.setText(""+year+"/"+(monthOfYear+1)+"/"+dayOfMonth);
                          FP.p("touch");
                      }
                  }, cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE)).show();
              }
          });

 

2.
檢查輸入字數不可超過 7 位數,超過出現提示並重新輸入

          //get EditText
          EditText etMoney = (EditText) findViewById(R.id.editTextMoney);
          etMoney.setText("100");
          etMoney.addTextChangedListener(new TextWatcher() {
              @Override
              public void onTextChanged(CharSequence s, int start, int before, int count) {
                  // TODO Auto-generated method stub
              }
              @Override
              public void beforeTextChanged(CharSequence s, int start, int count,
                      int after) {
                  // TODO Auto-generated method stub
              }
              @Override
              public void afterTextChanged(Editable s) {
                  // TODO Auto-generated method stub
                  if(s.length()>7){
                      Toast.makeText(ADEdit_Flow.this, "最大輸入7位數字,請重新輸入",Toast.LENGTH_SHORT).show();
                      s.clear();
                  }
              }
          });

 

3.
若字串開頭部分有0,去掉0再重整,如 00987 -> 987,原理是藉由 Integer 的 parseInt() 來達成

  String temps =  etMoney.getText().toString();//只要可以轉換為字串即可
  int tempi = Integer.parseInt(temps);
  String.valueOf(tempi);
分類
Uncategorized

取得系統日期時間

1.使用 SimpleDateFormat + Date

    public String getTimeBySimpleDateFormat()
    {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd kk:mm:ss", Locale.TAIWAN);
        return dateFormat.format(new Date());
    }

Note: SimpleDateFormat 的建構式參數 hh:mm:ss 各代表不同意義,詳細請參考 api
第2個參數為預設語言環境。
使用這個方法的好處在於不必費心去處理格式化的問題。


 
2.使用 Calendar

    public String getTimeByCalendar()
    {
        Calendar cal = Calendar.getInstance();
        String dateStr = ""+cal.get(Calendar.YEAR)
        +"/"+(cal.get(Calendar.MONTH)+1)
        +"/"+cal.get(Calendar.DATE)
        +" "+cal.get(Calendar.HOUR_OF_DAY)
        +":"+cal.get(Calendar.MINUTE)
        +":"+cal.get(Calendar.SECOND);
        return dateStr;
    }

也可以直接使用 Calendar 來取得日期時間,要注意Calendar.MONTH 起始是從0開始,所以要+1。
 

分類
Uncategorized

Activity 之間的切換與傳送資料(Activity+Bundle)

在前幾篇的 “啟動新 Activity” 中,介紹如何在舊 Activity 中啟動新的 Activity,如果情況是 Activity 互相切換甚至它們還能傳送數值,要如何做到呢? 很簡單,一樣使用 Intent 設定要切換的 Activity ,接著利用 Bundle 綁定數值,就能達到目的了,以下建立 2 個 Activity
第 1 個 MainActivity

  package com.example.androidtestproject;
   
  import android.app.Activity;
  import android.content.Intent;
  import android.os.Bundle;
  import android.view.Menu;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.widget.Button;
  import android.widget.TextView;
   
  public class MainActivity extends Activity {
   
      Button bright;
   
      TextView tv1;
   
      int num;
   
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
   
          Bundle b = this.getIntent().getExtras();
          if (b != null) {
              num = b.getInt("num");
          }
   
          tv1 = (TextView) findViewById(R.id.text1);
   
          tv1.setText("MainActivity1: " + num);
   
          bright = (Button) findViewById(R.id.buttonright);
          bright.setOnClickListener(new OnClickListener() {
   
              @Override
              public void onClick(View v) {
                  // TODO Auto-generated method stub
   
                  Bundle b = new Bundle();
                  num++;
                  b.putInt("num", num);
   
                  Intent inte = new Intent();
                  inte.setClass(MainActivity.this, MainActivity2.class);
                  inte.putExtras(b);
   
                  startActivity(inte);
                       MainActivity.this.finish();
              }
          });
   
      }
   
  }

第 23 行的 R.layout.activity_main 內容如下,裡面只有 1 個按鈕,和 1 個 TextView

  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent" >
   
      <TextView
          android:id="@+id/text1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_centerHorizontal="true"
          android:layout_centerVertical="true"
          android:text="@string/hello_world"
          tools:context=".MainActivity" />
   
      <Button
          android:id="@+id/buttonright"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_alignParentBottom="true"
          android:layout_alignParentRight="true"
          android:text="activity2" />
   
  </RelativeLayout>

 

第 25 ~ 28 行為取得從 MainActivity2 傳來的資料,注意第 26 行檢查 b 是否為 null , 因為在啟動程序時並不會有數值傳送,如果沒有檢查第 27 行就會出現錯誤
第 41 ~ 43 行為建立 Bundle 物件 b , 並放入數值 num , 放入的方式是 key – value 對應,在另 1 個 Activity 中取得數值時也必須藉由 key 來取得
第 45 ~ 46 行為設定切換的 Activity , 第 1 個參數為自己本身, 第 2 個參數為另 1 個 Activity
第 47 行將第 41 行建立的 b 放入以便傳送
第 49 行開始切換
接著是第 2 個 MainActivity 的內容

  package com.example.androidtestproject;
   
  import android.app.Activity;
  import android.content.Intent;
  import android.os.Bundle;
  import android.view.View;
  import android.view.View.OnClickListener;
  import android.widget.Button;
  import android.widget.TextView;
   
  public class MainActivity2 extends Activity {
   
      Button bright;
   
      TextView tv1;
   
      int num;
   
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main2);
   
          Bundle b = this.getIntent().getExtras();
          num = b.getInt("num");
   
          tv1 = (TextView) findViewById(R.id.text2);
          tv1.setText("MainActivity2: " + num);
   
          bright = (Button) findViewById(R.id.buttonright);
          bright.setOnClickListener(new OnClickListener() {
   
              @Override
              public void onClick(View v) {
                  // TODO Auto-generated method stub
   
                  Bundle b = new Bundle();
                  num++;
                  b.putInt("num", num);
   
                  Intent inte = new Intent();
                  inte.setClass(MainActivity2.this, MainActivity.class);
                  inte.putExtras(b);
   
                  startActivity(inte);
                       MainActivity2.this.finish();
              }
          });
   
      }
  }

 

內容和第 1 個 MainActivity 相當類似,只差沒有檢查 b 是否為 null , 因為這個 Activity 預設並不會先啟動,一定會有 Activity 傳資料給它
結果為
一開始的 Activity 畫面,數值為 0

 
 
 
 
 
 
 
 
 
 
點選右下方的 button 之後,數值增加

分類
Uncategorized

自訂標籤頁(TabHost+TabWidget)的使用

在 “標籤頁(TabHost+TabWidget)的使用” 提到預設標籤頁的使用,實際上的應用卻不會使用預設標籤頁,因為介面美觀實在不夠,1個好的應用除了內容外,其 UI 的包裝也是相當重要, 這裡介紹如何使用自訂的標籤頁,如下圖

 
 
 
 
 
 
 
 
 
 
首先來看看 TabHost 套用的佈局檔,如下

  <?xml version="1.0" encoding="utf-8"?>
  <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@android:id/tabhost"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent" >
   
      <LinearLayout
          android:id="@+id/LinearLayout01"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:orientation="vertical" >
   
          <!-- Admob add here -->
   
          <LinearLayout
              android:id="@+id/AdLayout"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content" >
          </LinearLayout>
   
          <TabWidget
              android:id="@android:id/tabs"
              android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:visibility="gone" />
   
          <!-- framelayout put here will be buttom -->
   
          <RadioGroup
              android:id="@+id/tab_group"
              android:layout_width="fill_parent"
              android:layout_height="50dp"
              android:layout_gravity="bottom"
              android:background="@drawable/background1"
              android:checkedButton="@+id/tab1"
              android:gravity="center_vertical"
              android:orientation="horizontal" >
   
  <!--             button set null that will remove default radio button -->
   
              <RadioButton
                  android:id="@id/tab1"
                  android:layout_width="fill_parent"
                  android:layout_height="fill_parent"
                  android:layout_marginTop="1.0dip"
                  android:layout_weight="1.0"
                  android:background="@drawable/tab_bg_selector"
                  android:button="@null"
                  android:gravity="center"
                  android:tag="tab1"
                  android:text="消費清單" />
   
              <RadioButton
                  android:id="@+id/tab2"
                  android:layout_width="fill_parent"
                  android:layout_height="fill_parent"
                  android:layout_marginTop="1.0dip"
                  android:layout_weight="1.0"
                  android:background="@drawable/tab_bg_selector"
                  android:button="@null"
                  android:gravity="center"
                  android:text="本日消費" />
   
              <RadioButton
                  android:id="@+id/tab3"
                  android:layout_width="fill_parent"
                  android:layout_height="fill_parent"
                  android:layout_marginTop="1.0dip"
                  android:layout_weight="1.0"
                  android:background="@drawable/tab_bg_selector"
                  android:button="@null"
                  android:gravity="center"
                  android:text="本周消費" />
   
              <RadioButton
                  android:id="@+id/tab4"
                  android:layout_width="fill_parent"
                  android:layout_height="fill_parent"
                  android:layout_marginTop="1.0dip"
                  android:layout_weight="1.0"
                  android:background="@drawable/tab_bg_selector"
                  android:button="@null"
                  android:gravity="center"
                  android:text="本月消費" />
          </RadioGroup>
   
          <!-- framelayout put here will be Top -->
          <FrameLayout
              android:id="@android:id/tabcontent"
              android:layout_width="fill_parent"
              android:layout_height="0.0dip"
              android:layout_weight="1.0" />
      </LinearLayout>
   
  </TabHost>

第 7 行指出使用垂直線性排版
第 8 ~ 11 行為 LinearLayout 的內容
第 13 ~ 19 行為 Admob 的使用,如果沒有 admob 可以忽略
第 21 ~ 25 行為原先的 TabWidget ,注意 25 行我們直接讓它不顯示,也不會作用
第 29 ~ 85 行為取代 TabWidget 的 RadioGroup , 裡面有 4 個 RadioButton 分別在 41, 53, 64, 75 行
第 32 行設定高度
第 33 行設定在畫面底部
第 34 行設定底圖為 background1,為1張 png 圖,它會設定在整個按鈕的下方,注意這張圖的寬高
第 36 行設定其內容按鈕為橫向排列
第 41 ~ 51 行為第 1 個按鈕的設定
第 42 行設定其 id, 注意這個 id 名稱會連結到程式碼中
第 43 ~ 44 行設定尺寸
第 45 行距離上方多 1 dp
第 46 行設定 weight 為 1.0
第 47 行設定按鈕的格式為 xml 檔,注意它決定按鈕顯示的外觀,其內容如下

  <?xml version="1.0" encoding="utf-8"?>
  <selector xmlns:android="http://schemas.android.com/apk/res/android">
   
      <item android:drawable="@drawable/button1" android:state_focused="true"/>
      <item android:drawable="@drawable/button2" android:state_pressed="true"/>
      <item android:drawable="@drawable/button3" android:state_checked="true"/>
   
  </selector>

第 4 行無作用
第 5 行為按鈕被按下的顯示圖片,注意圖片寬高
第 6 行為按鈕被選擇的顯示圖片,注意圖片寬高
第 48 行設定為 null ,以去除預設的按鈕外觀
第 50 行設定其 tag, 注意這個 tag 名稱會連結到程式碼中
第 51 行設定顯示字樣,其他按鈕也是類似的設定
第 88 ~ 92 行為 framelayout 的設定, 注意它也可以放在第 27 行 ,如此按鈕們都會移動到畫面底部
看完  TabHost 套用的佈局檔後,接著來看看其程式碼

  package com.example.helloworld;
   
  import android.app.TabActivity;
  import android.content.Intent;
  import android.os.Bundle;
  import android.view.animation.Animation;
  import android.view.animation.ScaleAnimation;
  import android.widget.LinearLayout;
  import android.widget.RadioButton;
  import android.widget.RadioGroup;
  import android.widget.RadioGroup.OnCheckedChangeListener;
  import android.widget.TabHost;
   
  import com.google.ads.AdRequest;
  import com.google.ads.AdSize;
  import com.google.ads.AdView;
   
  @SuppressWarnings("deprecation")
  public class Table_Flow extends TabActivity{
   
      private RadioGroup tabGroup;
      private RadioButton rb1;
      private RadioButton rb2;
      private RadioButton rb3;
      private RadioButton rb4;
      private TabHost thost;
      public void onCreate(Bundle savedInstanceState){
          super.onCreate(savedInstanceState);
          setContentView(R.layout.table_host);
  //        showAdmob();
          initView();
      }
      void initView(){
          thost = getTabHost();// build tabhost
          tabGroup = (RadioGroup) findViewById(R.id.tab_group);
          rb1 = (RadioButton)findViewById(R.id.tab1);
          rb2 = (RadioButton)findViewById(R.id.tab2);
          rb3 = (RadioButton)findViewById(R.id.tab3);
          rb4 = (RadioButton)findViewById(R.id.tab4);
          Intent inte1 = new Intent(this, Table_widget4.class);
          Intent inte2 = new Intent(this, Table_widget1.class);
          Intent inte3 = new Intent(this, Table_widget2.class);
          Intent inte4 = new Intent(this, Table_widget3.class);
          thost.addTab(thost.newTabSpec("TAB1").setIndicator("tab1").setContent(inte1));
          thost.addTab(thost.newTabSpec("TAB4").setIndicator("tab4").setContent(inte2));
          thost.addTab(thost.newTabSpec("TAB2").setIndicator("tab2").setContent(inte3));
          thost.addTab(thost.newTabSpec("TAB3").setIndicator("tab3").setContent(inte4));
          tabGroup.setOnCheckedChangeListener(new    OnTabChangeListener());
   
      }
       private class OnTabChangeListener implements OnCheckedChangeListener {
   
              @Override
              public void onCheckedChanged(RadioGroup group, int id) {
                  // TODO Auto-generated method stub
                  //button anim
                  Animation scalybig = new ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f);
                  scalybig.setDuration(500);
                  switch(id){
                  case R.id.tab1:
                      thost.setCurrentTabByTag("TAB1");
                      rb1.startAnimation(scalybig);
                      break;
                  case R.id.tab2:
                      thost.setCurrentTabByTag("TAB2");
                      rb2.startAnimation(scalybig);
                      break;
                  case R.id.tab3:
                      thost.setCurrentTabByTag("TAB3");
                      rb3.startAnimation(scalybig);
                      break;
                  case R.id.tab4:
                      thost.setCurrentTabByTag("TAB4");
                      rb4.startAnimation(scalybig);
   
                      break;
                  }
              }
       }
      void showAdmob(){
      AdView adView;
  //        Create the adView
         adView = new AdView(this, AdSize.BANNER, "a150189a3abeb1a");
         LinearLayout layout = (LinearLayout)findViewById(R.id.AdLayout);
         layout.addView(adView);
         adView.loadAd(new AdRequest());
      }
  }
   
   

事實上內容也沒有太大的改變,只是加入 RadioGroup
第 34 行套用上述的佈局檔
第 36 行為 Admob 的使用,目前不用
第 46 行取得 RadioGroup, 注意 id 要對應 xml 中的設定
第 48 ~ 51 行取得 4 個按鈕, 我針對按鈕有做點選後的動畫
第 53 ~ 56 行設定 4 個 Intent
第 58 ~ 61 行設定 4 個按鈕對應的內容, 注意 setIndicator(“”) 和 setContent(),其傳入參數必須對應 xml 中的設定
第 64 行設定按鈕們的監聽器,其內容在 68 ~ 105 行
第 71 行覆寫 onCheckedChanged 方法
第 75 ~ 76 行為按鈕被按下時播放的動畫
第 79 ~ 101 行為按鈕按下切換的方法,注意 case 對應的 id 和 setCurrentTabByTag 的 id 必須符合

分類
Uncategorized

標籤頁(TabHost+TabWidget)的使用

標籤頁在顯示上是相當方便且用途廣泛的元件,在電話簿,訊息中常常可見,簡單的範例如下圖

 
 
 
 
 
 
 
 
 
 
首先是 TabHost 和 TabWidget 的關係, TabHost 包含著 TabWidget , 可以有多個 TabWidget 的存在,如上圖就包含 4 個 TabWidget (消費清單,本日消費,本周消費,本月消費),每個 TabWidget 可以視為不同的 Activity ,當手指觸碰到不同的 TabWidget ,就會執行不同的 TabWidget, TabHost 的 xml 結構如下

  <?xml version="1.0" encoding="utf-8"?>
  <TabHost xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@android:id/tabhost"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent" >
   
      <LinearLayout
          android:id="@+id/LinearLayout01"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:orientation="vertical" >
   
          <TabWidget
              android:id="@android:id/tabs"
              android:layout_width="match_parent"
              android:layout_height="wrap_content" />
   
          <FrameLayout
              android:id="@android:id/tabcontent"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent" />
      </LinearLayout>
   
  </TabHost>

 
這是標準的 TabHost 的 xml 格式,第 7 行指出是個線性垂直的佈局,且依序為 TabWidget(標籤頁),以及其內容(FrameLayout),接著來看 TabHost的程式碼,如下

  package com.example.helloworld;
   
  import android.app.TabActivity;
  import android.content.Intent;
  import android.os.Bundle;
  import android.widget.TabHost;
  import android.widget.TabHost.TabSpec;
   
  @SuppressWarnings("deprecation")
  public class Table_Flow extends TabActivity{
   
      public void onCreate(Bundle savedInstanceState){
          super.onCreate(savedInstanceState);
          setContentView(R.layout.table_host);
          initView();
      }
      void initView(){
          TabHost thost = getTabHost();// build tabhost
          Intent inte = new Intent();
          inte.setClass(Table_Flow.this, Table_widget4.class);
          TabSpec ts = thost.newTabSpec("tab4");
          ts.setContent(inte);
          ts.setIndicator("消費清單");
          thost.addTab(ts);
          inte = new Intent();
          inte.setClass(Table_Flow.this, Table_widget1.class);
          TabSpec ts1 = thost.newTabSpec("tab1");
          ts1.setContent(inte);
          ts1.setIndicator("本日消費");
          thost.addTab(ts1);
          inte = new Intent();
          inte.setClass(Table_Flow.this, Table_widget2.class);
          TabSpec ts2 = thost.newTabSpec("tab2");
          ts2.setContent(inte);
          ts2.setIndicator("本周消費");
          thost.addTab(ts2);
          inte = new Intent();
          inte.setClass(Table_Flow.this, Table_widget2.class);
          TabSpec ts3 = thost.newTabSpec("tab3");
          ts3.setContent(inte);
          ts3.setIndicator("本月消費");
          thost.addTab(ts3);
          thost.setCurrentTab(0);
      }
  }

 

注意第 10 行繼承 TabActivity , 第 15 行套用上述的 xml 佈局 ,接著就是對各個 TabWidget 的初始化(initView)
第 23 行取得 TabHost 物件 thost
第 25 ~ 30 行為建立第 1 個 TabWidget 的內容
第 26 行注意 Table_widget4.class 必須先建立好,這代表當點選該標籤頁就會執行的類別
第 27 行建立 TabSpec 物件, tab4 代表該標籤頁的 Tag,之後若有需要可取得 Tag 即可
第 28 行設定 Content 內容,其對應的類別為 Table_widget4.class
第 29 行顯示的內容
第 30 行加入TabSpec
接著選擇其中 1 個最簡單的 TabWidget 來看(Table_widget2.class),其內容為

  package com.example.helloworld;
   
  import android.app.Activity;
  import android.os.Bundle;
   
  public class Table_widget2 extends Activity{
   
      public void onCreate(Bundle savedInstanceState){
          super.onCreate(savedInstanceState);
      }
  }

 

是的~ 這個就是最簡單的 TabWidget ,當然你可以任意改寫其內容來達到需求

分類
Uncategorized

顯示自訂的清單內容(ArrayList+SimpleAdapter+ListView)

在 “顯示簡單的清單內容” 中提到 String + ArrayAdapter + ListView 可達到簡單的清單顯示(單行單筆資訊),如下圖每行只有顯示1個字串(aaaaaa,bbbbbbb等等)

 
 
 
 
 
 
 
 
 
 
那如果想達到單行多筆資訊顯示就必須使用 ArrayList + SimpleAdapter + ListView 才能達到需求,如下圖每行有 3 個資訊(2012/01/01 , 111111 , 這是備註1 )

 
 
 
 
 
 
 
 
 
 
首先是 ArrayList ,它的作用如同上述範例中的 String 一樣,負責提供顯示的資訊(3個字串),在這裡還必須搭配 map 來使用, map 提供 key – value 的對應型態, 1個 key 對應 1個 value ,由於我們要加入 3 個資訊, map 也必須放入 3 個 key – value 的元素,如下

  map.put("str1", "2012/01/01");
  map.put("str2", "111111");
  map.put("str3", "這是備註1");

接著把 map 加到 list 中

list.add(map);

這樣就完成 3 個資訊的顯示,接著為 SimpleAdapter 的使用,和 ArrayAdapter 一樣提供顯示資訊(ArrayList)與清單(ListView)的橋樑,如下

          SimpleAdapter sa = new SimpleAdapter(
          this,
          list,
          R.layout.test2,
          new String[]{"str1","str2","str3"},
          new int[] { R.id.date, R.id.money , R.id.detail});

 

建立需要 5 個參數,第 1個參數為 Context ,傳入自己(this)即可,第 2 個參數為資訊內容,就是剛剛提到的 ArrayList , 第 3 個參數為顯示資訊的格式,必須在 xml 中定義, R.layout.test2 如下

  <?xml version="1.0" encoding="utf-8"?>
  <!-- Copyright (C) 2006 The Android Open Source Project
   
       Licensed under the Apache License, Version 2.0 (the "License");
       you may not use this file except in compliance with the License.
       You may obtain a copy of the License at
            http://www.apache.org/licenses/LICENSE-2.0
       Unless required by applicable law or agreed to in writing, software
       distributed under the License is distributed on an "AS IS" BASIS,
       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       See the License for the specific language governing permissions and
       limitations under the License.
  -->
  <TwoLineListItem xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:minHeight="?android:attr/listPreferredItemHeightSmall"
      android:mode="twoLine" >
   
      <TextView
          android:id="@+id/date"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="2012/01/01"
          android:textAppearance="?android:attr/textAppearanceSmall" />
   
      <TextView
          android:id="@+id/money"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_below="@+id/date"
          android:layout_toRightOf="@+id/date"
          android:text="-$99999"
          android:maxEms="4"
          android:singleLine="true"
          android:textAppearance="?android:attr/textAppearanceListItem" />
   
      <TextView
          android:id="@+id/detail"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_below="@+id/date"
          android:layout_toRightOf="@+id/date"
          android:layout_marginLeft="120dp"
          android:text="這是備註"
          android:maxLines="2"
          android:ellipsize="end"
          android:textAppearance="?android:attr/textAppearanceSmall" />
   
  </TwoLineListItem>

 

內容其實很簡單,就是 3 個 TextView 的定義也代表資訊的顯示格式,第 4 和 5 個參數代表對應的值,如 “str1” 就是對應 R.id.date(也就是顯示資訊的 2012/01/01 ), “str2” 對應 R.id.money(為顯示資訊的 111111 ) , “str3” 對應 R.id.detail(為顯示資訊的 這是備註1),如此完成 SimpleAdapter 的建立,最後是 ListView 的建立,只需要設定佈局中的格式,以及將剛剛建立的 SimpleAdapter 傳入即可,如下

lv = (ListView) findViewById(R.id.listview1);
lv.setAdapter(sa);

 

最後的程式碼如下

   
  public class Table_widget4 extends Activity{
      String[] strArr1 = {"2012/01/01","2012/01/02","2012/01/03","2012/01/04","2012/01/05"
              ,"2012/01/01","2012/01/02","2012/01/03","2012/01/04","2012/01/05"
              ,"2012/01/01","2012/01/02","2012/01/03","2012/01/04","2012/01/05"};
      String[] strArr2 = {"111111","222222","3333333","4444444","55555555555555555"
              ,"111111","222222","3333333","4444444","55555555555555555"
              ,"111111","222222","3333333","4444444","55555555555555555"};
      String[] strArr3 = {"這是備註1","這是備註222222222222222222222222","這是備註3","這是XXXOOO","這是備註"
              ,"這是備註1","這是備註222222","這是備註3","這是XXXOOO","這是備註"
              ,"這是備註1","這是備註222222","這是備註3","這是XXXOOO","這是備註"};
      ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
      ListView lv;
      public void onCreate(Bundle savedInstanceState){
          super.onCreate(savedInstanceState);
          setContentView(R.layout.tabwidget4);
          initXml();
      }
      @SuppressLint("NewApi")
      void initXml(){
   
          for(int i=0; i<strArr1.length; i++){
              HashMap<String, String> map = new HashMap<String, String>();
              map.put("str1", strArr1[i]);
              map.put("str2", strArr2[i]);
              map.put("str3", strArr3[i]);
              list.add(map);
          }
          SimpleAdapter sa = new SimpleAdapter(
                  this,
                  list,
                  R.layout.test2,
                  new String[]{"str1","str2","str3"},
                  new int[] { R.id.date, R.id.money , R.id.detail});
          lv = (ListView) findViewById(R.id.listview1);
          lv.setAdapter(sa);
      }
  }

 

其中關於資訊的顯示有一些小技巧,如指定顯示單行,限制字數等等,都在 R.layout.test2 中

分類
Uncategorized

ListView 的清單起始動畫使用(LayoutAnimationController)

使用 ListView 來顯示清單時,預設的顯示方式是瞬間顯示,沒有任何的動畫,你可以使用 anim + LayoutAnimationController ,讓你的清單顯示增加質感,使用方式相當簡單,當已經處理完 ListView 的建立後,再加上 anim 和 LayoutAnimationController 即可,如下

      void listShowAnim(){
          AnimationSet set = new AnimationSet(true);
   
          Animation animation;
          animation = new TranslateAnimation(-300.0f,0.0f,0.0f,0.0f);
          animation.setDuration(1000);
          set.addAnimation(animation);
  //        Animation animation;
  //        animation = new AlphaAnimation(0.0f, 1.0f);
  //        animation.setDuration(500);
  //        set.addAnimation(animation);
  //
  //        animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
  //                Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
  //                -1.0f, Animation.RELATIVE_TO_SELF, 0.0f);
  //        animation.setDuration(100);
  //        set.addAnimation(animation);
   
          //every sublist action move, 0.0f: action together
          LayoutAnimationController controller = new LayoutAnimationController(
                  set, 0.0f);
   
          lv.setLayoutAnimation(controller);
      }

第 1 行為動畫方法的名子,以我的範例而言,它放在 initXml() 之後呼叫
第 3 行建立 AnimationSet set 如果想使用多種動畫就使用 AnimationSet ,只有1種的話使用 Animation 即可
第 5 行到第 8 行就是第 1 個動畫的建立,單純的移位動作
第 9 行把動畫加入 set
第 11 ~ 22行的註解就是多種動畫的示範
第 23 行使用 LayoutAnimationController 可以決定 ListView 中的清單是否一起動作, 0.0f 代表一起動作,如果是 1.0f 的話代表清單會以 1 秒為單位依序動作
第 26 行執行動畫,該動畫為從左邊移位進入畫面置中位置
最後把它放到 initXml() 後呼叫

  public void onCreate(Bundle savedInstanceState){
          super.onCreate(savedInstanceState);
          setContentView(R.layout.tabwidget4);
          initXml();
          listShowAnim();
      }

 

結果為


清單移動中…


清單移動中…

 

分類
Uncategorized

顯示簡單的清單內容(string+ArrayAdapter+ListView)

想要顯示簡單的清單內容可以使用 ArrayAdapter + ListView 來達成, 把想要顯示的內容以及格式加到 ArrayAdapter 中,在設定到 ListView 就完成了,以下以步驟的方式來完成
1.在 setContentView 中 的佈局檔必須加入 ListView

  <?xml version="1.0" encoding="utf-8"?>
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent" >
   
      <ListView
          android:id="@+id/listview1"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"
          android:layout_alignParentLeft="true"
          android:layout_alignParentTop="true" >
      </ListView>
      <Button
          android:id="@+id/buttonexit"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_alignParentBottom="true"
          android:layout_alignParentRight="true"
          android:text="@string/exit"
          android:shadowDx="20"
          />
   
      <Button
          android:id="@+id/buttonadd"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_alignParentBottom="true"
          android:layout_alignParentLeft="true"
          android:text="@string/add_record" />
   
   
  </RelativeLayout>

 

第 6 ~ 12行就是 ListView 的設定,接著將要顯示的內容和格式設定到 ArrayAdapter 中

//use arrAdapt
ArrayAdapter<String> arrAdapt = new ArrayAdapter<String>(this, R.layout.tabwidget4_textview, strArr);

 

第 2 行第 2 個參數就是顯示的格式,如下

  <?xml version="1.0" encoding="utf-8"?>
  <TextView xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
          android:layout_height="wrap_content"
      android:layout_marginLeft="?android:attr/listPreferredItemPaddingLeft"
      android:layout_marginTop="8dip"
          android:textAppearance="?android:attr/textAppearanceListItem"
  />

 

內容只是簡單的 TextView 格式
第 3 個參數為顯示的內容

String[] strArr = {"aaaaaa","bbbbbbb","ccccccc","ddddddd","eeeeeee"};

最後建立 ListView 並設定 ArrayAdapter 即可

ListView lv1 = (ListView)findViewById(R.id.listview1);
lv1.setAdapter(arrAdapt);

 

結果就像這樣

 
 
 
 
 
 
 
 
 
 
 
在單個清單中想要顯示多個資訊的話使用 ArrayAdapter 並不好用,可以改用 SimpleAdapter