Now you can Subscribe using RSS

Submit your Email

2017/05/19

RecyclerView

asd
RecyclerView 是在 Version 22.0.0 時候加入的 UI 元件。
學會使用 RecyclerView 後大致上可以不使用 ListView 了。
畢竟 RecyclerView  的功能比 ListView 強大許多。
效果圖如下。


Android 版本的演變與更版本更新的資料。
有興趣可以到 Wiki:Android 歷史版本 查看相關資訊。

使用 RecyclerView 必須 import v7 support library。
Android Studio 現在也很貼心,可以在 layout Design 直接幫你 import 。

import library後在 layout.xml 中放入 RecyclerView 。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    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="com.demo.recyclerviewdemo.activity.RecyclerViewDemo">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_RecyclerDemo"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>
接下來與使用 BaseAdapter 一樣需要建立 item layout.xml 與自定義 Adapter 。
<?xml version="1.0" encoding="utf-8"?>
<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="120dp">

    <ImageView
        android:id="@+id/iv_AndroidLogo"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerVertical="true"
        tools:src="@drawable/eclair"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_toEndOf="@id/iv_AndroidLogo">

        <TextView
            android:id="@+id/tv_AndroidTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="4dp"
            android:text="Android Version"
            android:textColor="@android:color/black"
            android:textSize="20sp"
            android:textStyle="bold"/>

        <TextView
            android:id="@+id/tv_AndroidVersion"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/tv_AndroidTitle"
            android:layout_centerHorizontal="true"
            android:textColor="@android:color/holo_red_dark"
            android:textSize="16sp"
            tools:text="2.0/2.1 eclair"/>

        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/tv_AndroidVersion"
            android:layout_marginLeft="4dp"
            android:layout_marginRight="4dp"
            android:layout_marginTop="4dp">

            <EditText
                android:id="@+id/et_AndroidMemo"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@null"
                android:enabled="false"
                android:focusable="false"
                android:textSize="12sp"
                tools:text="最佳化硬體速度「Car Home」程式支援更多的螢幕解像度
改良的使用者介面新的瀏覽器的用户介面和支援HTML5新的聯繫人名單更好的白色/黑色背景比率改進Google Maps 3.1.2支援Microsoft Exchange
支援內建相機閃光燈支援數位變焦改進的虛擬鍵盤支援藍牙2.1支援動態桌面的設計"/>
        </ScrollView>
    </RelativeLayout>
</RelativeLayout>
item 畫面如下。
製作 Adapter 。
RecyclerView 所使用的 Adapter 也與 ListView 不一樣。
必須要繼承 RecyclerView.Adapter 來實作。
而且支援使用 ViewHolder 不必像 BaseAdapter 需要自己判斷 ViewHolder 。

繼承 RecyclerView.Adapter 需要 Override 以下三種方法。
  • onCreateViewHolder:處理 ViewHolder View。
  • onBindViewHolder   :處理 ViewHolder 中 UI 與資料綁定。
  • getItemCount            :決定 RecyclerView 有幾個 Item 項目。
public class RecyclerViewDemoAdapter extends RecyclerView.Adapter<RecyclerViewDemoAdapter.ViewHolder> {
    int[] image = new int[]{R.drawable.beta, R.drawable.one, R.drawable.cupcake, R.drawable.donut,
            R.drawable.donut, R.drawable.eclair, R.drawable.froyo, R.drawable.gingerbread, R.drawable.honeycomb,
            R.drawable.ice_cream_sandwich, R.drawable.jelly_bean, R.drawable.kitkat, R.drawable.lollipop,
            R.drawable.marshmallow, R.drawable.nougat, R.drawable.o};

    private List<AndroidVO> mAndroidVOList;

    public RecyclerViewDemoAdapter(List<AndroidVO> androidVOList) {
        mAndroidVOList = androidVOList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler_view_demo, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.tvVersion.setText(mAndroidVOList.get(position).getVersion());
        holder.ivLogo.setImageResource(image[position]);
        holder.etMemo.setText(mAndroidVOList.get(position).getMemo());
    }

    @Override
    public int getItemCount() {
        return mAndroidVOList.size();
    }

    class ViewHolder extends RecyclerView.ViewHolder {
        ImageView ivLogo;
        TextView tvVersion;
        EditText etMemo;

