android 5.0新特性学习--RecyclerView

时间:2022-05-07 01:16:57

在过去很多年,我们的PC或者手机设备都是采用拟物化的设计风格,IOS采用扁平化的特性,android在2014年IO大会上说采用Material Design的设计风格,显示效果不能过于生硬的转换,而是平滑,过度的切换方式,避免线性的动画效果,而是代替以曲线的效果进行展示,并且所有的图标的动画切换都应该无缝化切换。

如果想深入了解材料设计即(material Design)的设计:

可以参看如下网址:http://design.1sters.com,尤其是android 应用的UED设计师们,可以看下:

开发中要在libs文件夹下面中加上android_support_v4.jar包

RecyclerView

java.lang.Object
  android.view.View
    android.view.ViewGroup
      android.support.v7.widget.RecyclerView

官网地址:https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html

RecyclerView 一个特点就是,将 layout 抽象成了一个 LayoutManager,RecylerView 不负责子 View 的布局, 我们可以自定义 LayoutManager 来实现不同的布局效果, 目前只提供了LinearLayoutManager。 LinearLayoutManager 可以指定方向,默认是垂直, 可以指定水平, 这样就轻松实现了水平的 ListView。

除了LinearLayoutManager还有其他两种布局管理器:

GridLayoutManager 网格的item
StaggeredGridLayoutManager 交错的网格item

当然也可以通过集成ResyclerView,layoutManager类来自定义自己的布局管理器。

RecyclerView的使用过程中会使用到一个Adapter:RecyclerView.Adapter,里面屏蔽了以前写BaseAdapter的中好多重读的代码的编写,将加载item布局放在onCreateViewHolder(ViewGroup viewGroup, int i)方法中,在onBindViewHolder(ViewHolder viewHolder, int i)中数据加载到item中。用于优化的viewHolder也是继承自RecyclerView.ViewHolder。

RecyclerView不提供setOnItemClickListener方法,你可以在ViewHolder中添加事件。

RecyclerView之间的分割线:

http://my.oschina.net/xesam/blog/351408

官网地址:https://developer.android.com/reference/android/support/v7/widget/RecyclerView.Adapter.html

关于使用可以参考:

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0710/1631.html

http://blog.csdn.net/cym492224103/article/details/41719497

编写demo:

android 5.0新特性学习--RecyclerView

布局文件:

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.wangfubin.recyclerview.MainActivity"> <android.support.v7.widget.RecyclerView
android:id="@+id/id_recyclerview"
android:divider="#ffff0000"
android:dividerHeight="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
item_gridview.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
xmlns:tool="http://schemas.android.com/tools"
android:background="#44ff0000"
android:layout_height="100dp"> <TextView
android:id="@+id/id_num"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
tool:text="1" />
</FrameLayout>
item_listview.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
xmlns:tool="http://schemas.android.com/tools"
android:background="#44ff0000"
android:layout_height="wrap_content"> <TextView
android:id="@+id/id_num"
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center"
tool:text="1" />
</FrameLayout>
MainActivity.java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast; import java.util.ArrayList;
import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView;
private List<String> mDatas;
private HomeAdapter mAdapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initData();
mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
//垂直线性RecyclerView
//mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); //Grid布局
//mRecyclerView.setLayoutManager(new GridLayoutManager(this,4)); //瀑布流
//垂直方向
//mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL));
//水平方向
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.HORIZONTAL)); mRecyclerView.setAdapter(mAdapter = new HomeAdapter(getApplicationContext(),initData()));
//垂直线性RecyclerView分割线
//mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST)); //GridView的分隔线
mRecyclerView.addItemDecoration(new DividerGridItemDecoration(this));
//添加默认动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mAdapter.setOnItemClickLitener(new HomeAdapter.OnItemClickLitener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(getApplicationContext(),"单击事件",Toast.LENGTH_SHORT).show();
} @Override
public void onItemLongClick(View view, int position) {
Toast.makeText(getApplicationContext(),"长按事件",Toast.LENGTH_SHORT).show();
}
}); } /**
* 初始化模拟数据
* @return
*/
protected List<String> initData() {
mDatas = new ArrayList<String>();
for (int i = 'A'; i < 'z'; i++) {
mDatas.add("" + (char) i);
}
return mDatas;
} @Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
} @Override
public boolean onOptionsItemSelected(MenuItem item)
{
switch (item.getItemId())
{ case R.id.id_action_add:
//新增数据
mAdapter.addData(1);
break;
case R.id.id_action_delete:
//删除数据
mAdapter.removeData(1);
break;
}
return true;
} }

