android從放棄到堅持放棄第三課(下)

續UI設計

學習資料:第一行代碼

ListView

手機屏幕空間有限,能夠一次顯示出來的內容並不多,有大量數據需要顯示的時候,就可以藉助ListView來實現。如QQ聊天消息和聊天記錄。

最簡單的用法

首先新建一個項目ListView。

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.wrjjrw.listviewtest.MainActivity">

    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </ListView>

</LinearLayout>

MainActivity:

package com.example.wrjjrw.listviewtest;

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

public class MainActivity extends AppCompatActivity {

    private final static String Tag = "MainActivity";

    private String[] data = {"huchi","huchi","huchi","huchi","huchi",
            "huchi","huchi","huchi","huchi","huchi","huchi","huchi",
            "huchi","huchi","huchi","huchi","huchi","huchi","huchi"
    };

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

        ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                MainActivity.this, android.R.layout.simple_list_item_1, data);
        ListView listview = (ListView) findViewById(R.id.list_view);
        listview.setAdapter(adapter);
    }
}

既然ListView適用於展示大量的數據的,就應先保存好。數據來源可以是文件,數據庫等等。

數組的數據是無法直接傳遞給ListView的,我們還需要藉助適配器來完成。這裏用ArrayAdapter,通過泛型來指定要適配的數據類型,然後在構造函數中把要適配的數據傳入。

ArrayAdapter;

public ArrayAdapter (Context context, int resource, int textViewResourceId, T[] objects)

Constructor

Parameters

context The current context.
resource The resource ID for a layout file containing a layout to use when instantiating views.
textViewResourceId The id of the TextView within the layout resource to be populated
objects The objects to represent in the ListView.

最後還需要調用ListView的setAdapter()方法,將構建好的適配器對象傳遞進去。這樣就完成了ListView和數據的關聯。

public void setAdapter (ListAdapter adapter)

Sets the data behind this ListView. The adapter passed to this method may be wrapped by a WrapperListAdapter, depending on the ListView features currently in use. For instance, adding headers and/or footers will cause the adapter to be wrapped.

Parameters

adapter The ListAdapter which is responsible for maintaining the data backing this list and for producing a view to represent an item in that data set.

See Also

  • getAdapter()

定製ListView的界面

定製ListView的界面,使之更加豐富。

先新建一個類:

public class Fruit {
    private String name;
    private int imageId;
    public Fruit(String name , int imageId){
        this.name = name;
        this.imageId = imageId;
    }
    public String getName(){
        return  name;
    }
    public int getImageId(){
        return imageId;
    }
}

layout下新建一個xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/fruit_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="10dp"
        />

</LinearLayout>

這裏定義了一個imageView用於顯示圖片,還有一個顯示名字。

接下來要創建一個自定義的適配器,這個適配器繼承自ArrayAdapter,並將泛型指定Fruit類。新建類FruitAdapter.

public class FruitAdapter extends ArrayAdapter<Fruit> {

    private int resourceId;

    public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects){
        super(context, textViewResourceId, objects);
        resourceId = textViewResourceId;
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Fruit fruit = getItem(position);    //獲取當前項的Fruit實例
        View view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
        ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
        TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
        fruitImage.setImageResource(fruit.getImageId());
        fruitName.setText(fruit.getName());
        return view;
    }
}

FruitAdapter重寫了父類的一組構造函數和getView()方法。getView()方法中在每個子項被滾動到屏幕內的時候會被調用。在getView()方法中首先通過getItem()方法得到當前項的Fruit實例,然後使用LayoutInflater來爲至俄格子項加載我們傳入的佈局。

public View inflate (int resource, ViewGroup root, boolean attachToRoot)

Inflate a new view hierarchy from the specified xml resource. Throws InflateException if there is an error.

Parameters

resource ID for an XML layout resource to load (e.g., R.layout.main_page)
root Optional view to be the parent of the generated hierarchy (if attachToRoot is true), or else simply an object that provides a set of LayoutParams values for root of the returned hierarchy (if attachToRoot is false.)
attachToRoot Whether the inflated hierarchy should be attached to the root parameter? If false, root is only used to create the correct subclass of LayoutParams for the root view in the XML.

