1. 程式人生 > >Android列表用法之一:實戰簡單ListView

Android列表用法之一:實戰簡單ListView

ListView這個列表控制元件,是我們在開發當中使用頻率比較高的一個控制元件。
既然是使用頻率比較高,那麼我們就有必要將它的使用方式儲存,方便以後直接複製貼上,把注意力放在架構上面,不用經常做程式碼搬運工(重複搬運)。

當然Android的API也提供了許多建立ListView介面卡的快捷方式。例如ArrayAdapter、SimpleAdapter、SimpleCursorAdapter等。但是在日常的開發當中,我是從來不會使用系統自帶的介面卡。畢竟一個專案當中,大部分列表Item的高度、容納的控制元件數量、控制元件型別、邏輯處理、事件的處理等等都是不同的,使用系統自帶的完全不能勝任。

套用一句俚語:一切不以實際專案為例子的Sample都是耍*流*氓^_^

今天的簡單例項為百度地圖-收藏夾頁面的收藏點列表的仿寫(只是列表喲),下面我們先來看看原裝正品效果圖動畫:
百度地圖原版GIF

怎麼樣,夠簡單吧,不過雖然簡單,卻不能使用系統提供給我們的介面卡來做,我們來自定義介面卡
一、縱觀全域性—-我們先來分析一下頁面有哪些元素
1、一個列表(費話,我們就是來做列表的!^_^)。
2、一個餐廳名稱、一個收藏時間、一個右箭頭。
3、一條分隔線(這一個千萬忘不得)。
4、點選Item會有互動顏色變化。

二、技術選型
1、這一步是不可少的哈,因為實現列表,我們有多種方式,ListView可以,RecyclerView也可以,當然硬佈局+ScrollView也可以(這一個估計沒人這麼做)等等。這裡,我們使用ListView。沒什麼原因,就因為今天是ListView的例項。^_^
2、名稱和時間肯定使用TextView了。右箭頭使用ImageView,由於這個箭頭只是一個標識作用,沒有整合事件之類的,所以不會選擇ImageButton、Button等控制元件。
3、分隔線,這個就有講究了。我們仔細觀察,這個分隔線是從左到右,橫跨整個列表的。實現它的方法,至少有兩種:(1)使用Listview自帶的divder. (2)寫一個View到Item佈局當中。
如果這個分隔線不是橫跨整個列表,而是有左邊距或右邊距呢,比如分隔線是和文字以及時間控制元件左對齊的呢,我們就只能寫到Item佈局當中了。
4、選擇使用Selector。

三、碼程式碼
1、構造資料,模擬好像是線上獲取的資料,這裡我們封閉一個數據獲取的方法即可,所有的資料增刪查改等都在此方法內進行。

    /**
     * 資料封裝,模擬從網路上獲取到的資料
     *
     * @return 返回資料列表
     */
    private List<RestaurantBean> getDatasFromNetwork() {
        for (int i = 0; i < Constants.PLACE.length; i++) {
            RestaurantBean restaurant = new
RestaurantBean(); restaurant.setPlace(Constants.PLACE[i]); restaurant.setTime(Constants.TIME[i]); datas.add(restaurant); } //重新整理列表,如果是真實的網路資料,則放到請求回撥函式當中使用。 //注意如果是在非同步執行緒中,應該怎麼使用?它必須在主執行緒中執行!! listViewSimpleAdapter.notifyDataSetChanged(); return datas; }

以下附方法內使用到的常量:

package oliver.zhantao.oliverproject.constants;

/**
 * 存放常量類
 *
 * Created by ZhanTao on 2017/4/17.
 */

public class Constants {

    //地點列表
    public static final String PLACE[] = {
        "德克士(新世幻環球中心店)", "肯德基(九方餐廳)", "第18區海鮮拼盤", "鄧家麵館",
            "錦水緣餐廳", "麥地裡(中海店)", "可可豆湯", "臨江門火鍋店",
            "若水河鮮", "自貢鴻鶴鮮鍋兔", "又見曾毛肚老火鍋"
    };

    //時間列表
    public static final String TIME[] = {
            "2017-04-08" , "2017-04-09", "2017-04-10", "2017-04-11",
            "2017-04-12", "2017-04-13", "2017-04-14" , "2017-04-15",
            "2017-04-16", "2017-04-17", "2017-04-18"
    };
}

以下附方法內使用到的實體類:

package oliver.zhantao.oliverproject.listview;

import java.io.Serializable;

/**
 * 用於存放儲存餐廳的地點和時間的實體類。
 *
 * Created by ZhanTao on 2017/4/17.
 */

public class RestaurantBean implements Serializable {
    //地點欄位
    private String place;
    //收藏時間欄位
    private String time;

    public String getPlace() {
        return place;
    }

    public void setPlace(String place) {
        this.place = place;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }
}

2、構建一個ListViewSimpleActivity

package oliver.zhantao.oliverproject.listview;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.List;

import oliver.zhantao.oliverproject.R;
import oliver.zhantao.oliverproject.constants.Constants;

/**
 * 實戰專案中簡單的列表實現,自定義介面卡。
 * 仿寫百度地圖當中,收藏夾裡面,收藏點的列表實現。
 * 一切脫離實戰的例項,都是耍流氓。
 * <p>
 * Created by ZhanTao on 2017/4/14.
 */

public class ListViewSimpleActivity extends AppCompatActivity {
    private ListView listViewSimple;
    private ListViewSimpleAdapter listViewSimpleAdapter;
    private List<RestaurantBean> datas = null;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_listview_simple);
        datas = new ArrayList<>();
        //1、找到佈局當中的列表控制元件
        listViewSimple = (ListView) findViewById(R.id.listViewSimple);
        //2、建立介面卡物件, 上下文必須傳(非常有用)、資料必須傳
        listViewSimpleAdapter = new ListViewSimpleAdapter(ListViewSimpleActivity.this, datas);
        //3、將介面卡與listview進行繫結
        listViewSimple.setAdapter(listViewSimpleAdapter);
        //4、構造資料、重新整理列表
        getDatasFromNetwork();
    }
}

