其他分享
首页 > 其他分享> > 浅谈ListView、RecycleView、GridView的使用方法步骤和效果区别.TXT

浅谈ListView、RecycleView、GridView的使用方法步骤和效果区别.TXT

作者:互联网

一、ListView的使用

说明:1、LIstView与滚动视图(ScrollView)类似,可以将多个组件加入到ListView之中以达到组件的滚动显示效果,
可以通过divider设置分割线颜色和高度
 布局文件中:android:dividerHeight="20dp"
        android:paddingTop="10dp"(设置listview和顶部的距离)
        ListView组件本身也有对应的ListView类支持,可以通过操作ListView类以完成对此组组件的操作,
        ListView类的继承结构如下所示:
        java.lang.Object
            ? android.view.View
                 ? android.view.ViewGroup
                    ? android.widget.AdapterView<T extends android.widget.Adapter>
                          ? android.widget.AbsListView
                             ? android.widget.ListView

      2、ListView的使用需要3个元素
            *ListView控件的支持
            *需要Adapter,用于将数据显示到ListView的每一个item布局中
            *数据源。多条数据的集合

                    ArrayAdapter:

                        系统线性布局适配器,只显示一行字,绑定的数据类型,可以是基本数据类型,也可以是自定义的对象类型。
                        ArrayAdapter(Context context, int textViewResourceId, List<T> objects)
                        context:Context对象,为this;
                        textViewResourceId:每一行布局文件的id;
                        objects:数据源;
                         代码: private void intiArrayList(){
                                //数据构建
                                str_list=new ArrayList<String>();
                                str_list.add("Android");
                                str_list.add("IOS");
                                str_list.add("WindowsPhone");
                                ArrayAdapter adapter=new ArrayAdapter(this,android.R.layout.simple_list_item_1,str_list);
                                //将适配器设置给listview
                                lv.setAdapter(adapter);
                            }

                    SimpleAdapter:

                        具有良好的扩展性,可以自定义item布局,实现没有逻辑的图文混排的效果
                                步骤:a/在acvitity布局文件中定义ListView布局,并给布局添加ID
                                      b/在layout文件中新建自定义的布局文件
                                      c/构建数据源,新建simpleadapter,给listview设置adapter

                                       代码:private void intiSimpleAdapter(){
                                            List<HashMap<String,Object>> list=new ArrayList();
                                            for (int i = 0; i <names.length ; i++) {
                                                HashMap<String,Object> map=new HashMap<>();
                                                map.put("name",names[i]);
                                                map.put("img",ids[i]);
                                                list.add(map);
                                            }
                                            //上下文对象 数据源 资源文件的id
                                            //String[] from
                                            //int[]  to
                                            String[] from=new String[]{"name","img"};
                                            int[] to =new int[]{R.id.name,R.id.iv_img};
                                            SimpleAdapter adapter=new SimpleAdapter(this,list,R.layout.activity_item_list,from,to);
                                            lv.setAdapter(adapter);

                    自定义Adapter: 

                            可以有自己的逻辑,实现带按钮的item布局
                            步骤:a/在acvitity布局文件中定义ListView布局,并给布局添加ID
                                  b/在layout文件中新建自定义的布局文件
                                  c/构建数据源,新建自定义adapter继承与BaseAdapter(创建有参的构造函数,重写里边的四个方法),给listview设置adapter

                                代码:
                                    public class MyAdapter extends BaseAdapter {
                                            private List<CarCompany> list;//数据源
                                            private Context context;//上下文对象
                                            private LayoutInflater inflater;//布局加载器
                                            //有参的构造函数,为数据源,上下文对象复制,同时实例化布局加载器
                                            public MyAdapter(List<CarCompany> list,Context context) {
                                                this.list=list;
                                                this.context=context;
                                                inflater=LayoutInflater.from(context);
                                            }

                                            //有多少条数据,需要创建多少个item布局
                                            @Override
                                            public int getCount() {
                                                return list.size();
                                            }
                                            //返回position对应位置的数据
                                            @Override
                                            public Object getItem(int position) {
                                                return list.get(position);
                                            }
                                            //返回position对应位置item的id
                                            @Override
                                            public long getItemId(int position) {
                                                return position;
                                            }
                                            /**
                                             * 具体定义加载item布局,并将数据显示到item布局上的方法。
                                             * @param position
                                             * @param convertView
                                             * @param parent
                                             * @return
                                             */
                                            @Override
                                            public View getView(int position, View convertView, ViewGroup parent) {
                                                //加载item布局 将xml布局加载到内存中,形成一个view
                                                View view=inflater.inflate(R.layout.activity_item_list,null);
                                                //实例化item布局上的控件
                                                ImageView iv= (ImageView) view.findViewById(R.id.iv_img);
                                                TextView tv= (TextView) view.findViewById(R.id.name);
                                                //往控件上显示数据
                                                //获取position对应位置的数据
                                                CarCompany company= (CarCompany) getItem(position);
                                                iv.setImageResource(company.getImg());
                                                tv.setText(company.getCompany());
                                                return view;
                                            }
                            在activity中实例化adapter,设置给listview
                                private void intiCustomAdapter(){
                                    List<CarCompany> list=new ArrayList<CarCompany>();
                                    for (int i = 0; i < names.length; i++) {
                                        CarCompany company=new CarCompany();
                                        company.setImg(ids[i]);
                                        company.setCompany(names[i]);
                                        list.add(company);
                                    }//数据源构建好之后实例化自定义的适配器,将数据源list作为参数传入适配器中,然后将adapter加载到ListView的布局中
                                    MyAdapter myadapter=new MyAdapter(list,this);
                                    lv.setAdapter(myadapter);
                                }

ListView的优化:

        1、复用convertview,减少item的数量:节省内存,运行更流畅
        2、使用ViewHolder类,减少findviewbyid的次数,好处就是运行更流畅

        代码:在自定义Adapter从写BaseAdapter的getview()方法时:
                public View getView(int position, View convertView, ViewGroup parent) {
                                ViewHolder holder=null;
                                //加载item布局 将xml布局加载到内存中,形成一个view
                                if(convertView==null){ //被复用后的convertview类依然包含tag
                                    holder=new ViewHolder();
                                    convertView=inflater.inflate(R.layout.activity_phone_list,null);
                                    holder.iv= (ImageView) convertView.findViewById(R.id.img_phone);
                                    holder.tv_phonename= (TextView) convertView.findViewById(R.id.phone_name);
                                    holder.tv_phoneprice= (TextView) convertView.findViewById(R.id.phone_price);
                                    holder.tv_phonecounter= (TextView) convertView.findViewById(R.id.phone_counter);
                                    convertView.setTag(holder);
                                }else {//convertview不为空,不为空则说明convertview包含tag
                                   holder= (ViewHolder) convertView.getTag();
                                }
                        //        View view=inflater.inflate(R.layout.activity_phone_list,null);
                                //实例化item布局上的控件
                        //          ImageView iv= (ImageView) view.findViewById(R.id.img_phone);
                        //          TextView tv_phonename= (TextView) view.findViewById(R.id.phone_name);
                        //          TextView tv_phoneprice= (TextView) view.findViewById(R.id.phone_price);
                        //          TextView tv_phonecounter= (TextView) view.findViewById(R.id.phone_counter);
                                //往控件上显示数据
                                //获取position对应位置的数据
                                PhoneEntity phonety= (PhoneEntity) getItem(position);
                                holder.iv.setImageResource(phonety.getImg());
                                holder.tv_phonename.setText(phonety.getName());
                                holder.tv_phoneprice.setText(phonety.getPrice());
                                holder.tv_phonecounter.setText(phonety.getCountNum());
                                return convertView;
                            }
                            class ViewHolder{
                            //ViewHolder内部类:相当于一个View视图的缓存容量池,里边记录了自定义adapter布局中所有控件的属性,不用每次重新加载自定义布局
                                public ImageView iv;
                                public  TextView tv_phonename;
                                public  TextView tv_phoneprice;
                                public TextView tv_phonecounter;
                            }


******************************************************************************************************************************************************************************                              

二、GridView的使用(展示相同图片大小的网格布局):

说明:1、GridView组件是以网格的形式显示所有的组件(大小相同),
        例如:在制作相册的时候,所有的图片都会以相同大小显示在不同的格子之中,就可以依靠此组件完成,
        让图文混排组件整体居中的方法就是在整个自定义item布局中设置
          android:gravity="center"
        此组件的继承结构如下所示:
                        java.lang.Object
                               ? android.view.View
                                   ? android.view.ViewGroup
                                       ? android.widget.AdapterView<T extends android.widget.Adapter>
                                           ? android.widget.AbsListView
                                               ? android.widget.GridView 

    2、GridView常用方法说明:
            public GridView(Context context)                                创建GridView对象

            public void setStretchMode(int stretchMode)                     android:stretchMode 缩放模式

            public void setVerticalSpacing(int verticalSpacing)             android:verticalSpacing 设置垂直间距

            public void setHorizontalSpacing(int horizontalSpacing)         android:horizontalSpacing   设置水平间距

            public void setNumColumns(int numColumns)                       android:numColumns  设置每列显示的数据量,如果设置为auto_fit则表示自动设置

            public void setSelection(int position)                          设置默认选中项

            public void setGravity(int gravity)                             android:gravity 设置对齐模式,由Gravity类指定

            public void setAdapter(ListAdapter adapter)                     设置显示图片集 

    3、代码:
            a/自定义布局样式layout:item_gridview.xml,给样例中每个控件添加id          
                <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:orientation="vertical" android:layout_width="match_parent"
                android:layout_height="match_parent">
                <ImageView
                    android:id="@+id/iv_img"
                    android:src="@drawable/benz"
                    android:layout_width="60dp"
                    android:layout_height="60dp"
                    android:layout_margin="10dp"/>
                <TextView
                    android:id="@+id/tv_name"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="奔驰"
                    android:textSize="30sp"
                    android:layout_marginLeft="10dp"/>

            b/acvitity_gridview.xml设置GridView属性,给布局文件添加id
                  <!--显示3列(auto_fit自己适应屏幕),垂直距离为30dp-->
                  <GridView
                    android:id="@+id/gv"
                    android:numColumns="3"
                    android:verticalSpacing="30dp"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"/>

            c/在Acvitity的Java代码中实例化GridView布局,并给布局构建数据源

                public class GridBarActivity extends AppCompatActivity {
                    private GridView gv;
                    private String[] names = new String[]{"长安", "沃尔沃", "大众", "宾利", "奔驰"};
                    private int[] ids = new int[]{R.drawable.changan, R.drawable.vol, R.drawable.das, R.drawable.bl, R.drawable.benz};
                    @Override
                    protected void onCreate(Bundle savedInstanceState) {
                        super.onCreate(savedInstanceState);
                        setContentView(R.layout.activity_grid_bar);
                        gv= (GridView) findViewById(R.id.gv);
                        //adapter SimpleAdapter 自定义也可
                        intiGrid();
                    }
                    private void intiGrid(){
                        //构建数据源
                        final List<Map<String,Object>> list =new ArrayList<>();
                        for (int i = 0; i <names.length ; i++) {
                            Map<String,Object> map=new HashMap<>();
                            map.put("name",names[i]);
                            map.put("img",ids[i]);
                            list.add(map);
                        }
                        String[] from=new String[]{"name","img"};
                        int[] to=new int[]{R.id.tv_name, R.id.iv_img};
                        SimpleAdapter adapter=new SimpleAdapter(this,list,R.layout.item_gridview,from,to);
                        gv.setAdapter(adapter);
                        //添加点击事件
                        gv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                            @Override
                            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                                Toast.makeText(GridBarActivity.this,"点击"+list.get(position).get("name").toString(),Toast.LENGTH_SHORT).show();
                            }
                        });
                        gv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
                            @Override
                            public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                                Toast.makeText(GridBarActivity.this,"长按"+list.get(position).get("name").toString(),Toast.LENGTH_SHORT).show();
                                return true;//不再返回上一次监听
                            }
                        }); 

