使用过今日头条的伙计们对这个效果肯定很熟悉。拖拽可排序,点击标签后可以删除。今天我们采用RecyclerView来实现。
实现思路:
通过ItemTouchHelper来绑定RecyclerView的子控件触摸事件。
当滑动拖拽的时候,通知适配器来交换两个子控件的显示位置。
更改数据源,使数据源与子空间显示内容一致。
这就是实现的基本思路,是不是很简单?当然,首先要了解一下ItemTouchHelper这哥们儿是干啥的,有什么作用。
This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.
It works with a RecyclerView and a Callback class, which configures what type of interactions are enabled and also receives events when user performs these actions.
Depending on which functionality you support, you should override onMove(RecyclerView, ViewHolder, ViewHolder) and / or onSwiped(ViewHolder, int).
This class is designed to work with any LayoutManager but for certain situations, it can be optimized for your custom LayoutManager by extending methods in the ItemTouchHelper.Callback class or implementing ItemTouchHelper.ViewDropHandler interface in your LayoutManager.
By default, ItemTouchHelper moves the items' translateX/Y properties to reposition them. You can customize these behaviors by overriding onChildDraw(Canvas, RecyclerView, ViewHolder, float, float, int, boolean) or onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, boolean).
Most of the time you only need to override onChildDraw.
通过API文档的介绍,这个哥们儿是为RecyclerView工作的,他需要一个CallBack,可以回调RecyclerView的子控件滑动和拖拽事件,而且也可以通过这个CallBack重绘我们的子view。这就一目了然了嘛。通过使用ItemTouchHelper,可以很轻松的就实现了RecyclerView触摸事件的回调。换句话说,只要我们为RecyclerView 绑定了ItemTouchHelper之后,RecyclerView子控件的拖动和滑动事件已经帮我们实现了。我们所要做的就是在触摸事件之后,如何去改变去更新Adapter和改变我们的数据。
开始撸码:
public class ChannelActivity extends Activity {
public RecyclerView rv;
public List<DataBean> list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_channel);
initData();
initView();
}
private void initView() {
rv = (RecyclerView) findViewById(R.id.rl_view);
rv.setLayoutManager(new GridLayoutManager(this, 4));
MyAdapter adapter = new MyAdapter(this, list);
rv.setAdapter(adapter);
//关联ItemTouchHelper
ItemTouchHelper touchHelper = new ItemTouchHelper(new MyItemTouchCallBack(adapter));
touchHelper.attachToRecyclerView(rv);
}
private void initData() {
DataBean bean1 = new DataBean("体育", 0, "url");
DataBean bean2 = new DataBean("新闻", 1, "url");
DataBean bean3 = new DataBean("*", 2, "url");
DataBean bean4 = new DataBean("电视剧", 3, "url");
DataBean bean5 = new DataBean("热点", 4, "url");
DataBean bean6 = new DataBean("推荐", 5, "url");
DataBean bean7 = new DataBean("屌丝男士", 6, "url");
DataBean bean8 = new DataBean("音乐", 7, "url");
DataBean bean9 = new DataBean("电影", 8, "url");
list.add(bean1);
list.add(bean2);
list.add(bean3);
list.add(bean4);
list.add(bean5);
list.add(bean6);
list.add(bean7);
list.add(bean8);
list.add(bean9);
}
}
自定义MyItemTouchCallBack
public class MyItemTouchCallBack extends ItemTouchHelper.Callback {
private TouchInterface touchInterface;
public MyItemTouchCallBack(TouchInterface touchInterface) {
this.touchInterface = touchInterface;
}
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
//拖拽
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT;
//滑出屏幕
int swipeFlags = ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT | ItemTouchHelper.UP | ItemTouchHelper.DOWN;
return makeMovementFlags(dragFlags, 0);
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
int position_target = target.getLayoutPosition();
int position = viewHolder.getLayoutPosition();
//滑动事件回调到了Adapter,用来处理数据
touchInterface.onMove(position, position_target);
return true;
}
//标签动画持续时间,默认是250
@Override
public long getAnimationDuration(RecyclerView recyclerView, int animationType, float animateDx, float animateDy) {
return super.getAnimationDuration(recyclerView, animationType, animateDx, animateDy);
}
/**
* 是否可以长按拖拽,默认是true
*
* @return
*/
@Override
public boolean isLongPressDragEnabled() {
return super.isLongPressDragEnabled();
}
/**
* 标签划出去的回调,direction是滑动的方向
*
* @return
*/
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
}
}
Adapter类中处理数据
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> implements TouchInterface {
private Context context;
//是否显示delete
public boolean isShow;
public List<DataBean> getList() {
return list;
}
public void setList(List<DataBean> list) {
this.list = list;
}
private List<DataBean> list;
public MyAdapter(Context context, List<DataBean> list) {
this.context = context;
this.list = list;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MyViewHolder viewHolder = new MyViewHolder(LayoutInflater.from(context).inflate(R.layout.item_layout, parent, false));
return viewHolder;
}
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.tv_des.setText(list.get(position).name);
holder.tv_des.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DataBean bean = list.remove(position);
notifyDataSetChanged();
Toast.makeText(context,"删除了"+bean.name+"频道",Toast.LENGTH_SHORT).show();
}
});
holder.tv_des.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
isShow = true;
notifyDataSetChanged();
return true;
}
});
if (isShow) {
holder.iv_icon.setVisibility(View.VISIBLE);
} else {
holder.iv_icon.setVisibility(View.GONE);
}
}
@Override
public int getItemCount() {
return list.size();
}
@Override
public void onMove(int currentPosition, int targetPosition) {
Collections.swap(list, currentPosition, targetPosition);
if (targetPosition < currentPosition) {
List<DataBean> subList = list.subList(targetPosition + 1, currentPosition + 1);
//向右移一位
rightStepList(0, subList);
} else {
List<DataBean> subList = list.subList(currentPosition, targetPosition);
//向左移一位
leftStepList(0, subList);
}
notifyItemMoved(currentPosition, targetPosition);
}
}
class MyViewHolder extends RecyclerView.ViewHolder {
public ImageView iv_icon;
public TextView tv_des;
public MyViewHolder(View itemView) {
super(itemView);
iv_icon = (ImageView) itemView.findViewById(R.id.iv_icon);
tv_des = (TextView) itemView.findViewById(R.id.tv_des);
}
}
解释一下onMove方法,例如:我们的数据是[1,2,3,4,5,6],当6移动到3的位置时,那么数据源最后变化为[1,2,6,3,4,5]。但是在显示的时候我们先是将当前position和targetposition对调[1,2,6,4,5,3],然后取出[4,5,3]进行右移一位,这样数据源就对上了。如果是从3移动到6进行左移就可以了,数据排序的算法,采用反转的思想。
public class DataUtils {
/**
* 利用反转的思想对数据进行排序
* 例如:list{0,1,2,3,4,5,6,7} 左移一位
* 第一步:第一位先反转{0,1,2,3,4,5,6,7}
* 第二部:剩下的在反转{0,7,6,5,4,3,2,1}
* 第三步:全部反转{1,2,3,4,5,6,7,0}
*
* 例如:list{0,1,2,3,4,5,6,7} 右移一位
* 第一步:最右边一位先反转{1,2,3,4,5,6,7}
* 第二部:剩下的在反转{6,5,4,3,2,1,0,7}
* 第三步:全部反转{7,6,5,4,3,2,1,0}
*
* 因为list的index是从0开始的,step要相应的-1
* 优点:少创建对象,优化内存
*
* @param start
* @param end
* @param list
*/
public static void reverseList(int start,int end,List list){
int count = (end+1-start)/2 ;
for(int i = 0;i< count;i++){
Object temp = list.get(start+i);
list.set(start+i,list.get(end-i));
list.set(end-i,temp);
}
}
public static void leftStepList(int step,List list){
int size = list.size() -1;
//左移
reverseList(0,step,list);
reverseList(step+1,size,list);
reverseList(0,size,list);
}
public static void rightStepList(int step,List list){
int size = list.size() -1;
//右移
reverseList(size-step,size,list);
reverseList(0,size-step-1,list);
reverseList(0,size,list);
}
}
Activity布局文件:
<?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_channel"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.iwintrue.channe.ChannelActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/rl_view"
android:background="@color/white"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
</RelativeLayout>
子控件布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp">
<TextView
android:id="@+id/tv_des"
android:layout_width="80dp"
android:layout_height="30dp"
android:text="屌丝男士"
android:gravity="center"
android:background="@drawable/rl_shape"
android:textColor="@color/textColor"
android:layout_marginTop="5dp"
android:layout_marginRight="5dp" />
<ImageView
android:layout_alignRight="@+id/tv_des"
android:layout_marginRight="-5dp"
android:id="@+id/iv_icon"
android:layout_width="20dp"
android:layout_height="20dp"
android:src="@mipmap/delete"
android:scaleType="fitXY"
android:visibility="gone" />
</RelativeLayout>
</LinearLayout>
实现效果:
github地址:https://github.com/zhoukai1526/Channel
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Android
# 今日头条
# 频道管理
# android自定义view仿今日头条加载文字变色效果
# Android仿今日头条顶部导航栏效果的实例代码
# Android仿今日头条多个fragment懒加载的实现
# Android studio导入项目的方法详解(简单快速)
# Android 仿今日头条简单的刷新效果实例代码
# Android仿今日头条APP实现下拉导航选择菜单效果
# Android应用中仿今日头条App制作ViewPager指示器
# Android实现仿网易今日头条等自定义频道listview 或者grideview等item上移到
# Android仿今日头条滑动页面导航效果
# Android实现今日头条订阅频道效果
# 拖拽
# 回调
# 是从
# 第二部
# 第三步
# 哥们儿
# 实现了
# 有什么
# 上了
# 这就是
# 这就
# 可以通过
# 很简单
# 自定义
# 拖动
# 定了
# 要了
# 就对
# 来实现
# 使用过
相关文章:
如何在IIS7上新建站点并设置安全权限?
正规网站制作公司有哪些,目前国内哪家网页网站制作设计公司比较专业靠谱?口碑好?
简历在线制作网站免费,免费下载个人简历的网站是哪些?
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
建站之星如何修改网站生成路径?
定制建站是什么?如何实现个性化需求?
如何用低价快速搭建高质量网站?
定制建站流程步骤详解:一站式方案设计与开发指南
行程制作网站有哪些,第三方机票电子行程单怎么开?
广州营销型建站服务商推荐:技术优势与SEO优化解析
定制建站策划方案_专业建站与网站建设方案一站式指南
如何通过商城免费建站系统源码自定义网站主题?
如何在七牛云存储上搭建网站并设置自定义域名?
如何在Windows服务器上快速搭建网站?
魔毅自助建站系统:模板定制与SEO优化一键生成指南
小型网站制作HTML,*游戏网站怎么搭建?
香港服务器租用每月最低只需15元?
黑客如何通过漏洞一步步攻陷网站服务器?
宝塔建站助手安装配置与建站模板使用全流程解析
建站10G流量真的够用吗?如何应对访问高峰?
如何使用Golang table-driven基准测试_多组数据测量函数效率
北京建设网站制作公司,北京古代建筑博物馆预约官网?
建站之星价格显示格式升级,你的预算足够吗?
建站主机空间推荐 高性价比配置与快速部署方案解析
深圳网站制作培训,深圳哪些招聘网站比较好?
如何通过PHP快速构建高效问答网站功能?
如何快速生成高效建站系统源代码?
实例解析Array和String方法
如何快速生成橙子建站落地页链接?
实惠建站价格推荐:2025年高性价比自助建站套餐解析
建站之星后台搭建步骤解析:模板选择与产品管理实操指南
建站之星2.7模板快速切换与批量管理功能操作指南
如何挑选高效建站主机与优质域名?
如何快速查询域名建站关键信息?
邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?
建站IDE高效指南:快速搭建+SEO优化+自适应模板全解析
专业公司网站制作公司,用什么语言做企业网站比较好?
招商网站制作流程,网站招商广告语?
免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?
如何在建站之星绑定自定义域名?
模具网站制作流程,如何找模具客户?
如何做静态网页,sublimetext3.0制作静态网页?
如何选择域名并搭建高效网站?
香港服务器建站指南:免备案优势与SEO优化技巧全解析
如何快速辨别茅台真假?关键步骤解析
建站主机选择指南:服务器配置与SEO优化实战技巧
建站之星北京办公室:智能建站系统与小程序生成方案解析
韩国服务器如何优化跨境访问实现高效连接?
如何通过主机屋免费建站教程十分钟搭建网站?
建站之星安装路径如何正确选择及配置?
*请认真填写需求信息,我们会在24小时内与您取得联系。