3、建立activity的佈局檔案activity_listview_simple
有人可能會疑惑:ConstraintLayout這個是什麼佈局。你可以將它改為RelativeLayout或LinearLayout,這個佈局我會在以後的文章中介紹到。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
    tools:context="oliver.zhantao.oliverproject.listview.ListViewSimpleActivity">

    <ListView
        android:id="@+id/listViewSimple"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:listSelector="@drawable/listviewsimple_bg_selector"
        android:divider="@color/transparent_20"
        android:dividerHeight="@dimen/px_1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

以上佈局檔案要注意幾個要點:
(1)分隔線的粗細:dividerHeight
(2)分隔線的顏色:divider
(3)點選Item後互動變化:listSelector

以下來製作:listviewsimple_bg_selector
顏色值就自己定義:以下color_221E90FF名字當中,221E90FF就是顏色值。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@color/color_221E90FF" android:state_pressed="true" />
    <item android:drawable="@color/transparent" />

</selector>

4、自定義Adapter,按照順序,得先把優化框架搭上,這個是不能少的。然後再是填資料,附加事件

package oliver.zhantao.oliverproject.listview;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.util.List;

import oliver.zhantao.oliverproject.R;

/**
 * 餐廳列表介面卡,在這裡將資料與控制元件進行繫結
 * <p>
 * 專案中都是自定義介面卡,很少用到系統提供的簡易介面卡。
 * 所以果斷拋棄系統的簡易介面卡,自定義想咋樣就咋樣,一個字,爽^_^
 * <p>
 * Created by ZhanTao on 2017/4/17.
 */

public class ListViewSimpleAdapter extends BaseAdapter {
    private Context mContext;
    //餐廳列表
    private List<RestaurantBean> restaurantList;
    private LayoutInflater mInflater;

    public ListViewSimpleAdapter(Context context, List<RestaurantBean> restaurantList) {
        this.mContext = context;
        this.restaurantList = restaurantList;
        mInflater = LayoutInflater.from(context);
    }

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

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

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        //1、優化框架搭起
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.activity_listview_simple_item, null);
            holder = new ViewHolder();
            holder.place = (TextView) convertView.findViewById(R.id.resturant_place);
            holder.time = (TextView) convertView.findViewById(R.id.resturant_time);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        //2、繫結資料到控制元件
        bindViewData(position, convertView, holder);
        //3、繫結監聽事件
        bindViewClickListener(position, convertView, holder);

        return convertView;
    }

    class ViewHolder {
        private TextView place;
        private TextView time;
    }

    /**
     * 繫結資料到控制元件,在這裡做統一處理,方便資料抽離
     *
     * @param position    列表索引
     * @param convertView 每個position對應的itemView
     * @param holder      holder物件
     */
    private void bindViewData(int position, View convertView, ViewHolder holder) {
        holder.place.setText(restaurantList.get(position).getPlace());
        holder.time.setText("時間:" + restaurantList.get(position).getTime());
    }

    /**
     * 繫結控制元件的各種View的事件,在這裡做統一處理,比如點選事件,長安事件。
     *
     * @param position    列表索引
     * @param convertView 每個position對應的itemView
     * @param holder      holder物件
     */
    private void bindViewClickListener(int position, View convertView, ViewHolder holder) {

    }
}

5、編寫Item佈局檔案activity_listview_simple_item
資源icon_right_arrow,大家都自己去各種app當中扒。

<?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"
    android:paddingBottom="@dimen/dp_10"
    android:paddingTop="@dimen/dp_10">

    <ImageView
        android:id="@+id/img_right_arrow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="@dimen/dp_16"
        android:layout_marginRight="@dimen/dp_16"
        android:src="@drawable/icon_right_arrow" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="@dimen/dp_16"
        android:layout_toLeftOf="@id/img_right_arrow"
        android:orientation="vertical">

        <TextView
            android:id="@+id/resturant_place"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textColor="@color/color_AA000000"
            android:textSize="@dimen/dp_14" />

        <TextView
            android:id="@+id/resturant_time"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="@dimen/dp_5"
            android:textSize="@dimen/dp_12" />
    </LinearLayout>
</RelativeLayout>

下面我們來看看程式碼執行後的效果圖:
簡單ListView實戰
以上,完了。程式碼貼完就完了。如有問題或好的建議希望大家留言,感激。

作者:Amir
部落格:http://blog.csdn.NET/amir_zt/
以上原創,轉載請註明出處,謝謝。
http://blog.csdn.net/amir_zt/article/details/70240519