        public ViewHolder(View itemView) {
            super(itemView);
            ivLogo = (ImageView) itemView.findViewById(R.id.iv_AndroidLogo);
            tvVersion = (TextView) itemView.findViewById(R.id.tv_AndroidVersion);
            etMemo = (EditText) itemView.findViewById(R.id.et_AndroidMemo);
        }
    }
}
ViewHolder 不像 BaseAdapter 只是一個 inner class 。
而是要繼承 RecyclerView.ViewHolder 。
事先把網路上抓好的圖片位置寫成 int[] 方便之後抓取位置。
可以看到我是傳入一個 List<AndroidVO> 的物件進去。

AndroidVO:幫我把從 Wiki 上抓的資料組成一個物件傳入 Adapter 。
public class AndroidVO {
    private String version;
    private String memo;

    public AndroidVO(String version, String memo) {
        this.version = version;
        this.memo = memo;
    }

    public String getVersion() {
        return version;
    }

    public String getMemo() {
        return memo;
    }

}
Java Code
 public class RecyclerViewDemo extends AppCompatActivity {
    private List<String> version = new ArrayList<>();
    private List<String> memo = new ArrayList<>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recycler_view_demo);

        RecyclerViewDemoAdapter adapter = new RecyclerViewDemoAdapter(initData());
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv_RecyclerDemo);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);
    }

    private List<AndroidVO> initData() {
        version = Arrays.asList(getResources().getStringArray(R.array.android_version));
        memo = Arrays.asList(getResources().getStringArray(R.array.android_memo));
        
        List<AndroidVO> list = new ArrayList<>();
        for (int i = 0; i < version.size(); i++) {
            AndroidVO vo = new AndroidVO(version.get(i), memo.get(i));
            list.add(vo);
        }
        return list;
    }
}
initData() 只是幫我把資料組成 List 方便我傳入 Adapter 。
RecyclerView 使用方法與 ListView 雷同。
差別在於 RecyclerView  需要使用 setLayoutManager() 設定 LayoutManager Type。
這樣系統才知道要讓 RecyclerView 進行怎樣的排列。
這次我們以 LinearLayoutManager 作為示範。
最後在 RecyclerView.setAdapter() 就完成 RecyclerView 初步的使用了。

可以看到跟 ListView 效果差不多,但是效能上比 Listview 好很多。

接下來要寫上 onClick 事件。
與 ListView 不同的是 RecyclerView 沒有 setOnClickListener 接口可以使用。
所以要自己去實現它。

首先我們在 ViewHolder class 中 implement View.OnItemClickListener 。
並且 override onClick()。
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
        @Override
        public void onClick(View v) {
            if (mClick != null)
                mClick.onItemClick(v, (int) v.getTag());
        }
可以看到 override onClick 中 我判斷了 mClick 並且做了某些事情。
mClick 是自己定義的 interface 如下。
private OnRecyclerViewClick mClick;

    public interface OnRecyclerViewClick {
        void onItemClick(View v, int position);
    }

    public void setOnClickListener(OnRecyclerViewClick clickListener) {
        this.mClick = clickListener;
    }
寫了一個 OnRecyclerViewClick interface 。
裡面宣告一個 void onItemClick(View v,int position) 。
View 的目的是要把點擊到的 item 傳出去就像 ListView 的 itemClick 事件。
int 不用多解釋就是點擊當前 itemView 的 adapter 位置。

然後再 onBindViewHolder 中把我們需要的 position 數值放進去 itemView中。
holder.itemView.setTag(position);
並且在 adapter 中宣告 setOnClickListener 好讓我們可以在 class 中接收 click 事件。
Activity 中只要這樣使用。
       adapter.setOnClickListener(new RecyclerViewDemoAdapter.OnRecyclerViewClick() {
            @Override
            public void onItemClick(View v, int position) {
                Toast.makeText(RecyclerViewDemo.this, "version=" + version.get(position) + "\n" + memo.get(position),
                        Toast
                        .LENGTH_SHORT)
                        .show();
            }
        });
設置完 click 事件後效果如下圖。


程式碼下載:GitHub
相關連結

0 意見:

張貼留言

Coprights @ 2016, Blogger Templates Designed By Templateism | Templatelib