高级UI之炫酷拖拽GridView—可拖拽,记录索引的GridV
2017-07-25 本文已影响179人
goodgleCoder
最近项目有要求对测量模块做一个快捷入口处理,需求要做一个可以拖拽的自定义View。
话不多说,先看 效果图吧:
思路:
- 1.对于可拖拽的view可以是个GridView自定义
- 也可以是一个自定义的ViewGroup
- 重新onToutchEvent方法,拖动处理
- 动态计算布标
- 动画:自定义属性动画
- 拖拽刷新布局
- 记录当前的位置
实现方式
- 1.自定义GridView
自定义已经显现好的ViewGroup回事一个不错的选择,而其已经为我们摆放好了一些位置如onLayout,onDraw等方法。
-
2.GridView 长按事件的处理
/** * 长按点击监听 * @param ev */ public void setOnItemClickListener(final MotionEvent ev) { setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { int x = (int) ev.getX();// 长安事件的X位置 int y = (int) ev.getY();// 长安事件的y位置 startPosition = position;// 第一次点击的postion dragPosition = position; if (startPosition <= 1) { return false; } ViewGroup dragViewGroup = (ViewGroup) getChildAt(dragPosition - getFirstVisiblePosition()); TextView dragTextView = (TextView)dragViewGroup.findViewById(R.id.text_item); dragTextView.setSelected(true); dragTextView.setEnabled(false); itemHeight = dragViewGroup.getHeight(); itemWidth = dragViewGroup.getWidth(); itemTotalCount = DragMyGridView.this.getCount(); int row = itemTotalCount / nColumns;// 算出行数 Remainder = (itemTotalCount % nColumns);// 算出最后一行多余的数量 if (Remainder != 0) { nRows = row + 1; } else { nRows = row; } // 如果特殊的这个不等于拖动的那个,并且不等于-1 if (dragPosition != AdapterView.INVALID_POSITION) { // 释放的资源使用的绘图缓存。如果你调用buildDrawingCache()手动没有调用setDrawingCacheEnabled(真正的),你应该清理缓存使用这种方法。 win_view_x = windowX - dragViewGroup.getLeft();//VIEW相对自己的X,半斤 win_view_y = windowY - dragViewGroup.getTop();//VIEW相对自己的y,半斤 dragOffsetY = (int) (ev.getRawY() - y);//手指在屏幕的上y位置-手指在控件中的位置就是距离最上边的距离 dragItemView = dragViewGroup; dragViewGroup.destroyDrawingCache(); dragViewGroup.setDrawingCacheEnabled(true); Bitmap dragBitmap = Bitmap.createBitmap(dragViewGroup.getDrawingCache()); mVibrator.vibrate(50);//设置震动时间 startDrag(dragBitmap, (int)ev.getRawX(), (int)ev.getRawY()); hideDropItem(); dragViewGroup.setVisibility(View.INVISIBLE); isMoving = false; requestDisallowInterceptTouchEvent(true); return true; } return false; } }); }
-
3.拖动事件的处理
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
boolean bool = true;
if (dragImageView != null && dragPosition != AdapterView.INVALID_POSITION) {
// 移动时候的对应x,y位置
bool = super.onTouchEvent(ev);
int x = (int) ev.getX();
int y = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int) ev.getX();
windowX = (int) ev.getX();
downY = (int) ev.getY();
windowY = (int) ev.getY();
break;
case MotionEvent.ACTION_MOVE:
onDrag(x, y ,(int) ev.getRawX() , (int) ev.getRawY());
if (!isMoving){
OnMove(x, y);
}
if (pointToPosition(x, y) != AdapterView.INVALID_POSITION){
break;
}
break;
case MotionEvent.ACTION_UP:
stopDrag();
onDrop(x, y);
requestDisallowInterceptTouchEvent(false);
break;
default:
break;
}
}
return super.onTouchEvent(ev);
}
- 4.如何记录位置?
- 拖动时改变索引
/** 在松手下放的情况 */ private void onDrop(int x, int y) { // 根据拖动到的x,y坐标获取拖动位置下方的ITEM对应的POSTION int tempPostion = pointToPosition(x, y); dropPosition = tempPostion; BaseCAdapter mBaseCAdapter = (BaseCAdapter) getAdapter(); //显示刚拖动的ITEM mBaseCAdapter.setShowDropItem(true); //刷新适配器,让对应的ITEM显示 mBaseCAdapter.notifyDataSetChanged(); }
- 4如何在第一个GridView的第一行画条线
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if(isShowFirstGridLine){
double count =getChildCount();
double numCoumn = getNumColumns();
int rowNum = (int) Math.ceil(count / numCoumn);
int rowHeight = getHeight() / rowNum;
Paint paint = new Paint();
paint.setColor(ContextCompat.getColor(getContext(),R.color.drawer_item_bg));
paint.setAntiAlias(true);
paint.setStrokeWidth(1);
canvas.drawLine(0,rowHeight,DensityUtil.getScreenIntWidth(getContext()),rowHeight,paint);
}
}
- 5 将集合保存在整个数据库
/**
* 类功能描述:</br>
* 数据库管理类
* 博客地址:http://blog.csdn.net/androidstarjack
* 公众号:终端研发部
* @author yuyahao
* @version 1.0 </p> 修改时间:2017-07-19</br> 修改备注:</br>
*/
public class AcheManager {
private static final String DEVICE_NAME_KEY = "com.yyh.mode.device.save";
private static ACache aCache;
private static final String CHANNELITEM_KEY = "com.yyh.mode.channelitem.save";
private static final AtomicReference<AcheManager> INSTANCE = new AtomicReference<AcheManager>();
private AcheManager(){}
//单例模式
public static AcheManager getInstance() {
for (;;) {
AcheManager current = INSTANCE.get();
if (current != null) {
return current;
}
current = new AcheManager();
if (INSTANCE.compareAndSet(null, current)) {
return current;
}
}
}
/**
* 保存设备的model
* @param context
* @param modelList 要存放的list集合
*/
public ArrayList<DeviceValue> saveDeviceValue(Context context, ArrayList<DeviceValue> modelList){
if(aCache == null){
aCache = ACache.get(context);
}
aCache.remove(DEVICE_NAME_KEY);
aCache.put(DEVICE_NAME_KEY, modelList);
return modelList;
}
/**
* 获取设备的model
* @param context
*/
public ArrayList<DeviceValue> getDeviceValue(Context context){
if(aCache == null){
aCache = ACache.get(context);
}
ArrayList<DeviceValue> modelList = (ArrayList<DeviceValue>) aCache.getAsObject(DEVICE_NAME_KEY);
if(modelList == null) {
modelList = new ArrayList<>();
}
return modelList;
}
/**
* 保存设备的model
* @param context
* @param modelList 要存放的list集合
*/
public ArrayList<ChannelItem> saveChannelItemUserValue(Context context, ArrayList<ChannelItem> modelList){
if(aCache == null){
aCache = ACache.get(context);
}
aCache.remove(CHANNELITEM_KEY);
aCache.put(CHANNELITEM_KEY, modelList);
return modelList;
}
/**
* 获取设备的model
* @param context
*/
public ArrayList<ChannelItem> getChannelItemUserValue(Context context){
if(aCache == null){
aCache = ACache.get(context);
}
ArrayList<ChannelItem> modelList = (ArrayList<ChannelItem>) aCache.getAsObject(CHANNELITEM_KEY);
if(modelList == null) {
modelList = new ArrayList<>();
}
return modelList;
}
......
}
扩展
多个View进入交互效果图下:
多个GridView进行交互demo下载地址:
CSDN下载链接
如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809
微信公众号:终端研发部