iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 13
0
Mobile Development

Android Studio 學習交流系列 第 13

[Day13]Android學習-我的清單好朋友與baseAdapter類別

  • 分享至 

  • xImage
  •  

大家好!接續[Day10-12]三篇文章的介紹,我們了解到常用的清單元件有ListView、GridView和Spinner,分別從其中了解到:

  1. 三者在xml檔的設計

  2. 了解ListView、GridView的比較,GridView為二維的排列方式,而ListView是可滑動的垂直清單,清單為單方向的排列

  3. Spinner的偵聽方式setOnItemSelectedListener與ListView、GridView的偵聽方式setOnItemClickListener不同

雖然介紹完這三者元件的特色,不過好像缺了甚麼東西,總覺得三者的清單選單太過單調、不吸引人,那是不是有什麼方法可以改變清單的樣式呢?能否自己設計我想要的清單模式呢?OK,千萬別離開,這篇文章將會討論上述問題喔。那我們趕快來討論清單模式的設計吧!
/images/emoticon/emoticon31.gif
這篇要接續作水果清單,以下範例以GridView元件作說明:

UI程式設計

xml檔必須要設計2個檔案,第一個主畫面GridView的顯示,第二個選單的設計,沒錯!選單的設計就是在layout文件底下建立xml檔。

第一步驟:建立主畫面GridView

https://ithelp.ithome.com.tw/upload/images/20190925/2012114933bqgo63y3.png
主畫面GridView程式碼

gridview_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <GridView
        android:id="@+id/gvShow"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:numColumns="2"
 />
</LinearLayout>
  • android:numColumns="2" 一列排兩欄的形式

第二步驟:建立選單

https://ithelp.ithome.com.tw/upload/images/20190925/201211498loBfvCxi9.png
選單程式碼

fruit_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/imgFruit"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginTop="5dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_gravity="center_horizontal"
        />

    <TextView
        android:id="@+id/tvName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_gravity="center_horizontal"/>

    <TextView
        android:id="@+id/tvPrice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginBottom="5dp"/>
</LinearLayout>
  • 元件上下左右都距離layout版面"5dp"
  • android:layout_marginTop="5dp"
  • android:layout_marginBottom="5dp"
  • android:layout_marginLeft="5dp"
  • android:layout_marginRight="5dp"

這樣主畫面和選單都準備妥當了!趕緊來設計Java程式!GO!

/images/emoticon/emoticon33.gif

Java程式設計

首先,要建立清單內容,每一個選項內容包含名稱、價格、圖片,由於選項中有比較多的資訊,因此我們定義一個類別為Fruit裡面存放水果名稱、水果價格及水果圖片,往後要使用裡頭的內容可以建立Fruit物件呼叫類別的方法。

public class Fruit {
    private String name;
    private int price;
    private int img;

    Fruit(String name,int price,int img){
        this.name=name;
        this.price=price;
        this.img=img;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public void setImg(int img) {
        this.img = img;
    }

    public String getName() {
        return name;
    }

    public int getPrice() {
        return price;
    }

    public int getImg() {
        return img;
    }
}

第二步驟準備列表以便存放Fruit物件

    private List<Fruit> fruitList = new ArrayList<>();
  • List 以存取Fruit物件為主的List類別

第三步驟建立資料,新增Fruit物件,並加入Fruit物件集合的列表

        private List<Fruit> getList () {
            fruitList.add(new Fruit("Apple", 50, R.drawable.apple));
            fruitList.add(new Fruit("Banana", 20, R.drawable.banana));
            fruitList.add(new Fruit("Orange", 30, R.drawable.orange));
            fruitList.add(new Fruit("Grape", 100, R.drawable.grape));
            fruitList.add(new Fruit("Strawberry", 120, R.drawable.strawberry));
            return fruitList;
        }
  • fruitList.add 物件加入清單

第四步驟實作baseAdapter類別
在實作之前先討論一下baseAdapter需要覆寫的方法

        public class FruitAdapter extends BaseAdapter{
            @Override
            public int getCount() {
                return 0;
            }

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

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

            @Override
            public View getView(int i, View view, ViewGroup viewGroup) {
                return null;
            }
        }
  • getCount()計算清單裡的選項有幾個
  • getItem(int i)回傳點選當前選項的物件
  • long getItemId(int i)回傳點選當前選項物件的ID,通常ID值不可重複
  • View getView回傳選單畫面,getView回隨著getCount()的值而當作執行次數
      public class FruitAdapter extends BaseAdapter {
            private List<Fruit> fruitList = new ArrayList<>();

            FruitAdapter(List<Fruit> fruitList) {
                this.fruitList = fruitList;
            }

            @Override
            public int getCount() {
                return fruitList.size();
            }

            @Override
            public Object getItem(int position) {
                return fruitList.get(position);
            }

            @Override
            public long getItemId(int position) {
                return fruitList.get(position).getImg();
            }

