热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

android5.0新特性学习--RecyclerView

在过去很多年,我们的PC或者手机设备都是采用拟物化的设计风格,IOS采用扁平化的特性,android在2014年IO大会上说采用MaterialDesign的设计风格,显示效果不能过于生硬的转换,而

在过去很多年,我们的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:

布局文件:

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 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 initData() {
mDatas
= new ArrayList();
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
{

private List 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 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 ) {
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 ) {
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 )
{
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 )
{
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());
}
}
}

效果:

 


推荐阅读
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 原文地址:https:www.cnblogs.combaoyipSpringBoot_YML.html1.在springboot中,有两种配置文件,一种 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
author-avatar
x75066882
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有