色yeye在线视频观看_亚洲人亚洲精品成人网站_一级毛片免费播放_91精品一区二区中文字幕_一区二区三区日本视频_成人性生交大免费看

當前位置:首頁 > 嵌入式培訓 > 嵌入式學習 > 講師博文 > RecyclerView 學習筆記(一)---實現ListView

RecyclerView 學習筆記(一)---實現ListView 時間:2018-09-26      來源:未知

RecyclerView和ListView一樣,都是做列表顯示View子項的控件,它比ListView更高效和自由。

解析RecycleView,Recycle View,意思就是該控件只管回收和顯示View子項,而對于如何顯示,顯示什么,它是不關心的,這給開發過程帶來了極大的便利,比如ListView只能作為單列的列表顯示,GridView將一個界面表格化,通常情況下GridView通過強制View子項的寬度來顯示,在橫豎屏切換時的效果很差。

而RecycleView可以實現:

ListView的功能

GridView的功能

橫向ListView的功能

橫向ScrollView的功能

瀑布流的功能

添加和刪除View子項

這些功能,非常強大,可以看出,它幾乎可以替代所有的動態布局控件。

這么強大的動態布局控件,得益于它的高度解耦,同樣,眾所周知,高度解耦,就意味著復雜度提升,相較于ListView、GridView等控件,RecycleView才實現過程是相對較復雜的。

RecyclerView的適配器需要繼承自RecyclerView.Adapter,在該適配器將要面向ViewHolder,也就是說,它內部已經實現了緩存復用。

實現LIstView功能

注意,RecyclerView是谷歌在support-v7包中添加的新組件,在開發的時候,請添加support.v7包以及recyclerview-v7包,在module的Project Structure中的Dependencies部分添加如下圖所示:

首先創建RecyclerViewDemo1,活動:RecyclerViewDemo.java,layout:activiy_main.xml。

簡單通過RecyclerView實現ListView的功能,那么首先就要理解ListView的實現過程。ListView是通過列表的的形式依次顯示一行行的數據,從編程的角度出發,就是一個LinnerLayout布局,方向為縱向,依次添加進數據,后通過Scrolling實現滾動屏幕。

再來對比RecyclerView,屏幕滾動部分,在RecyclerView中已經被實現好了,不需要關心,需要關心的就是布局,以及方向。

Java Code

recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

//設置RecyclerView的布局管理器,為了模仿ListView,

//這里設置為Vertical的LinnerLayout

LinearLayoutManager manager = new LinearLayoutManager(this);

manager.setOrientation(OrientationHelper.VERTICAL);

recyclerView.setLayoutManager(manager);

上述代碼第5行,定義了一個LinearLayoutManager,傳入上下文為活動的this,第6行將布局管理器的方向設置為VERTICAL,第7行,將這個布局管理器傳遞給RecyclerView。

對比ListView,這個時候我們只是擁有了一個ListView實例,數據源,適配器,以及View子項都還沒有說明。

接下來,創建一個View子項,這個View子項可以顯示一張圖片,以及一段文字,可以使用一個TextView,當然為了自由度,將聲明兩個控件,一個TextView、一個ImageView,分別用來顯示文字和圖片。

子View還是通過xml文件來定義。

XML Code

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="//schemas.android.com/apk/res/android"

android:orientation="horizontal" android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="@drawable/bg">

<ImageView

android:id="@+id/img_item"

android:layout_width="50dp"

android:layout_height="50dp" />

<TextView

android:id="@+id/txv_item"

android:gravity="center_vertical|center_horizontal"

android:textSize="21sp"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

</LinearLayout>

上述代碼第7行和第11行,分別定義了一個ImageView和一個TextView,第4行,將打下限定在了wrap_content,View子項的大小可控。

四大組成部分中,已經實現了兩部分,接下來是數據源,因為是一個Demo,這里數據源我們使用一個包含一個String和一個圖片Id的HashMap來實現。

Java Code

public HashMap getImgHash()