            @Override
            public View getView(int position, View view, ViewGroup viewGroup) {
                View gridview = view;
                if (gridview == null) {
                    gridview = getLayoutInflater().inflate(R.layout.fruit_layout, null);
                }
                Fruit fruit = fruitList.get(position);
                TextView tvName = (TextView) gridview.findViewById(R.id.tvName);
                tvName.setText(fruit.getName());
                TextView tvPrice = (TextView) gridview.findViewById(R.id.tvPrice);
                tvPrice.setText(Integer.toString(fruit.getPrice()));
                ImageView imgFruit = (ImageView) gridview.findViewById(R.id.imgFruit);
                imgFruit.setImageResource(fruit.getImg());
                return gridview;
            }
        }
    }
  • long getItemId物件內容有水果名稱、水果價格及水果圖片,通常尋找符合int型別有唯一值作為ID,物件內容的水果名稱不是int型別以及水果價格容易重複,因此實作會以水果圖片作為ID值

  • View getView(int position, View view, ViewGroup viewGroup) view存放當前使用者所看到的選單

  • if (gridview == null)避免重新載入同一個選單

  • getLayoutInflater().inflate(R.layout.fruit_layout, null) 得到LayoutInflater物件去載入已經設計好的fruit_layout.xml

  • 元件取得皆是由gridview所載入的fruit_layout.xml獲得


第五步驟建立GridView偵聽器

    private void setListener() {
        gvShow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                setToast(position);
            }
        });
    }

完整程式碼

MainActivity.java

//改為自己設定的APK名稱
package com.example.myapplication;
public class MainActivity extends AppCompatActivity {
    private List<Fruit> fruitList = new ArrayList<>();
    private GridView gvShow;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.gridview_layout);
        findViews();
        fruitList=getList();
        setAdapter();
        setListener();
    }

    private void findViews () {
        gvShow = (GridView) findViewById(R.id.gvShow);
    }

    private void setToast (int position){
        Toast.makeText(MainActivity.this,fruitList.get(position).getName(), Toast.LENGTH_SHORT).show();
    }

    private void setAdapter() {
        FruitAdapter adapter = new FruitAdapter(fruitList);
        gvShow.setAdapter(adapter);
    }

    private void setListener() {
        gvShow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
                setToast(position);
            }
        });
    }

        private List<Fruit> getList () {
            fruitList.add(new Fruit("Apple", 50, R.drawable.apple));
            fruitList.add(new Fruit("Banana", 20, R.drawable.banana));
            fruitList.add(new Fruit("Orange", 30, R.drawable.orange));
            fruitList.add(new Fruit("Grape", 100, R.drawable.grape));
            fruitList.add(new Fruit("Strawberry", 120, R.drawable.strawberry));
            return fruitList;
        }

        public class FruitAdapter extends BaseAdapter {
            private List<Fruit> fruitList = new ArrayList<>();

            FruitAdapter(List<Fruit> fruitList) {
                this.fruitList = fruitList;
            }

            @Override
            public int getCount() {
                return fruitList.size();
            }

            @Override
            public Object getItem(int position) {
                return fruitList.get(position);
            }

            @Override
            public long getItemId(int position) {
                return fruitList.get(position).getImg();
            }

            @Override
            public View getView(int position, View view, ViewGroup viewGroup) {
                View gridview = view;
                if (gridview == null) {
                    gridview = getLayoutInflater().inflate(R.layout.fruit_layout, null);
                }
                Fruit fruit = fruitList.get(position);
                TextView tvName = (TextView) gridview.findViewById(R.id.tvName);
                tvName.setText(fruit.getName());
                TextView tvPrice = (TextView) gridview.findViewById(R.id.tvPrice);
                tvPrice.setText(Integer.toString(fruit.getPrice()));
                ImageView imgFruit = (ImageView) gridview.findViewById(R.id.imgFruit);
                imgFruit.setImageResource(fruit.getImg());
                return gridview;
            }
        }
    }

Fruit.java

//改為自己設定的APK名稱
package com.example.myapplication;

public class Fruit {
    private String name;
    private int price;
    private int img;

    Fruit(String name,int price,int img){
        this.name=name;
        this.price=price;
        this.img=img;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPrice(int price) {
        this.price = price;
    }

    public void setImg(int img) {
        this.img = img;
    }

    public String getName() {
        return name;
    }

    public int getPrice() {
        return price;
    }

    public int getImg() {
        return img;
    }
}

實測

https://ithelp.ithome.com.tw/upload/images/20190925/20121149UiSFEVzHqw.png

https://ithelp.ithome.com.tw/upload/images/20190925/20121149RLUQqUozqB.png

https://ithelp.ithome.com.tw/upload/images/20190925/201211498q5rCkcv41.png

水果圖片來源請參考

終於完成自己打造的Adapter~
/images/emoticon/emoticon34.gif
辛苦大家了~

若文章有誤,歡迎大家提出建議。

Thank you for your time.

/images/emoticon/emoticon41.gif


上一篇
[Day12]Android學習-元件介紹-Spinner
下一篇
[Day14]Android學習-元件介紹-Activity
系列文
Android Studio 學習交流30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言