這次的單元要來介紹ListView元件

而這次最後的成品如下

現在的時間是2019年的11月

可能有人覺得奇怪為何在這種年代還在介紹ListView

為何不使用現在一致好評的RecycleView呢?

 

其實在RecycleView一出來我就使用了

RecycleView雖然超級好用,但是要Coding的內容其實蠻多的

對於僅需要輕量使用的狀況而言,實在是有點殺雞焉用牛刀

但是輕量歸輕量,在今天的範例中還是盡可能深入淺出

當然之後有打算寫RecycleView的文章的~

好啦~一如往常地先上Git以示誠意

https://github.com/thumbb13555/SampleListViewExample


今天要介紹的ListView如上所述算是非常輕量的寫法

多輕量?輕量到20行左右應該就可以搞定

也不用多寫其他類別輔助,也可以做到很多操作

layout的UI介面也可以自行定義

 

但是缺點是在UI設計上沒辦法用程式控制,會減少很多樂趣

PO一下最近用RecycleView寫出的專案

用RecycleView的話就可以用程式去控制單項目的背景色

也不能說用今天教的程式就做不到

只是....RecycleView來處理真的比較方便

好啦回歸正題

來簡述一下今天要完成的功能

1.標題(科目)是固定的,但是得分是亂數

2.點擊項目後顯示科目及分數

3.如果分數低於60,直接顯示不及格

4.點擊項目後背景色設為櫻花色,並在下次點擊後消失(該功能有方法可用)

 

在最開始我要先設置全域變數以及建立框架

public class MainActivity extends AppCompatActivity {

    String[] subject = {"國文", "英文", "數學", "物理", "地科", "基本電學", "電子學", "電工機械"};
    ArrayList<String> score = new ArrayList<>();
    ListView listView;
    SimpleAdapter simpleAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        displayListView();
    }
    private void displayListView(){

    }
}

這邊我將兩個陣列分開來寫,第一個陣列是決定科目的陣列

也就是subject的陣列

另一個陣列是分數的陣列,這個陣列會根據科目數量自動增減

講個個人的小小抱怨

我以前在對這些不熟的時候最討厭用兩個陣列顯示的ListView範例

因為在實際案例中,一般至少都會有一組陣列是要能自由增減的

甚至全部都要能自由增減的案例才是主流,也才是應該的

但後來了解是因為大家不想在單一元件介紹中偏離主題,才會這麼做

而且如果使用的話,就牽涉到集合元素之類的問題了

不過我這邊還是選擇讓一個固定陣列與一個自由陣列實現

反正只要有列表元素就肯定要使用集合了,根本逃不掉XD

 

好啦,接下來的程式都寫在displayListView()方法內

可參考Git的這個檔案喔

https://github.com/thumbb13555/SampleListViewExample/blob/master/app/src/main/java/com/example/samplelistviewexample/MainActivity.java

以下是內容

 private void displayListView() {

//        ArrayList<String> arraySubject = new ArrayList<>(Arrays.asList(subject));

        listView = findViewById(R.id.listView);
        final ArrayList<HashMap<String, String>> arrayList = new ArrayList<>();

        for (int i = 0; i < subject.length; i++) {
            HashMap<String, String> hashMap = new HashMap<>();
            score.add(String.valueOf(new Random().nextInt(60) + 40));
            hashMap.put("subject", subject[i]);
            hashMap.put("score", score.get(i));
            arrayList.add(hashMap);
        }
        String[] from = {"subject", "score"};
        int[] value = {R.id.textView, R.id.textView2};
        simpleAdapter =
                new SimpleAdapter(this, arrayList, R.layout.custom_layout, from, value);
        listView.setAdapter(simpleAdapter);

        listView.setOnItemClickListener(onItemClickListener);
    }

在註解的部分是將一般字串陣列轉為arrayList陣列的方法

在本案中我不需要

接著宣告一個包含了HashMap的ArrayList

利用HashMap內必須要有索引的特性,製造出一個具有索引的ArrayList

然後再產生亂數分數(score)的部分,根據科目數量決定產生的量

故使用for迴圈處理

for(int i = 0;i<subject,lenght;i++){}

其中subject.lenght方法中會回傳陣列長度,值為int屬性

故它回傳多少數字就是迴圈會跑幾次

接著在裡面若寫入

score.add(String.valueOf(new Random().nextInt(60) + 40));

的話,就能取得跟科目一樣長度的數量了

底線是亂數產生的方法,可自行替換

 

完成了score陣列後,接著就要把陣列輸入到Array陣列中的HashMap陣列了

因此,在迴圈內宣告一組HashMap

並把值先載入其中

作法為

HashMap<String, String> hashMap = new HashMap<>();

hashMap.put("subject", subject[i]);