Returns

  • The root View of the inflated hierarchy. If root was supplied and attachToRoot is true, this is root; otherwise it is the root of the inflated XML file.

第三個參數指定爲flase,即表示只讓我們在父佈局中聲明layout的屬性生效,但不爲這個View添加父佈局。因爲一旦有了父佈局之後,他就不能添加到ListView中了,如果現在還不能理解的話,只要知道這是ListView的標準寫法。

下面調用view.findViewById()找到實例後用setImageResouce()等方法來設置顯示圖片與文字。最後將佈局返回。

修改MainActivity:

public class MainActivity extends AppCompatActivity {

    private final static String Tag = "MainActivity";

    private List<Fruit> fruitList = new ArrayList<>();



    private String[] data = {"huchi","huchi","huchi","huchi","huchi",
            "huchi","huchi","huchi","huchi","huchi","huchi","huchi",
            "huchi","huchi","huchi","huchi","huchi","huchi","huchi"
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruits();
        FruitAdapter fruitAdapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item , fruitList);

        ListView listview = (ListView) findViewById(R.id.list_view);
        listview.setAdapter(fruitAdapter);
    }

    private void initFruits(){
        for(int i = 0; i < 2; i++){
            Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
            fruitList.add(apple);
            Fruit banana = new Fruit("Banana", R.drawable.apple_pic);
            fruitList.add(banana);
            Fruit orange = new Fruit("Orange", R.drawable.apple_pic);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("watermelon", R.drawable.apple_pic);
            fruitList.add(watermelon);
            Fruit cherry = new Fruit("Cherry", R.drawable.apple_pic);
            fruitList.add(cherry);
            Fruit huchi = new Fruit("huchi", R.drawable.apple_pic);
            fruitList.add(huchi);
        }
    }

}

這裏添加了一個initFruit()方法,用於初始化所有水果,由於我沒有圖片,。。。。。將就着(┬_┬)

接着在onCreate()方法中創建FruitAdapter對象。並將FruitAdapter作爲適配器傳遞給ListView,這樣定製ListView界面的任務就finish了。跑路。


提升ListView的運行效率

ListView之所以難用,是因爲他很多細節可以優化。上次中FruitAdapter的getView()方法每次都會將佈局重新加載一遍,當ListView快速滾動時,就會成爲性能的瓶頸。

修改FruitAdapter:

public class FruitAdapter extends ArrayAdapter<Fruit> {

    private int resourceId;

    public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects){
        super(context, textViewResourceId, objects);
        resourceId = textViewResourceId;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Fruit fruit = getItem(position);    //獲取當前項的Fruit實例
        View view;
        if(convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
        }else{
            view = convertView;
        }

        ImageView fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
        TextView fruitName = (TextView) view.findViewById(R.id.fruit_name);
        fruitImage.setImageResource(fruit.getImageId());
        fruitName.setText(fruit.getName());
        return view;
    }
}

我們可以發現getView()中進行了判斷,如果convertView爲null,則使用LayoutInflater去加載佈局,否則就直接重用。在快速滾動到時候也能表現出較好的性能。

繼續修改:

public class FruitAdapter extends ArrayAdapter<Fruit> {

    private int resourceId;

    public FruitAdapter(Context context, int textViewResourceId, List<Fruit> objects){
        super(context, textViewResourceId, objects);
        resourceId = textViewResourceId;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Fruit fruit = getItem(position);    //獲取當前項的Fruit實例
        View view;
        ViewHolder viewHolder;
        if(convertView == null) {
            view = LayoutInflater.from(getContext()).inflate(resourceId, parent, false);
            viewHolder = new ViewHolder();
            viewHolder.fruitImage  = (ImageView) view.findViewById(R.id.fruit_image);
            viewHolder.fruitName = (TextView) view.findViewById(R.id.fruit_name);
            view.setTag(viewHolder);
        }else{
            view = convertView;
            viewHolder = (ViewHolder) view.getTag();
        }

        viewHolder.fruitImage.setImageResource(fruit.getImageId());
        viewHolder.fruitName.setText(fruit.getName());
        return view;
    }

    private class ViewHolder {
        ImageView fruitImage;
        TextView fruitName;
    }
}

新增一個內部類ViewHolder,用於對控件的實例進行緩存。當convertView爲null的時候創建一個ViewHolder並將控件的實例都存放在ViewHolder裏,setTag()存放在View中。這樣所有的空間的實例都緩存在了ViewHolder裏,就沒有必要每次都通過findViewById()方法來獲取控件的實例。


ListView的點擊事件

滾動只是我們的視覺上的效果,如果不能點擊的話,是不是顯得很沒有用。

修改Manifest:


public class MainActivity extends AppCompatActivity {

    private final static String Tag = "MainActivity";

    private List<Fruit> fruitList = new ArrayList<>();



    private String[] data = {"huchi","huchi","huchi","huchi","huchi",
            "huchi","huchi","huchi","huchi","huchi","huchi","huchi",
            "huchi","huchi","huchi","huchi","huchi","huchi","huchi"
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initFruits();
        FruitAdapter fruitAdapter = new FruitAdapter(MainActivity.this, R.layout.fruit_item , fruitList);

        ListView listview = (ListView) findViewById(R.id.list_view);
        listview.setAdapter(fruitAdapter);

        listview.setOnItemClickListener(new AdapterView.OnItemClickListener(){
            @Override
            public void onItemClick(AdapterView<?>parent, View view, int position, long id){
                Fruit fruit = fruitList.get(position);
                Toast.makeText(MainActivity.this, fruit.getName(), Toast.LENGTH_LONG).show();
            }
        });

    }

    private void initFruits(){
        for(int i = 0; i < 2; i++){
            Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
            fruitList.add(apple);
            Fruit banana = new Fruit("Banana", R.drawable.apple_pic);
            fruitList.add(banana);
            Fruit orange = new Fruit("Orange", R.drawable.apple_pic);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("watermelon", R.drawable.apple_pic);
            fruitList.add(watermelon);
            Fruit cherry = new Fruit("Cherry", R.drawable.apple_pic);
            fruitList.add(cherry);
            Fruit huchi = new Fruit("huchi", R.drawable.apple_pic);
            fruitList.add(huchi);
        }
    }
}

可以看到使用了setOnItemClickListener()方法爲ListView註冊了一個監聽器。當用戶點擊時就會回調onItemClick()方法。通過position可以判斷點擊的是哪一個子項,然後獲得相應的實例,並通過Toast顯示其名稱。


RecyclerView

ListView需要一些技能提高性能,而且擴展性不好,只能實現數據縱向的滾動。

RecyclerView是一個更加強大的滾動控件。而且還優化了ListView中存在的各種問題。

新建一個新的項目(或者… (:D):

基本用法

修改app/build.gradle:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })

    compile 'com.android.support:appcompat-v7:25.3.0'
    compile 'com.android.support:recyclerview-v7:25.3.0'
    testCompile 'junit:junit:4.12'
}

→Sync Now

我新建了一個xml(或者你可以直接改main):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:id="@+id/Recycleview"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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


</LinearLayout>

由於RecycleView不是內置在系統SDK當中的,所以需要把完整的包路徑寫出來。

由於我沒有新建啦,就興建了一個empty Activity;

我新建了FruitAdapterNew……..

public class FruitAdapterNew extends RecyclerView.Adapter<FruitAdapterNew.ViewHolder> {

    private List<Fruit> mFruitList;

    static class ViewHolder extends RecyclerView.ViewHolder{
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(View view){
            super(view);
            fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            fruitName = (TextView) view.findViewById(R.id.fruit_name);

        }

    }

    public FruitAdapterNew(List<Fruit> fruitList){
        mFruitList = fruitList;
    }

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

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }

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

爲我們的RecyclerView準備一個適配器。其中ViewHolder是我們在FruitAdapter中定義的一個內部類。這個內部類繼承自RecyclerView.ViewHolder。然後ViewHolder的構造函數中要傳入一個View參數 ,即RecycleView子項的最外層佈局。獲得佈局後就可以獲得期中的控件。

FruitAdapterNew中將傳進來的數據源賦值給一個全局變量,之後的操作均在這個全局變量上進行。

FruitAdapterNew繼承了RecyclerView.Adapter,就需要重寫三個方法:

onCreateViewHolder()方法用於創建ViewHolder實例的,我們在這個方法中將fruit_item佈局加載進來。然後把加載出來的佈局傳入到構造函數中。最後將ViewHolder返回。onBindViewHolder()方法是用於對RecyclerView子項的數據進行賦值的,會在每個子項被滾動到屏幕內的時候執行,這裏我們通過position參數得到當前項的fruit.。getItemCount()返回有多少子項。

修改Activity的:

package com.example.wrjjrw.listviewtest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;

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

public class Main2Activity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();

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

        initFruits();
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.RecycleView);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(linearLayoutManager);
        FruitAdapterNew adapter = new FruitAdapterNew(fruitList);
        recyclerView.setAdapter(adapter);

    }

    private void initFruits(){
        for(int i = 0; i < 2; i++){
            Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
            fruitList.add(apple);
            Fruit banana = new Fruit("Banana", R.drawable.apple_pic);
            fruitList.add(banana);
            Fruit orange = new Fruit("Orange", R.drawable.apple_pic);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("watermelon", R.drawable.apple_pic);
            fruitList.add(watermelon);
            Fruit cherry = new Fruit("Cherry", R.drawable.apple_pic);
            fruitList.add(cherry);
            Fruit huchi = new Fruit("huchi", R.drawable.apple_pic);
            fruitList.add(huchi);
        }
    }
}

我們在這裏首先獲得了RecyclerView的實例,然後創建了一個LinearLayoutManager對象,並將他設置到RecyclerView的佈局中。linearLinayoutManager用於指定一個RecyclerView的佈局方式,這裏使用的類似ListView。接下來我們創建了FruitAdapter的實例,並將水果數據傳入FruitAdapter的構造函數,最後調用RecyclerView的setAdapter()方法完成適配器,完成RecyclerView和數據之間的關聯。

跑路


橫向滾動和瀑布流佈局

先來實現橫向滾動:

fruit_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="100dp"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/fruit_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />

</LinearLayout>

將每個水果的長度設爲100dp會比較好看

Activity裏面的:

public class Main2Activity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();

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

        initFruits();
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.RecycleView);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);

        recyclerView.setLayoutManager(linearLayoutManager);
        FruitAdapterNew adapter = new FruitAdapterNew(fruitList);
        recyclerView.setAdapter(adapter);

    }

    private void initFruits(){
        for(int i = 0; i < 2; i++){
            Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
            fruitList.add(apple);
            Fruit banana = new Fruit("Banana", R.drawable.apple_pic);
            fruitList.add(banana);
            Fruit orange = new Fruit("Orange", R.drawable.apple_pic);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("watermelon", R.drawable.apple_pic);
            fruitList.add(watermelon);
            Fruit cherry = new Fruit("Cherry", R.drawable.apple_pic);
            fruitList.add(cherry);
            Fruit huchi = new Fruit("huchi", R.drawable.apple_pic);
            fruitList.add(huchi);
        }
    }

}

只加了一句話。調用了linearLayoutManager的setOrientation()方法【他默認是縱向排列的】,現在改爲橫向的。

ListView的佈局排列是由自身去管理,RecyclerView則將這個工作交給了LayoutManager,LayoutManager中制定了一套可擴展的佈局排列接口,子類只要按照接口的規範來實現,就能定製出各種不同排列方式的佈局了。

除了LinearLayoutManager外,還有GridLayoutManager和StaggeredGridLayoutManager這兩種內置的佈局排列方式。GridLayoutManager可以用於實現網格佈局,後者可以實現瀑布流佈局。

先來瀑布流佈局。

fruit_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    >

    <ImageView
        android:id="@+id/fruit_image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        />

    <TextView
        android:id="@+id/fruit_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        />

</LinearLayout>

再改一下Activity:

public class Main2Activity extends AppCompatActivity {

    private List<Fruit> fruitList = new ArrayList<>();

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