{

HashMapimgHash = new HashMap<>();

imgHash.put("0000", R.drawable.zero);

imgHash.put("1111", R.drawable.one);

imgHash.put("2222", R.drawable.two);

imgHash.put("3333", R.drawable.three);

imgHash.put("4444", R.drawable.four);

imgHash.put("5555", R.drawable.five);

imgHash.put("6666", R.drawable.six);

imgHash.put("7777", R.drawable.seven);

imgHash.put("8888", R.drawable.eight);

imgHash.put("9999", R.drawable.nine);

imgHash.put("aaaa", R.drawable.a);

imgHash.put("bbbb", R.drawable.b);

imgHash.put("cccc", R.drawable.c);

imgHash.put("dddd", R.drawable.d);

imgHash.put("eeee", R.drawable.e);

imgHash.put("ffff", R.drawable.f);

return imgHash;

}

RecyclerView實例有了,數據源有了,View子項有了,只剩下適配器將這些東西串聯起來了。

RecyclerView的Adapter,通常使用的是自定義的,這是由RecyclerView高度解耦,高度自由決定的,高度解耦意味著編碼復雜度上升。

在創建Adapter的時候,繼承自RecyclerView.Adapter,不過在這之前,請先建立一個自定義的ViewHolder類,這是因為,在RecyclerView的編碼過程中,緩存部分的工作已經交由RecyclerView做好了,那么緩存什么,View子項是什么,需要程序員告知它。

Java Code

//自定義的ViewHolder

class MyViewHolder extends RecyclerView.ViewHolder{

public ImageView img;

public TextView textView;

public MyViewHolder(View itemView) {

super(itemView);

img = (ImageView) itemView.findViewById(R.id.img_item);

textView = (TextView) itemView.findViewById(R.id.txv_item);

}

}

編寫自定義適配器。

Java Code

public class MyAdapter extends RecyclerView.Adapter{

private Context context;

private List nameList;

private List imgList;

private LayoutInflater inflater;

private OnItemClickListener onItemClickListener;

//自定義構造器,傳入上下文和數據源

public MyAdapter(Context context, HashMap imgHash) {

this.context = context;

imgList = new ArrayList<>();

nameList = new ArrayList<>();

for (Object o : imgHash.entrySet()){

Map.Entry entry = (Map.Entry) o;

String name = (String) entry.getKey();

int img = (int) entry.getValue();

nameList.add(name);

imgList.add(nameList.indexOf(name), img);

}

inflater = LayoutInflater.from(context);

}

//面向ViewHolder編程

@Override

public MyViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

//View子項

View view = inflater.inflate(R.layout.item_recycler, viewGroup, false);

return new MyViewHolder(view);

  }

//面向ViewHolder編程

@Override

public void onBindViewHolder(MyViewHolder myViewHolder,

@SuppressLint("RecyclerView") final int i) {

//對View子項賦值

myViewHolder.img.setImageResource(imgList.get(i));

myViewHolder.textView.setText(nameList.get(i));

}

@Override

public int getItemCount() {

return nameList.size();

}

//自定義的ViewHolder

class MyViewHolder extends RecyclerView.ViewHolder{

public ImageView img;

public TextView textView;

//和View子項真正建立連接

public MyViewHolder(View itemView) {

super(itemView);

img = (ImageView) itemView.findViewById(R.id.img_item);

textView = (TextView) itemView.findViewById(R.id.txv_item);

}

}

}

四大組成部分已經編寫完成,接下來,

myAdapter = new MyAdapter(this, imgHash);

recyclerView.setAdapter(myAdapter);

完成適配器配置。

來看一下現象如下圖所示:

和ListView的效果很像,已經將數據完整的顯示在活動中,但是仔細看,會發現,View子項和View子項之間沒有明顯的分隔。并沒有ListView中的分隔的效果。

對于RecyclerView來說,添加分隔線也是耦合事件,所以,當想要分隔線的時候,需要自己添加。需要添加recyclerView.addItemDecoration()方法添加分隔線。該方法的參數需要一個RecycleView.ItemDecoration實例,該類是一個abstract的虛類,要實現該類需要做自定義操作,谷歌并沒有提供默認的實現。

創建MyItemDecoration繼承自RecyclerView.ItemDecoration,觀察該類,需要重寫其onDraw方法,getItemOffsets方法。

Java Code

package com.hqyj.dev.recyclerviewdemo1;

import android.content.Context;

import android.content.res.TypedArray;

import android.graphics.Canvas;

import android.graphics.Rect;

import android.graphics.drawable.Drawable;

import android.support.v7.widget.LinearLayoutManager;

import android.support.v7.widget.RecyclerView;

import android.view.View;

/**

* Created by jiyangkang on 2016/7/15 0015.

*/

