zoukankan      html  css  js  c++  java
  • 015 Android RecyclerView组件和 Spinner(下拉列表框)

    1.RecyclerView 

    <1>知识点介绍

      RecyclerView 比 ListView 更高级且更具灵活性。 它是一个用于显示庞大数据集的容器,可通过保持有限数量的视图进行非常有效的滚动操作。 如果您有数据集合,其中的元素将因用户操作或网络事件而在运行时发生改变,请使用 RecyclerView 。

      RecyclerView代表的意义是,我只管Recycler View,也就是说RecyclerView只管回收与复用View,其他的你可以自己去设置。可以看出其高度的解耦,给予你充分的定制自由(所以你才可以轻松的通过这个控件实现ListView,GirdView,瀑布流等效果)

      要实现一个RecyclerView,会接触到它的几个小伙伴,其中1、2是必须的。剩下的3、4、5三项,可以让RecyclerView更好看、效果更好。

        (1)想要控制其item们的排列方式,请使用布局管理器LayoutManager

        (2)如果要创建一个适配器,请使用RecyclerView.Adapter

        (3)想要控制Item间的间隔,请使用RecyclerView.ItemDecoration

        (4)想要控制Item增删的动画,请使用RecyclerView.ItemAnimator

        (5)CardView 扩展 FrameLayout 类并让您能够显示卡片内的信息,这些信息在整个平台中拥有一致的呈现方式。CardView 小部件可拥有阴影和圆角。
      

    2. 实际案例

    <1>先将RecyclerView拖入界面

    <2>源码(对应工程名为test17

    使用RecyclerView需在build.gradle中添加声明

    implementation 'com.android.support:design:28.0.0'

    (1)XML页面布局

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout 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"
        android:orientation="vertical"
        tools:context=".recyclerview.Recycler2Activity">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <Button
                android:id="@+id/button_add"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="添加" />
    
            <Button
                android:id="@+id/button_delete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="删除" />
    
            <Button
                android:id="@+id/button_list"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="list" />
    
            <Button
                android:id="@+id/button_grid"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="grid" />
    
            <Button
                android:id="@+id/button_flow"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="flow" />
    
        </LinearLayout>
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_test1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    
    </LinearLayout>

    (2)适配器源码 

    package com.lucky.test17.recyclerview;
    
    import android.content.Context;
    import android.support.annotation.NonNull;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ImageView;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.lucky.test17.R;
    
    import java.util.ArrayList;
    
    public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder> {
    
        private final Context content;
        private final ArrayList<String> datas;
    
    
        //构造方法
        public MyRecyclerViewAdapter(Context content, ArrayList<String> datas) {
            this.content=content;
            this.datas=datas;
        }
    
        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
            View viewItem=View.inflate(content, R.layout.item_recycle,null);
            return new MyViewHolder(viewItem);
        }
    
        //数据与view绑定
        @Override
        public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i) {
            //根据位置得到对应的数据
            String str=datas.get(i);
            myViewHolder.textView.setText(str);
        }
    
        //得到总条数
        @Override
        public int getItemCount() {
            return datas.size();
        }
    
        class MyViewHolder extends RecyclerView.ViewHolder{
            ImageView imageView;
            TextView textView;
    
            public MyViewHolder(@NonNull View itemView) {
                super(itemView);
                imageView=itemView.findViewById(R.id.image1);
                textView=itemView.findViewById(R.id.test1);
                itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Toast.makeText(content,"data=="+datas.get(getLayoutPosition()),Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }
    }

    (3)分割线源码(直接调用即可)

    package com.lucky.test17.recyclerview;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.Rect;
    import android.graphics.drawable.Drawable;
    import android.support.v4.content.ContextCompat;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.view.View;
    
    /**
     * @DateTime: 2016-07-21 17:55
     * @Author: duke
     * @Deacription: recyclerview万能分割线
     */
    public class RecycleViewDivider extends RecyclerView.ItemDecoration {
    
        private Paint mPaint;//如果需要用画笔手绘
        private Drawable mDrawableDivider;//如果需要绘制给定的drawable
        private int mPaintDividerLength = 2;//分割线宽度或高度
        private DrawType drawType;//用画笔绘制颜色,还是绘制特定的drawable
        /**
         * 注意:列表的方向
         * LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL
         */
        private int mOrientation;
        //系统默认的分割线
        private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
    
        /**
         * 自定义分割线
         *
         * @param context
         * @param orientation 列表方向
         * @param drawableId  分割线图片
         */
        public RecycleViewDivider(Context context, int orientation, int drawableId) {
            if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
                throw new IllegalArgumentException("请输入正确的参数!");
            }
            mOrientation = orientation;
            if (drawableId == -100) {
                //获取系统的样式
                final TypedArray a = context.obtainStyledAttributes(ATTRS);
                mDrawableDivider = a.getDrawable(0);
                a.recycle();
            } else {
                mDrawableDivider = ContextCompat.getDrawable(context, drawableId);
            }
            //表明绘制drawable
            drawType = DrawType.USEDRAWABLE;
        }
    
        /**
         * @param context     上下文
         * @param orientation 列表方向
         */
        public RecycleViewDivider(Context context, int orientation) {
            this(context, orientation, -100);
        }
    
        /**
         * 自定义分割线
         * @param orientation   列表方向
         * @param dividerHeight 分割线高度
         * @param dividerColor  分割线颜色
         */
        public RecycleViewDivider(int orientation, int dividerHeight, int dividerColor) {
            if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) {
                throw new IllegalArgumentException("请输入正确的参数!");
            }
            mOrientation = orientation;
            if (dividerHeight != -100) {
                //分割线高度
                mPaintDividerLength = dividerHeight;
            }
            //创建特定画笔
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setColor(dividerColor);
            mPaint.setStyle(Paint.Style.FILL);
            //表明绘制用paint
            drawType = DrawType.USEPAINT;
        }
    
        /**
         * 自定义分割线
         *
         * @param orientation  列表方向
         * @param dividerColor 分割线颜色
         */
        public RecycleViewDivider(int orientation, int dividerColor) {
            this(orientation, -100, dividerColor);
        }
    
    
        /**
         * 看图说话:get Item Offsets,获得item的偏移量。此方法用来控制item的偏移
         * @param outRect
         * @param view
         * @param parent
         * @param state
         */
        @Override
        public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
            super.getItemOffsets(outRect, view, parent, state);
            /**
             * 列表的方向为横向,画分割线就是纵向的,需要确定的是child的右边偏移值
             * 留出空间画分割线
             */
            if (this.mOrientation == LinearLayoutManager.HORIZONTAL)
                switch (drawType) {
                    case USEPAINT:
                        outRect.set(0, 0, mPaintDividerLength, 0);
                        break;
                    case USEDRAWABLE:
                        outRect.set(0, 0, mDrawableDivider.getIntrinsicWidth(), 0);
                        break;
                }
            /**
             * 列表的方向为纵向,画分割线就是横向的,需要确定的是child的下边偏移值
             * 留出空间画分割线
             */
            else if (this.mOrientation == LinearLayoutManager.VERTICAL)
                switch (drawType) {
                    case USEPAINT:
                        outRect.set(0, 0, 0, mPaintDividerLength);
                        break;
                    case USEDRAWABLE:
                        outRect.set(0, 0, 0, mDrawableDivider.getIntrinsicHeight());
                        break;
                }
        }
    
        /**
         * 绘制分割线
         * @param c
         * @param parent
         * @param state
         */
        @Override
        public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
            super.onDraw(c, parent, state);
            if (mOrientation == LinearLayoutManager.VERTICAL) {
                //列表是纵向的,需要绘制横向的分割线
                drawHorizontal(c, parent);
            } else {
                //列表是横向的,需要绘制纵向的分割线
                drawVertical(c, parent);
            }
        }
    
        /**
         * 绘制横向 item 分割线。左、上、右都是可计算的,下需要获取给定的高度值
         * @param canvas
         * @param parent
         */
        private void drawHorizontal(Canvas canvas, RecyclerView parent) {
            //左边:到父容器的left内间距位置值
            final int left = parent.getPaddingLeft();
            //右边:到父容器的right内间距位置值
            final int right = parent.getMeasuredWidth() - parent.getPaddingRight();
            final int childSize = parent.getChildCount();
            //循环绘制每条分割线
            for (int i = 0; i < childSize; i++) {
                final View child = parent.getChildAt(i);
                RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
                //上边:具体的某条分割线的左边以child的(bottom+bottomMargin)位置值
                final int top = child.getBottom() + layoutParams.bottomMargin;
                //下边:根据类型判断
                int bottom;
                switch (drawType){
                    case USEPAINT://构造方法声明使用画笔绘制
                        //下边:top加上指定的高度
                        bottom = top + mPaintDividerLength;
                        if (mPaint != null) {
                            canvas.drawRect(left, top, right, bottom, mPaint);
                        }
                        break;
                    case USEDRAWABLE://构造方法声明使用drawable
                        if (mDrawableDivider != null) {
                            //下边:top加上指定的高度
                            bottom = top + mDrawableDivider.getIntrinsicHeight();
                            mDrawableDivider.setBounds(left, top, right, bottom);
                            mDrawableDivider.draw(canvas);
                        }
                        break;
                }
            }
        }
        /**
         * 绘制纵向 item 分割线。上、下、左都是可计算的,右侧需要获取给定的宽度值
         * @param canvas
         * @param parent
         */
        private void drawVertical(Canvas canvas, RecyclerView parent) {
            //上边:到父容器的top内间距位置值
            final int top = parent.getPaddingTop();
            //下边:到父容器的bottom内间距位置值
            final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom();
            final int childSize = parent.getChildCount();
            //循环绘制每条分割线
            for (int i = 0; i < childSize; i++) {
                final View child = parent.getChildAt(i);
                RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams();
                //左边:具体的某条分割线的左边以child的(right+rightMargin)位置值
                final int left = child.getRight() + layoutParams.rightMargin;
                //右边:根据类型判断
                int right;
                switch (drawType){
                    case USEPAINT://构造方法声明使用画笔绘制
                        //右边:left加上指定的宽度
                        right = left + mPaintDividerLength;
                        if (mPaint != null) {
                            canvas.drawRect(left, top, right, bottom, mPaint);
                        }
                        break;
                    case USEDRAWABLE://构造方法声明使用drawable
                        if (mDrawableDivider != null) {
                            //右边:left加上指定的宽度
                            right = left + mDrawableDivider.getIntrinsicWidth();
                            mDrawableDivider.setBounds(left, top, right, bottom);
                            mDrawableDivider.draw(canvas);
                        }
                        break;
                }
            }
        }
        public static enum DrawType {
            USEPAINT(1),//用画笔画
            USEDRAWABLE(2); //画特定的drawable
            private final int type;
            DrawType(int type) {
                this.type = type;
            }
            public int getType() {
                return type;
            }
        }
    }

    (4)主屏幕源码

    package com.lucky.test17.recyclerview;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.GridLayoutManager;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.support.v7.widget.StaggeredGridLayoutManager;
    import android.view.View;
    import android.widget.Button;
    import android.widget.LinearLayout;
    
    import com.lucky.test17.R;
    
    import java.util.ArrayList;
    
    public class Recycler2Activity extends AppCompatActivity {
    
        private Button button_add;
        private Button button_delete;
        private Button button_list;
        private Button button_grid;
        private Button button_flow;
        private RecyclerView recyclerView;
        private ArrayList<String> datas;
        private MyRecyclerViewAdapter myAdapter;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_recycler2);
            initview();
            initdata();
    
            //设置RecyclerView的适配器
            myAdapter=new MyRecyclerViewAdapter(Recycler2Activity.this,datas);
            recyclerView.setAdapter(myAdapter);
    
            //设置分割线
            recyclerView.addItemDecoration(new RecycleViewDivider(Recycler2Activity.this,LinearLayout.VERTICAL));
    
        }
    
        //设置数据集合
        private void initdata() {
            datas=new ArrayList<>();
            for (int i = 0; i <100 ; i++) {
                datas.add("content_"+i);
            }
        }
    
        private void initview() {
            button_add=findViewById(R.id.button_add);
            button_delete=findViewById(R.id.button_delete);
            button_list=findViewById(R.id.button_list);
            button_grid=findViewById(R.id.button_grid);
            button_flow=findViewById(R.id.button_flow);
            recyclerView=findViewById(R.id.recycler_test1);
    
            button_add.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                }
            });
            button_delete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                }
            });
            button_list.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //使用布局管理器LayoutManager,实现list效果
                    recyclerView.setLayoutManager(new LinearLayoutManager(Recycler2Activity.this,LinearLayoutManager.VERTICAL,false));
                }
            });
            button_grid.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //使用布局管理器LayoutManager,实现Grid效果
                    recyclerView.setLayoutManager(new GridLayoutManager(Recycler2Activity.this,3,GridLayoutManager.VERTICAL,false));
                }
            });
            button_flow.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //使用布局管理器LayoutManager,实现瀑布流效果
                    recyclerView.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL));
                }
            });
        }
    }

     <3>效果图:

    2.ListView组件(了解,可以用RecyclerView 组件替换)

    <1>介绍

    <2>XML属性

     3.Spinner(下拉列表框)

    <1>简介

    <2>xml 文件配置

    (1)列表下拉框里的内容可以写在strings.xml文件中

    <resources>
        <string name="app_name">zjzyhq</string>
        <string-array name="riskrank">
            <item>----</item>
            <item></item>
            <item></item>
            <item></item>
            <item></item>
        </string-array>
    </resources>

    (2)在屏幕布局文件中

    <Spinner
                android:entries="@array/riskrank"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">
  • 相关阅读:
    element表单中一个elformitem下多个formitem项校验(循环校验)
    vscode配置
    git push时提示错误 sign_and_send_pubkey: no mutual signature supported
    syncthing文件同步网盘配置
    MQTT服务搭建和简单使用
    python脚本避免被多次执行
    Hadoop集群对datanode宕机后的处理机制源码阅读
    工作冲突和低谷
    职场的帮助
    测试总体思想
  • 原文地址:https://www.cnblogs.com/luckyplj/p/10488897.html
Copyright © 2011-2022 走看看