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