        initFruits();
        RecyclerView recyclerView = (RecyclerView) findViewById(R.id.RecycleView);
        StaggeredGridLayoutManager layoutManager =
                new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);

        recyclerView.setLayoutManager(layoutManager);
        FruitAdapterNew adapter = new FruitAdapterNew(fruitList);
        recyclerView.setAdapter(adapter);

    }

    private void initFruits(){
        for(int i = 0; i < 2; i++){
            Fruit apple = new Fruit("Apple", R.drawable.apple_pic);
            fruitList.add(apple);
            Fruit banana = new Fruit("Banana", R.drawable.apple_pic);
            fruitList.add(banana);
            Fruit orange = new Fruit("Orange", R.drawable.apple_pic);
            fruitList.add(orange);
            Fruit watermelon = new Fruit("watermelon", R.drawable.apple_pic);
            fruitList.add(watermelon);
            Fruit cherry = new Fruit("Cherry", R.drawable.apple_pic);
            fruitList.add(cherry);
            Fruit huchi = new Fruit("huchi", R.drawable.apple_pic);
            fruitList.add(huchi);
            Fruit randomOne = new Fruit(getRandomLengthName("randomOne"), R.drawable.apple_pic);
            fruitList.add(randomOne);
            Fruit randomTwo = new Fruit(getRandomLengthName("randomTwo"), R.drawable.apple_pic);
            fruitList.add(randomTwo);
            Fruit randomThree = new Fruit(getRandomLengthName("randomThree"), R.drawable.apple_pic);
            fruitList.add(randomThree);
        }
    }


    private String getRandomLengthName(String name){
        Random random = new Random();
        int length = random.nextInt(20) + 1;
        StringBuilder builder = new StringBuilder();
        for(int i = 0; i < length; ++i){
            builder.append(name);
        }
        return builder.toString();
    }

}

如果都比較短的話,看起來和網格佈局差不多。StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);可以看到三列,垂直。


RecyclerView的點擊事件

RecyclerView拋棄了ListView的子項點擊的監聽器,所有的事件都是由具體的View去註冊。

修改FruitAdapterNew:

public class FruitAdapterNew extends RecyclerView.Adapter<FruitAdapterNew.ViewHolder> {

    private List<Fruit> mFruitList;

    static class ViewHolder extends RecyclerView.ViewHolder{
        View fruitView;
        ImageView fruitImage;
        TextView fruitName;

        public ViewHolder(View view){
            super(view);
            fruitView = view;
            fruitImage = (ImageView) view.findViewById(R.id.fruit_image);
            fruitName = (TextView) view.findViewById(R.id.fruit_name);

        }

    }

    public FruitAdapterNew(List<Fruit> fruitList){
        mFruitList = fruitList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).
                inflate(R.layout.fruit_item, parent, false);
        final ViewHolder holder = new ViewHolder(view);
        holder.fruitView.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicked view" + fruit.getName(),
                        Toast.LENGTH_LONG).show();
            }
        });
        holder.fruitImage.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v){
                int position = holder.getAdapterPosition();
                Fruit fruit = mFruitList.get(position);
                Toast.makeText(v.getContext(), "you clicker image" + fruit.getName(),
                        Toast.LENGTH_LONG).show();
            }
        });

        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = mFruitList.get(position);
        holder.fruitImage.setImageResource(fruit.getImageId());
        holder.fruitName.setText(fruit.getName());
    }

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

增添了fruitView變量存儲子項最外層佈局的實例。然後給fruitView和fruitImage都註冊了點擊事件。

TextView沒有註冊事件,但點擊時會被子項的最外層佈局捕獲到。

下次貼書上的練習。

問題:

問:tools:context=”.MainActivity”這到底是什麼鬼?

tools:context=”activity name”這一句不會被打包進APK。只是ADT的Layout Editor在你當前的Layout文件裏面設置對應的渲染上下文,說明你當前的Layout所在的渲染上下文是activity name對應的那個activity,如果這個activity在manifest文件中設置了Theme,那麼ADT的Layout Editor會根據這個Theme來渲染你當前的Layout。就是說如果你設置的MainActivity設置了一個Theme.Light(其他的也可以),那麼你在可視化佈局管理器裏面看到的背景阿控件阿什麼的就應該是Theme.Light的樣子。僅用於給你看所見即所得的效果而已。source

問:遇到一個問題:如下

Error:Failed to resolve: com.android.support.recycleview-v7:25.3.0:
Install Repository and sync project
Open File

答:你打錯了標點符號。。。。。。。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章