先来看看网易新闻客户端以及自己实现的效果图,效果当然还是网易的好

gridviewsort.gif

如何实现拖拽一个Item

用WindowManager添加一个ImageView,并且将这个ImageView的显示图片设置成被拖拽item的截图,截图可以通过View的getDrawingCache获得。拖拽的时候,隐藏原始的item。处理触摸事件的ActionMove,调整ImageView的位置,跟随手指移动。在ActionUp的时候removeView

GridView

@Override

public boolean onItemLongClick(AdapterView> adapterView, View view, int i, long l)

{

// 至少有两个item的时候,才有排序

if (getChildCount() >= 2)

{

mView = view;

// 在调用getDrawingCache必须先调用

view.setDrawingCacheEnabled(true);

// 获取截图并设置

Bitmap bitmap = view.getDrawingCache();

mDragItemView.setImageBitmap(bitmap);

// 设置拖拽的imageview的params

mDragItemLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;

mDragItemLayoutParams.width = bitmap.getWidth();

mDragItemLayoutParams.height = bitmap.getHeight();

mDragItemLayoutParams.x = (mDownX - mDragItemLayoutParams.width / 2);

mDragItemLayoutParams.y = (mDownY - mDragItemLayoutParams.height / 2);

// 设置拖拽imageview的中心位于长按点击点

mDragItemLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE //不接受按键事件

| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE // 不接收触摸事件

| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON // 保持常亮

| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; // place the window within the entire screen, ignoring decorations around the border (such as the status bar)

mDragItemLayoutParams.format = PixelFormat.TRANSLUCENT;

mDragItemLayoutParams.windowAnimations = 0;

// 往WindowManager中添加拖拽的View

mWindowManager.addView(mDragItemView, mDragItemLayoutParams);

((GridViewSortAdapter) getAdapter()).init();

((GridViewSortAdapter) getAdapter()).hideView(i);

Log.d(TAG, "long click = " + i);

mDragStarted = true;

}

return true;

}

@Override

public boolean onTouchEvent(MotionEvent ev)

{

switch (ev.getAction() & ev.getActionMasked())

{

case MotionEvent.ACTION_DOWN:

mDownX = (int) ev.getRawX();

mDownY = (int) ev.getRawY();

break;

case MotionEvent.ACTION_MOVE:

if (mDragStarted)

{

// 保持中心

mDragItemLayoutParams.x = (int) (ev.getRawX() - mDragItemView.getWidth() / 2);

mDragItemLayoutParams.y = (int) (ev.getRawY() - mDragItemView.getHeight() / 2);

// 更新params

mWindowManager.updateViewLayout(mDragItemView, mDragItemLayoutParams);

// ......

}

break;

case MotionEvent.ACTION_UP:

// ......

break;

}

return super.onTouchEvent(ev);

}

如何实现隐藏拖拽的Item

在开始拖拽的时候,把隐藏的item的position告诉Adapter,调用Adapter的notifyDataSetChanged刷新数据,在getView方法中判断当前的构建的item的position是不是需要隐藏的position是的话就设置view为inVisible

GridView

@Override

public boolean onItemLongClick(AdapterView> adapterView, View view, int i, long l)

{

// ......

((GridViewSortAdapter) getAdapter()).hideView(i);

// ......

}

GridViewSortAdapter

public void hideView(int item)

{

// ......

mStartHideItemPosition = item;

notifyDataSetChanged();

}

private int mStartHideItemPosition = AdapterView.INVALID_POSITION;

@Override

public View getView(int position, View convertView, ViewGroup parent)

{

ViewHolder holder = null;

if (convertView == null)

{

convertView = LayoutInflater.from(mContext).inflate(R.layout.view_item_grid_view_sort, null);

holder = new ViewHolder();

holder.title = (TextView) convertView.findViewById(R.id.view_item_grid_view_sort_title);

convertView.setTag(holder);

}

else

{

holder = (ViewHolder) convertView.getTag();

}

holder.title.setText(mTypeTitle.get(position));

if (mStartHideItemPosition == position)

{

convertView.setVisibility(View.INVISIBLE);

}

else

{

convertView.setVisibility(View.VISIBLE);

}

return convertView;

}

如何知道当前拖拽到哪一个item之上

要想在拖拽到其他item上面时互换位置,那必须得知道当前拖拽到了哪一个item之上。GrideView提供了一个方法叫pointToPosition,可以在处理触摸事件的ACTION_MOVE时,获取手指触摸的x,y来得到当前拖拽到item之上的position。这里需要注意的一点是,在拖拽的过程,同一个item的position是不会变的,除非调用了Adapter的notifyDataSetChanged,position才会重新计算。比如position为2的item,在拖拽的过程无论怎么动画移动位置,他的position都是2,知道一次拖拽结束,ActionUp的时候,会调用notifyDataSetChanged