public class MyItemDecoration extends RecyclerView.ItemDecoration {

private static final int[] ATTRS = new int[]{

android.R.attr.listDivider

};

private static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;

private static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;

private Drawable mDivider;

private int mOrientation;

//構造器,從參數離別中拿出要繪制的Drawable

public MyItemDecoration(Context context, int orientation) {

//參數列表

final TypedArray a = context.obtainStyledAttributes(ATTRS);

//參數列表0項

mDivider = a.getDrawable(0);

//使用完參數列表之后一定要做recycle()

a.recycle();

try {

setmOrientation(orientation);

} catch (IllegalAccessException e) {

e.printStackTrace();

}

}

//選擇繪制什么樣的分隔線

@Override

public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {

super.onDraw(c, parent, state);

if (mOrientation == VERTICAL_LIST) {

drawVertiacl(c, parent, state);

} else {

drawHorizontal(c, parent, state);

}

}

public void setmOrientation(int orientation) throws IllegalAccessException {

if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {

throw new IllegalAccessException("invalid orientation");

}

mOrientation = orientation;

}

//縱向排列的View子項

public void drawVertiacl(Canvas c, RecyclerView parent, RecyclerView.State state) {

final int left = parent.getPaddingLeft();

final int right = parent.getWidth() - parent.getPaddingRight();

final int childCount = parent.getChildCount();

for (int i = 0; i < childCount; i++) {

final View child = parent.getChildAt(i);

final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

final int top = child.getBottom() + params.bottomMargin;

final int bottom = top + mDivider.getIntrinsicHeight();

mDivider.setBounds(left, top, right, bottom);

mDivider.draw(c);

}

}

//橫向排列的View子項

public void drawHorizontal(Canvas c, RecyclerView parent, RecyclerView.State state) {

final int top = parent.getPaddingTop();

final int bottom = parent.getHeight() - parent.getPaddingBottom();

final int childCount = parent.getChildCount();

for (int i = 0; i < childCount; i++) {

final View child = parent.getChildAt(i);

final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

final int left = child.getRight() + params.rightMargin;

final int right = left + mDivider.getIntrinsicHeight();

mDivider.setBounds(left, top, right, bottom);

mDivider.draw(c);

}

}

@Override

public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {

super.getItemOffsets(outRect, view, parent, state);

if (mOrientation == VERTICAL_LIST) {

outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());

} else {

outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);

}

}

}

自定義ItemDecoration寫好厚,就可以將其添加到RecyclerView中了。

添加recyclerView.addItemDecoration(new MyItemDecoration(this, LinearLayoutManager.VERTICAL));帶活動的onCreate方法中。

再看展示的效果圖,如下圖:

可以看到,已經有分隔線了,這個分隔線是我們在ATTRS中放入的第0個Drawable的id,我們知道它是來自android.R的,即系統集成的,使用該分隔線的一個好處就是,我們可以對其進行自定義。

在res下的drawable目錄下創建一個shap,來設置一個漸變drawable.

XML Code

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="//schemas.android.com/apk/res/android"

android:shape="rectangle" >

<gradient

android:centerColor="#ff00ff00"

android:startColor="#ff0000ff"

android:endColor="#ffff0000"/>

<size android:height="2dp"/>

</shape>

然后在styles.xml中為工程的AppTheme中添加一個android:listDivider子項,為listDivider賦值為定義好的drawable。

效果圖如下:

這樣的效果已經和ListView很像了,但是,在點擊對應的View子項的時候,會發現,是沒有效果的,這是因為RecyclerView中,并沒有和ListView一樣的OnItemClickLisener接口。

還是因為RecyclerView高度解耦的緣故,而自定義監聽將更加自由。在Adapter中添加一個接口,用以監聽按鈕事件。

Java Code

public interface OnItemClickListener

{

void onClick(int position, String name, int imgSource);

void onLongClick(int position, String name, int imgSource);

}

public void setOnItemClickListener(OnItemClickListener onItemClickListener)

{

this.onItemClickListener = onItemClickListener;

}

@Override

public void onBindViewHolder(MyViewHolder myViewHolder, @SuppressLint("RecyclerView") final int i)

