Android实现GridView中的item自由拖动效果

之前的工作中,需要实现一个功能就是GridView中的item可以自由拖动, 思考了一下,其实实现起来不是很困难,主要工作就是交换节点,以及拖动时的移动效果,下面讲讲具体的实现:

首先声明一个BaseAdapter:

package com.dafasoft.dragablegridview;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import java.util.ArrayList;
import java.util.List;
/**
* Created by zhangyulong on 16/9/22.
*/
public abstract class BaseDragableAdapter<T> extends BaseAdapter {
protected List<T> mList;
protected Context mContext;
protected LayoutInflater mInflater;
//初始化需隐藏的位置信息
protected int mHidePosition = AdapterView.INVALID_POSITION;
public BaseDragableAdapter(Context context) {
this.mContext = context;
this.mInflater = LayoutInflater.from(context);
mList = new ArrayList<T>();
}
@Override
public int getCount() {
return mList == null ? 0 : mList.size();
}
@Override
public Object getItem(int i) {
return mList == null ? 0 : mList.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public abstract View getView(int i, View view, ViewGroup viewGroup);
public void setList(List<T> list) {
if (this.mList != null) this.mList.clear(); // 避免脏数据
if (list == null) {
return;
}
this.mList = list;
}
public void setList(T[] list){
ArrayList<T> arrayList = new ArrayList<T>(list.length);
for (T t : list) {
arrayList.add(t);
}
setList(arrayList);
}
public List<T> getList() {
return this.mList;
}
public void addAll(List<T> list) {
if (list == null || list.size() == 0) return;
this.mList.addAll(list);
}
public void addAll(int location, List<T> list) {
if (list == null || list.size() == 0) return;
this.mList.addAll(location, list);
}
public void clean() {
if (getCount() == 0) return;
mList.clear();
}
public void hideView(int position){
mHidePosition = position;
notifyDataSetChanged();
}
public void showHideView(){
//重置hideposition
mHidePosition = AdapterView.INVALID_POSITION;
notifyDataSetChanged();
}
/**
* 交换节点
* @param draggedPos 拖拽的起始节点
* @param currentPos 拖拽的当前节点
*/
public void swapView(int draggedPos , int currentPos) {
//从前往后拖
if(draggedPos < currentPos){
//将被拖拽的节点移动至当前节点
mList.add(currentPos + 1 , mList.get(draggedPos));
//删除拖拽前的节点
mList.remove(draggedPos);
}
//从后往前拖
else if (draggedPos > currentPos) {
//将被拖拽的节点移动至当前节点
mList.add(currentPos , mList.get(draggedPos));
//删除拖拽前的节点
mList.remove(draggedPos + 1);
}
mHidePosition = currentPos;
notifyDataSetChanged();
}
}

其次实现DragableGridView:

package com.dafasoft.dragablegridview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.ImageView;
/**
* Created by zhangyulong on 16/9/22.
*/
public class DragableGridView extends GridView {
private static final int DRAG_IMG_SHOW = 1;
private static final int DRAG_IMG_NOT_SHOW = 0;
private static final String LOG_TAG = "DragGridView";
private static final float AMP_FACTOR = 1.2f;
private ImageView dragImageView;
private WindowManager.LayoutParams dragImageViewParams;
private WindowManager windowManager;
private boolean isViewOnDrag = false;
/**previous dragged over position*/
private int preDraggedOverPositon = AdapterView.INVALID_POSITION;
private int downRawX;
private int downRawY;
public DragableGridView(Context context) {
super(context);
initView();
}
public DragableGridView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public DragableGridView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
public void initView() {
setOnItemLongClickListener(mOnItemLongClickListener);
//setOnItemClickListener(onItemClickListener);
//setOnItemSelectedListener(onItemSelectedListener);
//初始化显示被拖动item的image view
dragImageView = new ImageView(getContext());
dragImageView.setTag(DRAG_IMG_NOT_SHOW);
//初始化用于设置dragImageView的参数对象
dragImageViewParams = new WindowManager.LayoutParams();
//获取窗口管理对象,用于后面向窗口中添加dragImageView
windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
}
private OnItemLongClickListener mOnItemLongClickListener = new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
//记录长按item位置
preDraggedOverPositon = position;
//获取被长按item的drawing cache
view.destroyDrawingCache();
view.setDrawingCacheEnabled(true);
//通过被长按item,获取拖动item的bitmap
Bitmap dragBitmap = Bitmap.createBitmap(view.getDrawingCache());
//设置拖动item的参数
dragImageViewParams.gravity = Gravity.TOP | Gravity.LEFT;
//设置拖动item为原item 1.2倍
dragImageViewParams.width = (int)(AMP_FACTOR*dragBitmap.getWidth());
dragImageViewParams.height = (int)(AMP_FACTOR*dragBitmap.getHeight());
//设置触摸点为绘制拖动item的中心
dragImageViewParams.x = (downRawX - dragImageViewParams.width/2);
dragImageViewParams.y = (downRawY - dragImageViewParams.height/2);
dragImageViewParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
//设置窗口支持透明度
dragImageViewParams.format = PixelFormat.TRANSLUCENT;
dragImageViewParams.windowAnimations = 0;
//dragImageView为被拖动item的容器,清空上一次的显示
if((int)dragImageView.getTag() == DRAG_IMG_SHOW) {
windowManager.removeView(dragImageView);
dragImageView.setTag(DRAG_IMG_NOT_SHOW);
}
//设置本次被长按的item
dragImageView.setImageBitmap(dragBitmap);
//添加拖动item到屏幕
windowManager.addView(dragImageView, dragImageViewParams);
dragImageView.setTag(DRAG_IMG_SHOW);
isViewOnDrag = true;
//设置被长按item不显示
((BaseDragableAdapter)getAdapter()).hideView(position);
return true;
}
};
@Override
public boolean onTouchEvent(MotionEvent ev) {
//被按下时记录按下的坐标
if(ev.getAction() == MotionEvent.ACTION_DOWN) {
//获取触摸点相对于屏幕的坐标
downRawX = (int)ev.getRawX();
downRawY = (int)ev.getRawY();
}
//dragImageView处于被拖动时,更新dragImageView位置
else if((ev.getAction() == MotionEvent.ACTION_MOVE) && (isViewOnDrag == true)) {
Log.i(LOG_TAG, "" + ev.getRawX() + " " + ev.getRawY());
//设置触摸点为dragImageView中心
dragImageViewParams.x = (int)(ev.getRawX() - dragImageView.getWidth()/2);
dragImageViewParams.y = (int)(ev.getRawY() - dragImageView.getHeight()/2);
//更新窗口显示,移动dragImageView的位置
windowManager.updateViewLayout(dragImageView, dragImageViewParams);
//获取当前触摸点的item position
int currDraggedPosition = pointToPosition((int)ev.getX(), (int)ev.getY());
//如果当前停留位置item不等于上次停留位置的item,交换本次和上次停留的item
if((currDraggedPosition != AdapterView.INVALID_POSITION) && (currDraggedPosition != preDraggedOverPositon)) {
((BaseDragableAdapter)getAdapter()).swapView(preDraggedOverPositon, currDraggedPosition);
preDraggedOverPositon = currDraggedPosition;
}
}
//释放dragImageView
else if((ev.getAction() == MotionEvent.ACTION_UP) && (isViewOnDrag == true)) {
((BaseDragableAdapter)getAdapter()).showHideView();
if((int)dragImageView.getTag() == DRAG_IMG_SHOW) {
windowManager.removeView(dragImageView);
dragImageView.setTag(DRAG_IMG_NOT_SHOW);
}
isViewOnDrag = false;
}
return super.onTouchEvent(ev);
}
}

