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

contextThe current context.
resourceThe resource ID for a layout file containing a layout to use when instantiating views.
textViewResourceIdThe id of the TextView within the layout resource to be populated
objectsThe 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

adapterThe 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

resourceID for an XML layout resource to load (e.g., R.layout.main_page)
rootOptional 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.)
attachToRootWhether 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

答:你打错了标点符号。。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值