{

myViewHolder.img.setImageResource(imgList.get(i));

myViewHolder.textView.setText(nameList.get(i));

if (onItemClickListener != null)

{

myViewHolder.itemView.setOnClickListener(new View.OnClickListener()

{

@Override

public void onClick(View view)

{

onItemClickListener.onClick(i, nameList.get(i), imgList.get(i));

}

});

myViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener()

{

@Override

public boolean onLongClick(View view)

{

//onItemClickListener.onLongClick(i, nameList.get(i), imgList.get(i));

//removeData(i);

return false;

}

});

}

}

在調用Adapter的部分添加

Java Code

myAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener()

{

@SuppressLint("DefaultLocale")

@Override

public void onClick(int position, String name, int imgSource)

{

textView.setText(String.format("%d is clicked, %s is contained", position, name));

}

@SuppressLint("DefaultLocale")

@Override

public void onLongClick(int position, String name, int imgSource)

{

textView.setText(String.format("%d is Long clicked, %s is contained", position, name));

}

});

到此,點擊事件也已經注冊到活動中,點擊每個View子項都已經有相應。

但是,還有一個問題,點擊事件發生的時候,View子項沒有任何反應,位View子項添加一個background,在Drawable里邊頂一個selector。就可以實現點擊事件發生時改變背景顏色的功能。

XML Code

<?xml version="1.0" encoding="utf-8"?>

<selector xmlns:android="//schemas.android.com/apk/res/android" >

<item android:state_pressed="true"

android:drawable="@color/colorBg_press"/>

<item android:drawable="@color/colorBg_default"/>

</selector>

至此,一個仿照的ListView就被實現出來了,而且更具靈活性,也更生動。

在靈活性上,一個很重要的體現就是,可以任意的增加和刪除View子項。在上述的代碼中其實已經可以看見一部分了,在長按的監聽事件中,長按發生時,會將對應的View子項從列表中刪除。

Java Code

public void removeData(int position){

nameList.remove(position);

imgList.remove(position);

notifyItemRemoved(position);

notifyDataSetChanged();//必須添加

}

notifyItemRemoved方法即為刪除方法。同樣的,還有一個為notifyItemInser(int position)的方法,用以插入一個View子項。View子項也是可以移動的,方法為notifyItemMove(int fromPosition, int toPosition)。

上一篇:談談socket 套接字

下一篇:異步通信和同步通信簡單對比

熱點文章推薦
華清學員就業榜單
高薪學員經驗分享
熱點新聞推薦
前臺專線:010-82525158 企業培訓洽談專線:010-82525379 院校合作洽談專線:010-82525379 Copyright © 2004-2022 北京華清遠見科技集團有限公司 版權所有 ,京ICP備16055225號-5京公海網安備11010802025203號

回到頂部

主站蜘蛛池模板: 午夜dj视频免费观看www | 波多野结衣中文AV无码专区 | 在线永久免费观看日韩a | 又黄又爽的视频在线观看网站 | 成年男人裸j网站 | 欧美丰满熟妇VAIDEOS | 美女高潮无套内谢视频免费 | 日本成人免费在线观看 | 亚洲精品无码久久久久av麻豆 | 热久久最新网站获取 | 高清精品一区二区三区 | 国产成人理论在线观看视频 | 国产最新无码AⅤ在线播放 亚州视频一区二区三区 | a级国产视频 | 国产精品久久久久久久日韩 | 一本到无码AV专区无码 | 一二三四在线看日本高清 | 欧美人与物ⅴideos另类 | 袖珍幻女bbwxxxx | 好硬啊进去太深了A片 | 国产成人aa在线视频 | 亚洲国产成人无码av在线 | 精品国产SM捆绑最大网免费站 | 国产成人无码一区二区在线播放 | 亚洲色精品三区二区一区 | 日本少妇寂寞少妇aaa | 中文欧美字幕 | 国产免费一区二区三区VR | 裸体美女扒开下部无遮挡网站免费 | 成人无码免费一区二区三区 | 97超碰人人爱香蕉精品 | 精品无码免费专区毛片 | 亚洲人成网站18禁止人 | 成人乱码免费视频A片含羞草传媒 | 免费无码无遮挡裸体视频在线观看 | 香蕉成人国产精品免费看网站 | 国产精品嫩草影院一二三区入口 | 精品无人区卡一卡二卡三 | 国产在线无码视频一区二区三区 | 久久精品国产99国产精品导航 | 亚洲日韩欧洲无码AV夜夜摸 |