GridView

@Override

public boolean onTouchEvent(MotionEvent ev)

{

case MotionEvent.ACTION_MOVE:

if (mDragStarted)

{

// ......

int position = pointToPosition((int) ev.getX(), (int) ev.getY());

// ......

}

break;

}

如何实现动画

一个item需要水平以及垂直需要移动的距离可以事先先计算出来,其实水平距离不管怎么样一定会是GridView一个单元格的宽度加上水平间距,垂直距离无论如何都是一个单元格的高度加上垂直距离,宽度非常好取,高度的话,这里默认item 的高度和单元格的高度相同。

GridViewSortAdapter

View view = mGridView.getChildAt(0);

mTranslateX = view.getWidth() + mHorizontalSpace;

mTranslateY = view.getHeight() + mVerticalSpace;

当拖拽到其他item之上时,开始动画

SortGridView

if (position != AdapterView.INVALID_POSITION && !((GridViewSortAdapter) getAdapter()).isInAnimation())

{

Log.d(TAG, "position = " + position);

((GridViewSortAdapter) getAdapter()).swap(position);

}

GridSortAdapter

public void swap(int position)

{

mAnimatorSetList.clear();

int r_p = mPositionList.indexOf(position);

Log.d(TAG, "r_p = " + r_p);

if (mCurrentHideItemPosition < r_p)

{

for (int i = mCurrentHideItemPosition + 1; i <= r_p; i++)

{

View v = mGridView.getChildAt(mPositionList.get(i));

if (i % mColsNum == 0 && i > 0)

{

startMoveAnimation(v, v.getTranslationX() + mTranslateX * (mColsNum - 1), v.getTranslationY() -

mTranslateY);

}

else

{

startMoveAnimation(v, v.getTranslationX() - mTranslateX, 0);

}

}

}

else if (mCurrentHideItemPosition > r_p)

{

for (int i = r_p; i < mCurrentHideItemPosition; i++)

{

View v = mGridView.getChildAt(mPositionList.get(i));

if ((i + 1) % mColsNum == 0)

{

startMoveAnimation(v, v.getTranslationX() - mTranslateX * (mColsNum - 1), v.getTranslationY() + mTranslateY);

}

else

{

startMoveAnimation(v, v.getTranslationX() + mTranslateX, 0);

}

}

}

resetPositionList();

int value = mPositionList.get(mStartHideItemPosition);

if (mStartHideItemPosition < r_p)

{

mPositionList.add(r_p + 1, value);

mPositionList.remove(mStartHideItemPosition);

}

else if (mStartHideItemPosition > r_p)

{

mPositionList.add(r_p, value);

mPositionList.remove(mStartHideItemPosition + 1);

}

mCurrentHideItemPosition = r_p;

}

public boolean isInAnimation()

{

return mInAnimation;

}

private void resetPositionList()

{

mPositionList.clear();

for (int i = 0; i < mGridView.getChildCount(); i++)

{

mPositionList.add(i);

}

}

private void startMoveAnimation(View myView, float x, float y)

{

AnimatorSet set = new AnimatorSet();

set.playTogether(

ObjectAnimator.ofFloat(myView, "translationX", myView.getTranslationX(), x),

ObjectAnimator.ofFloat(myView, "translationY", myView.getTranslationY(), y)

);

set.addListener(new Animator.AnimatorListener()

{

@Override

public void onAnimationStart(Animator animator)

{

mInAnimation = true;

}

@Override

public void onAnimationEnd(Animator animator)

{

mInAnimation = false;

}

@Override

public void onAnimationCancel(Animator animator)

{

}

@Override

public void onAnimationRepeat(Animator animator)

{

}

});

mAnimatorSetList.add(set);

set.setDuration(150).start();

}

这里我主要解释一下代码中 mPositionList这个列表的作用,之前说过一次拖拽的时候,item的position是不会变化的。

假设有一组数据

a b c d

e f g h

i j k l

此时mPositionList的内容就是 0 1 2 3 4 5 6 7 8 9 10 11 12

现在将c拖拽到g上,拖拽完成之后的数据应该是,未释放手指

a b d e

f g c h

i j k l

此时mPositionList的内容就是 0 1 2 4 5 6 7 3 8 9 10 11 12

紧接着,继续拖拽c到e上,你会发现调用pointToPosition方法得到的position是5,但是e现在的索引是4