**重点内容**
GridView中每个item的点击事件(将点击的item的属性设置在另一个控件上显示):(点击事件要在GridView的adapter加载后设置才会有效果,并且监听事件的返回值要设置成void,不能return view)
     gv_pig.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
                @Override
                public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
                    iv_move.setImageResource(ids[position]);
                    tv_move.setText(kind[position]);
                    return true;
                }
            });
******************************************************************************************************************************************************************************      

三、RecycleView的使用:

    说明: 1、RecyclerView:5.0之后的控件,扩展优化,吸收了ViewHolder,我们操作Recyvlerview的adapter的时候我们只操作ViewHolder
             以前listview:使用viewholder减少实例化的次数,本质上是一种实例化的方式。我们就负责创建holder.负责给holder上的控件设置数据。
            2、ViewHolder./RecyclerView的adapter与BaseAdapter不同
            3、RecyclerView的adapter:只负责创建holder,给holder设置展示的数据
            4、通过设置LayoutManager可设置展示方式  
                   rv.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));//瀑布流
                   rv.setLayoutManager(new LinearLayoutManager(this));//像ListView一样展示
                   rv.setLayoutManager(new GridLayoutManager(this, 3));//gridview
    步骤: 1、添加兼容包,依赖包 File-->project stru-->选中module,Dependes--->加号-->选择recyvlerview的包,添加。            
            2、自定义item布局
            3、创建实体类
            4、搭建数据集:List<实体类>
            5、Adapter:ViewHolder:实例化控件
                自定义Adapter步骤:
                 a、先创建一个ViewHolder的内部类MyHolder继承于ViewHolder,在内部类中实例化控件属性
                 b、让主类RecyclePhoneAdapter继承于RecycleView下的adapter并且给Adapter加上内部类的泛型
                    主要为了重写3个方法时候不用再强转返回值类型(不设置泛型返回值为父类)
                 c、新建自定义adapter完成后要在对应主Java代码中( RecyclePhoneAdapter adapter=new RecyclePhoneAdapter(this,list);)使用
                        并且设置展示样式( //设置布局管理器
                    rv_phone.setLayoutManager(new LinearLayoutManager(this));//像ListView一样展示
                    rv_phone.setAdapter(adapter);)
                    ps; //使用系统自带默认分割线
                    rv_phone.addItemDecoration(new DividerItemDecoration(this,LinearLayoutManager.VERTICAL));

     自定义Adapter代码样例:
            /**自定义adapter的作用,创建ViewHolder,给holder设置数据展示
             * 继承RecycleView.Adapter<当前类的泛型.MyHolder>,重写里边三个方法
             * Created by Administrator on 2017/2/20.
             * 步骤:1、先创建一个ViewHolder的内部类MyHolder继承于ViewHolder,在内部类中实例化控件属性
             *      2、让主类RecyclePhoneAdapter继承于RecycleView下的adapter并且给Adapter加上内部类的泛型
             *          主要为了重写3个方法时候不用再强转返回值类型(不设置泛型返回值为父类)
             *       3、新建自定义adapter完成后要在对应主Java代码中( RecyclePhoneAdapter adapter=new RecyclePhoneAdapter(this,list);)使用
             *          并且设置展示样式( //设置布局管理器
                            rv_phone.setLayoutManager(new LinearLayoutManager(this));//像ListView一样展示
                            rv_phone.setAdapter(adapter);)
                            ps; //使用系统自带默认分割线
                            rv_phone.addItemDecoration(new DividerItemDecoration(this,LinearLayoutManager.VERTICAL));
             */
            public class RecyclePhoneAdapter extends RecyclerView.Adapter<RecyclePhoneAdapter.MyHolder> implements View.OnClickListener{
                private Context pContext;
                private List<PhoneEntity> list;
                private LayoutInflater inflater;
                private OnItemClick ItemClickListener=null;
                //给自定义接口一个实例,并提供下边set方法
                public void setItemClickListener(OnItemClick itemClickListener) {
                    ItemClickListener = itemClickListener;
                }

                //有参的构造函数,并实例化布局加载器
                public RecyclePhoneAdapter(Context pContext, List<PhoneEntity> list) {
                    this.pContext = pContext;
                    this.list = list;
                    inflater=LayoutInflater.from(pContext);
                }

                @Override
                public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                    //第二个参数是容器 第三个参数:true使用父布局的布局参数,false使用自己的布局参数
                    View view=inflater.inflate(R.layout.activity_phone_list,parent,false);//使用自定义布局格式
                    MyHolder holder=new MyHolder(view);//将自定义的布局传给MyHolder内置处理
                    holder.itemView.setOnClickListener(this);//为当前item设置点击事件
                    return new MyHolder(view);
                }

                @Override
                public void onBindViewHolder(MyHolder holder, int position) {
                    //获取对应位置的数据, 不能再此重新实例化
                    PhoneEntity phone=list.get(position);
                    holder.phone_name.setText(phone.getName());
                    holder.img_phone.setImageResource(phone.getImg());
                    holder.phone_price.setText(phone.getPrice());
                    holder.phone_counter.setText(phone.getCountNum());
                    holder.itemView.setTag(position);//将item位置设置成标签,

                }

                @Override
                public int getItemCount() {
                    return list.size();
                }
                //继承自定义接口,重写自定义接口中的方法,给item添加点击事件

                @Override
                public void onClick(View v) {
                    //调用自定义接口中的方法,给当前item添加点击事件
                    if(ItemClickListener!=null){
                        ItemClickListener.onitemclick(Integer.parseInt(v.getTag().toString()));
                    }

                }

                //创建内部类继承于RecycleView.ViewHolder实例化自定义布局中的属性
                class MyHolder extends RecyclerView.ViewHolder{
                    private ImageView img_phone;
                    private TextView phone_name;
                    private TextView phone_price;
                    private  TextView phone_counter;

                    public MyHolder(View itemView) {
                        super(itemView);
                        img_phone= (ImageView) itemView.findViewById(R.id.img_phone);
                        phone_name= (TextView) itemView.findViewById(R.id.phone_name);
                        phone_price= (TextView) itemView.findViewById(R.id.phone_price);
                        phone_counter= (TextView) itemView.findViewById(R.id.phone_counter);
                    }
                }

             //有方法 我们需要知道点击的是第几个item.
            // 自定义接口,同时传入position参数设置item布局点击的是哪一个item
                public interface OnItemClick{
                    void onitemclick(int position);
                }


    自定义Adapter中自定义接口的使用步骤:
              1.在adapter中新建一个接口,接口在adapter中有一个实例,并且提供set方法
              2.在createViewHolder的时候给itemview设置点击事件this(Adapter实现了View.OnClickListener 接口).
              3.在onBindViewHolder的时候给itemview设置tag,目的是让itemview带着自己的位置,被复用后会设置新的。
              4.重写Adapter的OnClickListener方法。
                  if (ItemclickListener != null) {
                    ItemclickListener.onitemclick(Integer.parseInt(view.getTag().toString()));
                }
              5.在Activity中去使用。给adapter.setItemclickListener(匿名内部类的方式)。
                                     也可以Activity实现OnItemClick接口,重写onitemclick方法。

            代码:
                    public class RecyclePhoneAdapter extends RecyclerView.Adapter<RecyclePhoneAdapter.MyHolder> implements View.OnClickListener{
                    private Context pContext;
                    private List<PhoneEntity> list;
                    private LayoutInflater inflater;
                    private OnItemClick ItemClickListener=null;
                    //给自定义接口一个实例,并提供下边set方法
                    public void setItemClickListener(OnItemClick itemClickListener) {
                        ItemClickListener = itemClickListener;
                    }

                    //有参的构造函数,并实例化布局加载器
                    public RecyclePhoneAdapter(Context pContext, List<PhoneEntity> list) {
                        this.pContext = pContext;
                        this.list = list;
                        inflater=LayoutInflater.from(pContext);
                    }

                    @Override
                    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                        //第二个参数是容器 第三个参数:true使用父布局的布局参数,false使用自己的布局参数
                        View view=inflater.inflate(R.layout.activity_phone_list,parent,false);//使用自定义布局格式
                        MyHolder holder=new MyHolder(view);//将自定义的布局传给MyHolder内置处理
                        holder.itemView.setOnClickListener(this);//为当前item设置点击事件
                        return new MyHolder(view);
                    }

                    @Override
                    public void onBindViewHolder(MyHolder holder, int position) {
                        //获取对应位置的数据, 不能再此重新实例化
                        PhoneEntity phone=list.get(position);
                        holder.phone_name.setText(phone.getName());
                        holder.img_phone.setImageResource(phone.getImg());
                        holder.phone_price.setText(phone.getPrice());
                        holder.phone_counter.setText(phone.getCountNum());
                        holder.itemView.setTag(position);//将item位置设置成标签,

                    }

                    @Override
                    public int getItemCount() {
                        return list.size();
                    }
                    //继承自定义接口,重写自定义接口中的方法,给item添加点击事件

                    @Override
                    public void onClick(View v) {
                        //调用自定义接口中的方法,给当前item添加点击事件
                        if(ItemClickListener!=null){
                            ItemClickListener.onitemclick(Integer.parseInt(v.getTag().toString()));
                        }

                    }

                    //创建内部类继承于RecycleView.ViewHolder实例化自定义布局中的属性
                    class MyHolder extends RecyclerView.ViewHolder{
                        private ImageView img_phone;
                        private TextView phone_name;
                        private TextView phone_price;
                        private  TextView phone_counter;

                        public MyHolder(View itemView) {
                            super(itemView);
                            img_phone= (ImageView) itemView.findViewById(R.id.img_phone);
                            phone_name= (TextView) itemView.findViewById(R.id.phone_name);
                            phone_price= (TextView) itemView.findViewById(R.id.phone_price);
                            phone_counter= (TextView) itemView.findViewById(R.id.phone_counter);
                        }
                    }
                //    自定义接口,通过触发不同位置item的方式,调用接口中的方法,实现点击事件的监听效果
                    public interface OnItemClick{
                        void onitemclick(int position);
                    }















标签:GridView,浅谈,自定义,item,RecycleView,list,phone,new,public
来源: https://blog.51cto.com/u_15249199/2847166