HomeAdapter.java

import java.util.List;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.widget.TextView; /**
* Created by wangfubin on 2016/11/12.
*/ class HomeAdapter extends RecyclerView.Adapter<HomeAdapter.MyViewHolder>
{ private List<String> mDatas;
private LayoutInflater mInflater; public interface OnItemClickLitener
{
void onItemClick(View view, int position);
void onItemLongClick(View view , int position);
} private OnItemClickLitener mOnItemClickLitener; public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener)
{
this.mOnItemClickLitener = mOnItemClickLitener;
} public HomeAdapter(Context context, List<String> datas)
{
mInflater = LayoutInflater.from(context);
mDatas = datas;
} @Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
MyViewHolder holder = new MyViewHolder(mInflater.inflate(
R.layout.item_listview, parent, false));
return holder;
} @Override
public void onBindViewHolder(final MyViewHolder holder, final int position)
{
holder.tv.setText(mDatas.get(position)); // 如果设置了回调,则设置点击事件
if (mOnItemClickLitener != null)
{
holder.itemView.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View v)
{
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemClick(holder.itemView, pos);
}
}); holder.itemView.setOnLongClickListener(new OnLongClickListener()
{
@Override
public boolean onLongClick(View v)
{
int pos = holder.getLayoutPosition();
mOnItemClickLitener.onItemLongClick(holder.itemView, pos);
removeData(pos);
return false;
}
});
}
} @Override
public int getItemCount()
{
return mDatas.size();
} public void addData(int position)
{
mDatas.add(position, "Insert One");
notifyItemInserted(position);
} public void removeData(int position)
{
mDatas.remove(position);
notifyItemRemoved(position);
} class MyViewHolder extends ViewHolder
{ TextView tv; public MyViewHolder(View view)
{
super(view);
tv = (TextView) view.findViewById(R.id.id_num); }
}
}
DividerItemDecoration.java
/**
* 垂直水平分割线
*/
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) {
Log.v("recyclerview - itemdecoration", "onDraw()"); 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);
}
}
}
DividerGridItemDecoration.java
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.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.LayoutManager;
import android.support.v7.widget.RecyclerView.State;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.View; /**
*GridView分割线
* @author zhy
*
*/
public class DividerGridItemDecoration extends RecyclerView.ItemDecoration
{ private static final int[] ATTRS = new int[] { android.R.attr.listDivider };
private Drawable mDivider; public DividerGridItemDecoration(Context context)
{
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
} @Override
public void onDraw(Canvas c, RecyclerView parent, State state)
{ drawHorizontal(c, parent);
drawVertical(c, parent); } private int getSpanCount(RecyclerView parent)
{
// 列数
int spanCount = -1;
LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{ spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
spanCount = ((StaggeredGridLayoutManager) layoutManager)
.getSpanCount();
}
return spanCount;
} public void drawHorizontal(Canvas c, RecyclerView parent)
{
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.getLeft() - params.leftMargin;
final int right = child.getRight() + params.rightMargin
+ mDivider.getIntrinsicWidth();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
} public void drawVertical(Canvas c, RecyclerView parent)
{
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.getTop() - params.topMargin;
final int bottom = child.getBottom() + params.bottomMargin;
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicWidth(); mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
} private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
int childCount)
{
LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
if (orientation == StaggeredGridLayoutManager.VERTICAL)
{
if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
{
return true;
}
} else
{
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
return true;
}
}
return false;
} private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
int childCount)
{
LayoutManager layoutManager = parent.getLayoutManager();
if (layoutManager instanceof GridLayoutManager)
{
childCount = childCount - childCount % spanCount;
if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
return true;
} else if (layoutManager instanceof StaggeredGridLayoutManager)
{
int orientation = ((StaggeredGridLayoutManager) layoutManager)
.getOrientation();
// StaggeredGridLayoutManager 且纵向滚动
if (orientation == StaggeredGridLayoutManager.VERTICAL)
{
childCount = childCount - childCount % spanCount;
// 如果是最后一行,则不需要绘制底部
if (pos >= childCount)
return true;
} else
// StaggeredGridLayoutManager 且横向滚动
{
// 如果是最后一行,则不需要绘制底部
if ((pos + 1) % spanCount == 0)
{
return true;
}
}
}
return false;
} @Override
public void getItemOffsets(Rect outRect, int itemPosition,
RecyclerView parent)
{
int spanCount = getSpanCount(parent);
int childCount = parent.getAdapter().getItemCount();
if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
{
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
} else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
{
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else
{
outRect.set(0, 0, mDivider.getIntrinsicWidth(),
mDivider.getIntrinsicHeight());
}
}
}