实现一个adapter继承自BaseDragableAdapter:

package com.dafasoft.dragablegridview;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* Created by zhangyulong on 16/9/22.
*/
public class MyAdapter extends BaseDragableAdapter<String> {
public MyAdapter(Context context) {
super(context);
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder;
if (view == null) {
viewHolder = new ViewHolder();
view = mInflater.inflate(R.layout.adapter_my , null);
viewHolder.mItemTv = (TextView) view.findViewById(R.id.tv_item);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder)view.getTag();
}
if (mHidePosition == i) {
view.setVisibility(View.GONE);
} else {
view.setVisibility(View.VISIBLE);
}
viewHolder.mItemTv.setText(mList.get(i));
return view;
}
class ViewHolder{
TextView mItemTv;
}
}

在activity中使用:

package com.dafasoft.dragablegridview;
import android.app.Activity;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
private DragableGridView mDragableGv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDragableGv = (DragableGridView) findViewById(R.id.drag_grid_view);
MyAdapter adapter = new MyAdapter(this);
List<String> list = new ArrayList<String>();
for (int i = 0 ; i < 30 ; i ++) {
list.add("position" + i);
}
adapter.setList(list);
mDragableGv.setAdapter(adapter);
}
}

以上所述是小编给大家介绍的Android实现GridView中的item自由拖动效果,实现一个模拟后台数据登入的效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Android中在GridView网格视图上实现item拖拽交换的方法

    GridView基础 新建一个HelloGridView的工程 修改main.xml代码如下: <?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridview" android:layout_width=&q

  • android ListView和GridView拖拽移位实现代码

    关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:             首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.说明一点

  • Android自定义View实现可以拖拽的GridView

    先看看效果图 主要思想: 1.监听触碰事件 2.用WindowManager添加拖曳的图片 3.用Collections.swap()交换List数据 自定义代码: public class DragGridVeiw extends GridView { private final int PRESS_TIME = 1000;//长按时间 private int mDownX;//触碰时的X坐标 private int mDownY;//触碰时的Y坐标 private int mMoveX;//

  • Android实现GridView中的item自由拖动效果

    之前的工作中,需要实现一个功能就是GridView中的item可以自由拖动, 思考了一下,其实实现起来不是很困难,主要工作就是交换节点,以及拖动时的移动效果,下面讲讲具体的实现: 首先声明一个BaseAdapter: package com.dafasoft.dragablegridview; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import a

  • Android实现GridView中ImageView动态变换的方法

    本文实例讲述了Android实现GridView中ImageView动态变换的方法.分享给大家供大家参考.具体如下: 使用YY影音的时候,发现点击GridView的某一个Item,Item里面的图标会在按下的时候发生变换,变成另外一个图片. 自己写了一个类似的demo,具体步骤如下: 1.创建一个包含Grid的Acitity 2.创建item.xml 里面包含一个imageview和一个textview 3.自定义一个adapter,从baseadapter继承 4.在getView中为每个im

  • Android之RecycleView实现指定范围的拖动效果

    1 问题 在RecycleView里面实现指定位置的拖动效果,(这里是实现线性布局的,不是网格布局的) @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { Log.i(TAG, "onMove viewHolder.getAdapterPosition() is:" + viewHo

  • Android仿支付宝中余额宝的数字动画效果

    实现效果图: 下面是具体代码,可直接复制: package com.lcw.rabbit.widget; import android.animation.ObjectAnimator; import android.content.Context; import android.text.TextUtils; import android.util.AttributeSet; import android.view.animation.AccelerateDecelerateInterpola

  • Android使用ViewDragHelper实现QQ聊天气泡拖动效果

    QQ聊天气泡拖动效果Android实现代码,供大家参考,具体内容如下 概述 本文的目的是实现类似于QQ消息提醒的气泡的拖拽效果.网上已有大神的实现效果是通过监听控件的OnTouchEvent事件的ACTION_DOWN,ACTION_MOVE,ACTION_UP事件来处理相应的拖拽效果,这里采用ViewDragHelper的方式去实现拖拽,顺便学习了一下ViewDragHelper的使用方式,拖拽时的粘连效果采用贝塞尔曲线来实现. 用ViewDragHelper实现拖拽效果 ViewDragHe

  • Android使用ViewPager实现类似laucher左右拖动效果

    现在很多Android应用在首次安装完都会有指引如何使用该应用的某些功能的指引界面,这样会获得很好的用户体验,能够帮助用户更好使用应用的某些功能.其实该功能和Android主界面的 luncher 的功能完全一样的效果,可以实现左右拖动. 下面结合 ViewPager 的实例来展示如何实现该功能,先看下该Demo的结构图: 注:ViewPager类是实现左右两个屏幕平滑地切换的一个类,是由Google 提供的, 使用ViewPager首先需要引入android-support-v4.jar这个j

  • Android使用Gridview单行横向滚动显示

    本文实例为大家分享了Android使用Gridview单行横向滚动显示的具体代码,供大家参考,具体内容如下 要想实现滚动显示,layout布局里必须要使用HorizontalScrollView,才能实现横向滑动,但HorizontalScrollView标签里要嵌套一个LinearLayout布局 activity_main.xml,如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&qu

  • Android实现取消GridView中Item选中时默认的背景色

    本文实例讲述了Android实现取消GridView中Item选中时默认的背景色.分享给大家供大家参考,具体如下: 1.  取消GridView中Item选中时默认的背景色,当使用GridView时候点击item项时候,会有一个android默认的背景色,取消它的方法是: game_gridview.setSelector(new ColorDrawable(Color.TRANSPARENT)); //取消GridView中Item选中时默认的背景色 2.  GridView第一个item不显

  • Android自定义gridView仿头条频道拖动管理功能

    项目中遇到这样个需求:app的功能导航需要可拖动排序,类似头条中的频道拖动管理.效果如下,gif不是很顺畅,真机会好很多. 虽然类似的文章网上搜一下有很多,但写的都不令人满意,注释不清晰,而且动画还不够流畅.经本人整理优化后,拿出来供后续有需要的使用. 实现原理: gridView作为基本控件 WindowManager.addView的方式实现可拖动的view TranslateAnimation实现移动动画,动画完后更新adapter即可 主要的实现原理上面已经说明,源码中关键的地点也有注释

  • Android中ListView Item布局优化技巧

    本文实例讲述了Android中ListView Item布局优化技巧.分享给大家供大家参考,具体如下: 之前一直都不知道ListView有多种布局的优化方法,只能通过隐藏来实现,自己也知道效率肯定是很低的,但是也不知道有什么方法,这些天又查了一些资料,然后知道 其实google早就帮我们想好了优化方案了. 假设你的ListView Item有三种布局样式的可能:就比如很简单的显示一行字,要靠左,居中,靠右. 这时我们就可以在BaseAdapter里面重写两个方法: private static

随机推荐