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">

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM