Android的RecyclerView的初体验
来源:互联网 发布:美工 英文 编辑:程序博客网 时间:2024/05/02 01:29
前言:RecyclerView出来已经很久了,一直在用listView,也来尝试者在项目用一次RecyclerView,把一些心得拿出来分享一下,这里只用RecyclerView来做一个简单的列表展示,感觉还没有体现他的强大之处,相比listView,它少了分割线,点击后背景的变化,点击的回调接口,已经多了些设置。这里将:
- 列举出使用RecyclerView的基本步骤。
- 为RecyclerView添加分割线。
- 添加回调监听接口。
- 添加点击条目的水波纹效果。
一,使用RecyclerView的基本步骤:
- 添加gradle支持:
compile 'com.android.support:recyclerview-v7:23.1.1'
- 在布局文件中使用:
<android.support.v7.widget.RecyclerView android:id="@+id/rv_left_menu_content" android:layout_width="match_parent" android:layout_height="240dp"/>
- 编写条目的item;
<?xml version="1.0" encoding="utf-8"?><!--这里是引用了水波纹效果的布局,父类是一个linearLayout下面会展示源码--><com.wjustudio.phoneManager.widgt.RevealLayout android:id="@+id/item_home" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:clickable="true" android:background="@drawable/left_item_selector" android:gravity="center_vertical"> <ImageView android:id="@+id/img_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="30dp" android:src="@mipmap/icon_app"/> <TextView android:id="@+id/tv_icon_name" android:layout_weight="1" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="16dp" android:layout_toRightOf="@id/img_icon" android:text="应用管理" android:textColor="@color/textColor" android:textSize="20sp"/></com.wjustudio.phoneManager.widgt.RevealLayout></span>
- 在activity中使用,并添加相应的配置:
//先通过findviewbyid或注解的方式得到RecyclerView的对象:mRvLeftMenuContent//设置RecyclerView// 创建一个线性布局管理器LinearLayoutManager layoutManager = new LinearLayoutManager(this);//设置垂直滚动,也可以设置横向滚动layoutManager.setOrientation(LinearLayoutManager.VERTICAL);//RecyclerView设置布局管理器mRvLeftMenuContent.setLayoutManager(layoutManager);//设置侧拉菜单的recyclerView的布局mRvLeftMenuContent.setAdapter(new LeftMenuAdapter(mContext, mLeftPageIcons, windowSize));
- 编写adapter:
import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import com.wjustudio.phoneManager.R;import com.wjustudio.phoneManager.javaBean.IconInfo;import java.util.HashMap;import java.util.List;/** * 左侧菜单对应的viewHolder */public class LeftMenuAdapter extends RecyclerView.Adapter { private Context mContext; private List<IconInfo> mLeftPageIcons; private int mWindowHeight; private int mWindowWidth; public LeftMenuAdapter(Context context, List<IconInfo> leftPageIcons, HashMap<String, Integer> windowSize) { mContext = context; mLeftPageIcons = leftPageIcons; mWindowHeight = windowSize.get("height"); mWindowWidth = windowSize.get("width"); } /** * 自定义的ViewHolder,持有每个Item的的所有界面元素 */ public class NormalViewHolder extends RecyclerView.ViewHolder { ImageView icon; TextView iconName; public NormalViewHolder(View itemView) { super(itemView); icon = (ImageView) itemView.findViewById(R.id.img_icon); iconName = (TextView) itemView.findViewById(R.id.tv_icon_name); LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) icon.getLayoutParams(); params.height = mWindowHeight / 9; icon.setLayoutParams(params); params = (LinearLayout.LayoutParams) iconName.getLayoutParams(); params.width = mWindowWidth - icon.getWidth(); iconName.setLayoutParams(params); } } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //在该方法中我们创建一个ViewHolder并返回,ViewHolder必须有一个带有View的构造函数, //这个View就是我们Item的根布局,在这里我们使用自定义Item的布局; View item = View.inflate(mContext, R.layout.item_left, null); return new NormalViewHolder(item); } @Override public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { //将数据与界面进行绑定的操作 NormalViewHolder normalHolder = (NormalViewHolder) holder; normalHolder.icon.setImageResource(mLeftPageIcons.get(position).icon); normalHolder.iconName.setText(mLeftPageIcons.get(position).iconName); } } @Override public int getItemCount() { //获取数据的数量 return mLeftPageIcons == null ? 0 : mLeftPageIcons.size(); }}
windowSize放的是屏幕的宽高,这里是为了设置条目的宽度,是这样的的到的:
/** * 获得宽度和除去通知栏的屏幕的高度 * @param activity * @return */ public static HashMap<String,Integer> getWindowSize(Activity activity){ WindowManager wm = activity.getWindowManager(); DisplayMetrics metrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(metrics); int width = metrics.widthPixels; int height = metrics.heightPixels; height -= getStatusBarHeight(activity); HashMap<String,Integer> windowSize = new HashMap<>(); windowSize.put("height",height); windowSize.put("width",width); return windowSize; } /** * 获得状态栏的高度 * @param activity * @return */ public static int getStatusBarHeight(Activity activity){ int statusHeight = 0; Rect frame = new Rect(); activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame); statusHeight = frame.top; if (0 == statusHeight){ Class<?> localClass; try { localClass = Class.forName("com.android.internal.R$dimen"); Object localObject = localClass.newInstance(); int i5 = Integer.parseInt(localClass.getField("status_bar_height"). get(localObject).toString()); statusHeight = activity.getResources().getDimensionPixelSize(i5); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } } return statusHeight; }
二,为RecyclerView添加分割线:
编写类
package com.wjustudio.phoneManager.widgt;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;/** * This class is from the v7 samples of the Android SDK. It's not by me! * <p/> * See the license above for details. */public class DividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[]{ android.R.attr.listDivider }; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; private Drawable mDivider; private int mOrientation; public DividerItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); } public void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException("invalid orientation"); } mOrientation = orientation; } @Override public void onDraw(Canvas c, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } public void drawVertical(Canvas c, RecyclerView parent) { 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); android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext()); 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); } } public void drawHorizontal(Canvas c, RecyclerView parent) { 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, int itemPosition, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } }}
在RecyclerView中添加:
//添加分割线mRvLeftMenuContent.addItemDecoration(new DividerItemDecoration( this, DividerItemDecoration.VERTICAL_LIST));
三,添加回调监听接口:
/** * 点击事件的监听接口 */ public interface OnItemClickListener{ void onItemClick(View view, int position); } private OnItemClickListener mOnItemClickLitener; public void setOnItemClicklistener(OnItemClickListener listener){ mOnItemClickLitener = listener; }
@Overridepublic void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { //将数据与界面进行绑定的操作 NormalViewHolder normalHolder = (NormalViewHolder) holder; normalHolder.icon.setImageResource(mLeftPageIcons.get(position).icon); normalHolder.iconName.setText(mLeftPageIcons.get(position).iconName); if (mOnItemClickLitener != null){ holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mOnItemClickLitener.onItemClick(holder.itemView,position); } }); }}
四,添加条目点击的水波纹效果:
package com.wjustudio.phoneManager.widgt;import android.annotation.TargetApi;import android.content.Context;import android.graphics.Canvas;import android.graphics.Paint;import android.os.Build;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.widget.LinearLayout;import com.wjustudio.phoneManager.R;import java.util.ArrayList;public class RevealLayout extends LinearLayout implements Runnable{private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);private float mCenterX,mCenterY;private int[] mLocation = new int[2];private int INVALIDATE_DURATION = 40;private int mTargetHeight,mTargetWidth;private int mRevealRadius = 0,mRevealRadiusGap,mMaxRadius;private int mMinBetweenWidthAndHeight,mMaxBetweenWidthAndHeight;private boolean mIsPressed;private boolean mShouldDoAnimation;private View mTargetView;private DispatchUpTouchEventRunnable mDispatchUpTouchEventRunnable = new DispatchUpTouchEventRunnable();public RevealLayout(Context context) {super(context);init();}public RevealLayout(Context context, AttributeSet attrs){super(context,attrs);init();}@TargetApi(Build.VERSION_CODES.HONEYCOMB)public RevealLayout(Context context, AttributeSet attrs, int defStyleAttr){super(context,attrs,defStyleAttr);init();}public void init(){setWillNotDraw(false);mPaint.setColor(getResources().getColor(R.color.reveal_color));}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);this.getLocationOnScreen(mLocation);}@Overrideprotected void dispatchDraw(Canvas canvas) {super.dispatchDraw(canvas);if(mTargetView == null || !mShouldDoAnimation || mTargetWidth <= 0)return;if(mRevealRadius > mMinBetweenWidthAndHeight / 2)mRevealRadius += mRevealRadiusGap * 4;elsemRevealRadius += mRevealRadiusGap;int[] location = new int[2];this.getLocationOnScreen(mLocation);mTargetView.getLocationOnScreen(location);int top = location[1] - mLocation[1];int left = location[0] - mLocation[0];int right = left + mTargetView.getMeasuredWidth();int bottom = top + mTargetView.getMeasuredHeight();canvas.save();canvas.clipRect(left, top, right, bottom);canvas.drawCircle(mCenterX, mCenterY, mRevealRadius, mPaint);canvas.restore();if(mRevealRadius <= mMaxRadius)postInvalidateDelayed(INVALIDATE_DURATION, left, top, right, bottom);else if(!mIsPressed){mShouldDoAnimation = false;postInvalidateDelayed(INVALIDATE_DURATION, left, top, right, bottom);}}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {int x = (int)event.getRawX();int y = (int)event.getRawY();int action = event.getAction();switch(action){case MotionEvent.ACTION_DOWN:View targetView = getTargetView(this,x,y);if(targetView != null && targetView.isEnabled()){mTargetView = targetView;initParametersForChild(event,targetView);postInvalidateDelayed(INVALIDATE_DURATION);}break;case MotionEvent.ACTION_UP:mIsPressed = false;postInvalidateDelayed(INVALIDATE_DURATION);mDispatchUpTouchEventRunnable.event = event;postDelayed(mDispatchUpTouchEventRunnable, 40);break;case MotionEvent.ACTION_CANCEL:mIsPressed = false;postInvalidateDelayed(INVALIDATE_DURATION);break;}return super.dispatchTouchEvent(event);}public View getTargetView(View view,int x,int y){View target = null;ArrayList<View> views = view.getTouchables();for(View child : views)if(isTouchPointInView(child,x,y)){target = child;break;}return target;}public boolean isTouchPointInView(View child,int x,int y){int[] location = new int[2];child.getLocationOnScreen(location);int top = location[1];int left = location[0];int right = left + child.getMeasuredWidth();int bottom = top + child.getMeasuredHeight();if(child.isClickable() && y>=top && y<= bottom && x >= left && x<= right)return true;elsereturn false;}public void initParametersForChild(MotionEvent event,View view){mCenterX = event.getX();mCenterY = event.getY();mTargetWidth = view.getMeasuredWidth();mTargetHeight = view.getMeasuredHeight();mMinBetweenWidthAndHeight = Math.min(mTargetWidth, mTargetHeight);mMaxBetweenWidthAndHeight = Math.max(mTargetWidth, mTargetHeight);mRevealRadius = 0;mRevealRadiusGap = mMinBetweenWidthAndHeight / 8;mIsPressed = true;mShouldDoAnimation = true;int[] location = new int[2];view.getLocationOnScreen(location);int left = location[0] - mLocation[0];int mTransformedCenterX = (int)mCenterX - left;mMaxRadius = Math.max(mTransformedCenterX, mTargetWidth - mTransformedCenterX);}@Overridepublic void run() {super.performClick();}@Overridepublic boolean performClick() {postDelayed(this,40);return true;}private class DispatchUpTouchEventRunnable implements Runnable{public MotionEvent event;@Overridepublic void run() {if(mTargetView.isEnabled() && mTargetView.isClickable())return;if(isTouchPointInView(mTargetView, (int)event.getRawX(), (int)event.getRawX()))mTargetView.performClick();}}}
使用这个类作为条目的父控件就可以了。
点击的时候为了有颜色变化还应该为条目设置背景的selector:
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/reveal_color" android:state_pressed="true"/> <item android:drawable="@drawable/reveal_color" android:state_checked="true"/> <item android:drawable="@drawable/left_bg_color"/></selector>对应的颜色值为:
<drawable name="reveal_color">#1b000000</drawable> <drawable name="left_bg_color">#E7E5E4</drawable>
RecycleView中替代ListView中的setselection的方法:
((LinearLayoutManager)mRecyclerView.getLayoutManager()).scrollToPositionWithOffset(i,0);
其中的i表示第i个条目,0表示偏移的像素数。
1 0
- Android的RecyclerView的初体验
- Android RecyclerView初体验
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- Android RecyclerView 使用完全解析 体验艺术般的控件
- [从头学数学] 第112节 一元一次方程
- C++:private成员的访问
- Android手机号码归属地的查询(使用聚合数据API,获取JSON数据并解析)
- 【leetcode】【12】Integer to Roman
- 架构上的些许积累
- Android的RecyclerView的初体验
- hadoop2.5.2 mahout0.10.1 测试文本分类器
- ViewPager的notifiedDataChange
- jdoj 1930 慈善的约瑟夫 递推 数学做法
- 响应式web设计之CSS3 Media Queries
- 【慕课笔记】第五章 JAVA中的集合框架(中) 第1节 Map&HashMap简介
- 知乎登陆脚本
- 格式化数据#8: AIE实验室交流群推荐的相关书籍(附豆瓣链接和ISBN)
- spark RDD详解