因此你只需要调用

mPositionList.indexOf(pointToPosition(x,y))

就能得到真实的item的position

其他

如果把GridView的列数变成1那么似曾相识啊

gridviewex.gif

源码地址

以上所述是小编给大家介绍的Android 仿网易新闻客户端分类排序功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

android分类功能,Android 仿网易新闻客户端分类排序功能相关推荐

  1. [Android] 仿网易新闻客户端分类排序

    转载地址:http://www.jianshu.com/p/7be162740a95 效果图 先来看看网易新闻客户端以及自己实现的效果图,效果当然还是网易的好 wangyixinwen.gif gri ...

  2. Android 开源框架ViewPageIndicator 和 ViewPager 仿网易新闻客户端Tab标签

     转载请注明出处:http://blog.csdn.net/xiaanming/article/details/10766053 之前用JakeWharton的开源框架ActionBarSherl ...

  3. Android高仿网易新闻客户端之动态添加标签

    承接上一篇文章:Android高仿网易新闻客户端之首页,今天来实现动态添加标签效果. 动态标签页是一个流式布局,实现了宽度自动换行高度自动分配的功能,代码如下: FlowLayout.java pac ...

  4. android 仿网易新闻客户端源码都有

    原文:android 仿网易新闻客户端源码都有 android 仿网易新闻服务端源码 源代码下载地址: http://www.zuidaima.com/share/1550463560944640.h ...

  5. android 仿网易标签切换,Android 仿网易新闻客户端Tab标签

    Android 开源框架ViewPageIndicator和ViewPager仿网易新闻客户端Tab标签 http://blog.csdn.net/xiaanming/article/details/ ...

  6. 仿网易新闻客户端的上面的tab和下面的功能条

    2019独角兽企业重金招聘Python工程师标准>>> 仿网易新闻客户端的上面的tab和下面的功能条 package com.and.netease; import com.and. ...

  7. 仿网易新闻客户端UI界面小Demo

    图一 图二 图三 仿网易新闻客户端UI界面Demo 图一:新闻模块 UI界面:点击下方按钮,显示相应内容的页面信息 图三:点击新闻模块上方按钮显示体育,娱乐,科技等页面,相应的内容. 所涉及的知识点: ...

  8. IOS开发——仿网易新闻客户端

    IOS开发--仿网易新闻客户端 本文没有内容,传个资源 衔接地址:http://download.csdn.net/detail/u012881779/7152281 左侧导航部分: 新闻版块 订阅版 ...

  9. Android Studio精彩案例(四)《DrawerLayout使用详解仿网易新闻客户端侧边栏 》

    转载本专栏文章,请注明出处,尊重原创 .文章博客地址:道龙的博客 为了提高兴趣,咱们开头先看看最终要实现什么样的效果: 侧拉菜单在Android应用中非常常见,它的实现方式太多了,今天我们就说说使用G ...

最新文章

  1. 为什么说Python是伟大的入门语言
  2. 原来BCH是这样转给别人的
  3. 【 MATLAB 】xcorr 函数介绍(互相关)简介
  4. 给ModalPopupExtender控件添加弹出关闭等事件
  5. 《漫画算法2》源码整理-5 二维数组螺旋输出
  6. ParaEngine 一个同事的公司的开源引擎
  7. example:利用impdp通过dblink导入数据库
  8. Spring boot中如何获取profiles环境
  9. 带你玩转Visual Studio——带你高效开发
  10. 英特尔开源技术中心招收Linux内核高手一名
  11. C++字符编码的查看和检测
  12. 【CV】MobileNetV2:具有倒置残差和线性瓶颈的 CNN 骨干网络
  13. 各种浏览器开启JavaScript脚本
  14. Unity报错(bug)
  15. widowns上从chrome上抓取图片
  16. 消费者理论:效用函数
  17. 【Skynet】开始创建服务的代码流程
  18. 《深入理解Linux内核》-3.3. 进程切换
  19. MATLAB自相关矩阵计算方法
  20. 冯唐:老聃的金字塔原则

热门文章

  1. 双一流高校全球通邮经验:Coremail安全海外中继提升科研效率
  2. 硬盘电路板损坏故障数据如何修复
  3. 从流水线工人,到谷歌上班的程序媛
  4. macbook win10启动时一直在转圈的故障解决
  5. 双色球机选彩票shell脚本
  6. 11.17-判断一个数是质数还是合数
  7. 安装Fedora 36 Server
  8. 关于Eclipse无法创建web工程问题
  9. java华容道游戏_用java设计一个华容道游戏
  10. 怎么在pdf文件上添加水印