• 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">
  • 相关阅读:
    Apache 虚拟主机 VirtualHost 配置
    EAX、ECX、EDX、EBX寄存器的作用
    Python中文文档 目录(转载)
    八度
    POJ 3268 Silver Cow Party (最短路)
    POJ 2253 Frogger (求每条路径中最大值的最小值,Dijkstra变形)
    2013金山西山居创意游戏程序挑战赛——复赛(1) HDU 4557 非诚勿扰 HDU 4558 剑侠情缘 HDU 4559 涂色游戏 HDU 4560 我是歌手
    HDU 4549 M斐波那契数列(矩阵快速幂+欧拉定理)
    UVA 11624 Fire! (简单图论基础)
    HDU 3534 Tree (树形DP)
  • 原文地址:https://www.cnblogs.com/luckyplj/p/10488897.html
Copyright © 2020-2023  润新知