hashMap.put("score", score.get(i));

最後記得要加入

arrayList.add(hashMap);

資料才會正確載入喔

最後,在迴圈外可以設置一個Log,檢查一下值正不正確

D/Test: displayListView: 
[{subject=國文, score=88}
, {subject=英文, score=64}
, {subject=數學, score=63}
, {subject=物理, score=51}
, {subject=地科, score=91}
, {subject=基本電學, score=46}
, {subject=電子學, score=92}
, {subject=電工機械, score=51}]

外圍的[] 方形括號是ArrayList的部分

而中間的{}大括號是HashMap

這種格式眼熟嗎?其實跟JSON陣列很接近是吧~(當然這不是JSON)

 

接者就要進入正題了

首先先設置一個字串陣列,這個陣列是取得索引值的

String[] from = {"subject", "score"};

所以要特別注意字不能打錯喔

再來寫一個放入值的陣列,使用int宣告

int[] value = {R.id.textView, R.id.textView2};

這裡的textview1是我另行建立的介面

https://github.com/thumbb13555/SampleListViewExample/blob/master/app/src/main/res/layout/custom_layout.xml

裡面的textView1與texyView2

此外要設計介面的也從這邊處理喔

再來我們設置Adapter

老實說我到現在還是不夠清楚這是什麼

我都叫他適配器,基本上有關陣列的都是要靠它,很重要的

再來寫下這行

simpleAdapter =
                new SimpleAdapter(this, arrayList, R.layout.custom_layout, from, value);

SimpleAdapter()內要包含五個

1.Context

2.ArrayList

3.Layout

4.索引陣列

5.值陣列

 

接著讓listView載入Adapter

listView.setAdapter(simpleAdapter);

列表就會出現囉~

恩...但是有點太擠了

這時候我們進去

https://github.com/thumbb13555/SampleListViewExample/blob/master/app/src/main/res/layout/custom_layout.xml

調整一下layout_margin

就能得出我們要的結果了


接著就是該設置點擊事件了

請在最底下

 private void displayListView() {

//        ArrayList<String> arraySubject = new ArrayList<>(Arrays.asList(subject));

        listView = findViewById(R.id.listView);
        final ArrayList<HashMap<String, String>> arrayList = new ArrayList<>();

        for (int i = 0; i < subject.length; i++) {
            HashMap<String, String> hashMap = new HashMap<>();
            score.add(String.valueOf(new Random().nextInt(60) + 40));
            hashMap.put("subject", subject[i]);
            hashMap.put("score", score.get(i));
            arrayList.add(hashMap);
        }
        String[] from = {"subject", "score"};
        int[] value = {R.id.textView, R.id.textView2};
        simpleAdapter =
                new SimpleAdapter(this, arrayList, R.layout.custom_layout, from, value);
        listView.setAdapter(simpleAdapter);

        listView.setOnItemClickListener(onItemClickListener);
    }

加入紫紅色的程式

然後再displayListView()外加入點擊事件

private AdapterView.OnItemClickListener onItemClickListener
            = ((parent, view, position, id) -> {

     }

裡面有四個方法

其中這次會使用到的為position的方法

相關其他屬性在這邊,請參考

https://developer.android.com/reference/android/widget/AdapterView.OnItemClickListener

先PO上點擊事件的程式

 

private AdapterView.OnItemClickListener onItemClickListener
            = ((parent, view, position, id) -> {
                String getName = subject[position];
                String getValue= score.get(position);
                listView.setSelector(R.color.Sakura);
                if (Integer.parseInt(getValue)<60){
                    Toast.makeText(getBaseContext(),
                            "科目:"+getName+", 分數:不及格",Toast.LENGTH_SHORT).show();
                }else{
                    Toast.makeText(getBaseContext(),
                            "科目:"+getName+", 分數"+getValue,Toast.LENGTH_SHORT).show();
                }
    });

其實很簡單,只要 

陣列[position]

就可以了

因為我是宣告字串陣列

所以回傳也是字串

我已經把它寫好成getName跟getValue

最後我想要讓點擊下去的背景色變色

這裡就呼叫

listview.setSelector()

方法

()部分在裡面載入顏色資源就好

非常非常方便

加入它就可以完成想要的效果囉!


OK,介紹就到這邊

如果有問題就在留言詢問喔

上述的程式都在這,自行參考吧~

https://github.com/thumbb13555/SampleListViewExample/blob/master/app/src/main/java/com/example/samplelistviewexample/MainActivity.java

那麼,祝各位學習愉快!

arrow
arrow
    創作者介紹
    創作者 碼農日常 的頭像
    碼農日常

    碼農日常大小事

    碼農日常 發表在 痞客邦 留言(1) 人氣()