2015年5月29日 星期五

【Android】ListView 自訂畫面 簡易電話簿

這次要利用ListView來製作一個簡單的電話簿,
主要會用到這兩項知識:
  • ListView
  • BaseAdapter
我的範例主要是搭配fragment_navigation_drawer,所以我會建立在fragment裡,如果你是要寫在Activtiy裡就稍作修改就可以了 ! !

那我們會建立出:
  • myFragmet.java:用於顯示listview
  • PhoneNumberAdpater.java:listview的資料轉接器
  • myfragmet_layout.xml:fragment的layout
  • phonenumber_listview.xml:因為我們要自訂畫面所以要額外使用一個xml來設定我們要的畫面
  • listview_header.xml:來建立出listview的標頭header
  • item_select.xml:放置在drawable底下,用於點選後變色的設定
  • color.xml:放置在value底下用於建立要變的顏色

完成後的畫面:
























以下是code的部分

  • myFragment.java
先建立出需要的資料
String [] Name = new String[]{"陳oo","林oo","溫oo","施oo","胡oo"};
String [] Number = new String[]{"0970135531","0937232323","0928123456","0987987789","0988123423"};

用setAdapter這個方法去將資料送給BaseAdapter
PhoneNumberListView.setAdapter(new PhoneNumberAdapter(getActivity(),Name,Number));

public class Meun1Fragment extends Fragment {

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

}
View RootView;
private ListView PhoneNumberListView;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
RootView = inflater.inflate(R.layout.meun1_fragment,container,false);
//自己塞的資料
String [] Name = new String[]{"陳oo","林oo","溫oo","施oo","胡oo"};
String [] Number = new String[]{"0970135531","0937232323","0928123456","0987987789","0988123423"};
PhoneNumberListView = (ListView) RootView.findViewById(R.id.listView);
//取得header layout
View header = inflater.inflate(R.layout.listviewsms_header, PhoneNumberListView, false);
PhoneNumberListView.addHeaderView(header, null, false);
//自訂layout頁面並利用Baseadater來轉接
PhoneNumberListView.setAdapter(new PhoneNumberAdapter(getActivity(),Name,Number));

//用android本身設計得好的樣式
//ArrayAdapter aa= new ArrayAdapter(getActivity(),android.R.layout.simple_expandable_list_item_1,value);



return RootView;
}
}




  • PhoneNumberAdpater.java
建立出一個轉接器來讓我們能夠自訂listview的呈現方式以及將資料丟給listview


public class PhoneNumberAdapter extends BaseAdapter {
    private LayoutInflater inflater;
    String [] Name;
    String [] Number;
    private Context FragmentContext;
    //建構子
    public  PhoneNumberAdapter (Context FragmentContext, String[] Name, String [] Number){
        inflater = LayoutInflater.from(FragmentContext);
        this.Name = Name;
        this.Number = Number;
        this.FragmentContext = FragmentContext;
    }
    @Override
    public int getCount() {
        return Name.length;
    }

    @Override
    public Object getItem(int i) {
        return null;
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        //利用view去設定我們自訂的layout
        view = inflater.inflate(R.layout.phonenumber_listview,viewGroup,false);
        TextView NameText,NumberText;
        NameText = (TextView) view.findViewById(R.id.textView4);
        NumberText = (TextView) view.findViewById(R.id.textView3);
        NameText.setText(Name[i]);
        NumberText.setText(Number[i]);
        //設置監聽
        view.setOnClickListener(new OnClickListener(Name[i],Number[i]) {});
        return view;
    }
    class OnClickListener implements View.OnClickListener{
        private String Name;
        private String Number;
       //利用建構子取得內容
        public OnClickListener(String Name,String Number){
            this.Name = Name;
            this.Number = Number;
        }
        @Override
        public void onClick(View view) {
            AlertDialog.Builder builder = new AlertDialog.Builder(FragmentContext);
            builder.setTitle(FragmentContext.getString(R.string.callphone_yes_no))
                   .setMessage(Name +"\n"+ Number)
                    .setPositiveButton("撥打", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            Intent call = new Intent(
                                    Intent.ACTION_CALL, Uri.parse("tel:" + Number));
                            FragmentContext.startActivity(call);
                        }
                    })
                    .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {

                        }
                    });
            AlertDialog PhoneCallDialog = builder.create();
            PhoneCallDialog.show();
        }
    }
}




  • item_select.xml
主要用於設定click後變色的狀態,android:state_pressed="true"只要有按下則會去改變畫面的顏色


selector xmlns:android="http://schemas.android.com/apk/res/android">
item android:drawable="@color/lightskyblue" android:state_pressed="true">
item android:drawable="@android:color/transparent">
/item>


並且要記得在phonenumber_listview.xml上增加 android:background="@drawable/item_select"才會改變


linearlayout
xmlns:android="http://schemas.android.com/apk/res/android">
android:background="@drawable/item_select"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"

參考連結:

ListView+BaseAdapter應用 I ─ onLongClick與Clipboard

http://a6350202.pixnet.net/blog/post/241188445-%E3%80%90android%E3%80%91listview%2Bbaseadapter%E6%87%89%E7%94%A8-i-%E2%94%80-onlongclick%E8%88%87














2015年5月10日 星期日

【JAVA】String的內容值不可變

我們來探討一下關於String的內容指與比較



String s = "DOG";
s ="CAT";

在我們看來值好像改變了,但其實他並不是改變值,

因為String是一個參考類別,賦予他值後,他是將 s 指向 "DOG"這個這個實體,

當你又賦予了一個新的值"CAT", s 是直接重新指向"CAT"的實體,並非將DOG實體改為CAT


改變的是位址並不是實體!!!!



這就是所謂 String的內容值不可變 的意思。


延伸思考一:



既然String s 是指向位置

那麼當

String str1 = new String("Dog");
String str2 = new String("Dog");

System.out.println(str1 == str2);

會回傳甚麼?

答案是:false
因為他們指向的是不同的位置,用 == 是在比較str他們的值,而他們的值都是位置並非字串,所以當你使用 == 來做比較字串會發生錯誤!!!!

要利用equals()這個方法才能比較字串。



延伸思考二:

那麼當


String str1 = "Dog";
String str2 = "Dog";

System.out.println(str1 == str2);

會回傳甚麼?

答案是:true


因為我們是直接指向相同的字串,而在Java中有一個
StringPool他會先去找是否有相同的字串,有的話直接指向,不在重新創造實體出來。

如果你想先檢查是否在
StringPool有相同字串,你可以利用intern()這個方法。


範例:(取自良葛格blog)

public class StringIntern { 
    public static void main(String[] args) { 
        String str1 = "fly"; 
        String str2 = "weight"; 
        String str3 = "flyweight"; 
        String str4; 

        str4 = str1 + str2; 
        System.out.println(str3 == str4); 
        //false
        str4 = (str1 + str2).intern(); 
        System.out.println(str3 == str4); 
       //true
    } 
} 


參考連結:http://openhome.cc/Gossip/JavaGossip-V1/ImmutableString.htm