效果:

android 5.0新特性学习--RecyclerView

android 5.0新特性学习--RecyclerView的更多相关文章

  1. android 5&period;0新特性学习--视图阴影

    android 5.0的视图阴影主要是体验出层次性,就是在一个物体上面叠加上一层的设计,而这种设计就是除了传统的,x,y的纸面层,还有就是透过纸面的z轴的层次设计. elevation: 高度,静态属 ...

  2. android 5&period;0新特性学习总结之下拉刷新&lpar;一&rpar;

    android 5.0 后google最终在 support v4 包下 添加了下拉刷新的控件 项目地址: https://github.com/stormzhang/SwipeRefreshLayo ...

  3. android 5&period;0新特性学习--Drawable Tinting(为图片资源着色)

    使用android:tint属性去调整色调.android:tintMode 着色模式 screen multiply and src_atop/src_in/src_oversetTint(int ...

  4. android 5&period;0新特性学习--视图轮廓

    ViewOutlineProvider -- 视图轮廓setOutlineProvider--可以使用View.setClipToOutline方法去剪切一个视图的outline区域.只有rectan ...

  5. android 5&period;0新特性学习--CardView

    CardView继承自FrameLayout类,可以在一个卡片布局中一致性的显示内容,卡片可以包含圆角和阴影.CardView是一个Layout,可以布局其他View. 官网地址:https://de ...

  6. Android 6&period;0 新特性 整理 资料来自网络

    Android 6.0新特性 Runtime Permissions Doze and App Standby Apache HTTP Client Removal BoringSSL Access ...

  7. Android 8&period;0 新特性

    Android 8.0 (Android Oreo(奥利奥))新特性介绍 通知渠道 - Notification Channels 通知渠道是由应用自行定义的通知内容类别,借助渠道,开发者可以让用户对 ...

  8. android 7&period;0 新特性 和对开发者的影响

    android 7.0新特性 - jiabailong的专栏 - 博客频道 - CSDN.NEThttp://blog.csdn.net/jiabailong/article/details/5241 ...

  9. 腾讯云安全:开发者必看|Android 8&period;0 新特性及开发指南

    欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 背景介绍 谷歌2017 I/O开发者大会今年将于5月17-19日在美国加州举办.大会将跟往年一样发布最新的 A ...

随机推荐

  1. 标准库String类

    下面的程序并没有把String类的所有成员方法实现,只参考教程写了大部分重要的成员函数. [cpp] view plain copy #include<iostream> #include ...

  2. jdbc的基本应用

    JDBC-----英文全称--------Java Data Base Connectivity是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写 ...

  3. iOS 核心动画

    核心动画(Core Animation) : •CoreAnimation是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍,使用它需要先添加QuartzCore.fr ...

  4. 使用culr

    使用curl在采集有语言要求的网站时,首先需要发送带有语言设置的请求,再发送你要的请求如: 注:vget(); 这里没提供: $url='http://www.hotels.com/?locale=e ...

  5. Spring Bean基本管理--bean注入方式汇总

    依赖注入方式:Spring支持两种依赖注入方式,分别是属性注入和构造函数注入.还有工厂方法注入方式. 依赖注入还分为:注入依赖对象可以采用手工装配或自动装配,在实际应用开发中建议使用手工装配,因为自动 ...

  6. JS瀑布流效果

    本篇内容实现类似百度图片的呈现功能,瀑布流+自动加载 index13.html <!DOCTYPE html> <html> <head> <meta cha ...

  7. 抛弃vue-resource拥抱axios

    vue-resource用法 import Vue from 'vue' import VueResource from 'vue-resource' Vue.use(VueResource) 是不是 ...

  8. xcode升级10

    ld: library not found for -lstdc++.6 删除 libstdc++ * Building with libstdc++ was deprecat ...

  9. React中使用百度地图API

    今天我们来搞一搞如何在React中使用百度地图API好吧,最近忙的头皮发麻,感觉身体被掏空,所以很久都没来写博客了,但今天我一定要来一篇好吧 话不多说,我们直接开始好吧 特别注意:该React项目是用 ...

  10. C&num; 如何利用反射,将字符串转化为类名并调用类中方法

    首先,先随便创建一个测试类 <span style="font-family:Microsoft YaHei;font-size:18px;">public class ...