当前位置: 代码迷 >> Android >> Android开发之自定义View课题(三):自定义GridView
  详细解决方案

Android开发之自定义View课题(三):自定义GridView

热度:76   发布时间:2016-04-28 03:01:37.0
Android开发之自定义View专题(三):自定义GridView

      gridview作为android开发中常用的组件,其功能十分强大。但是,我们有时候有很多特殊的需求,需要在其基础上进行改造。有时候会有移动gridView中item位置的需求,这个网上已经有很多例子,博主就不在描述。今天博主讲的是移动gridView中item中的内容。博主没看过网上那些移动item位置的demo,不知道其原理是不是和博主想的一样。博主思考过,似乎博主的这种实现原理似乎也可以用作实现移动item位置。而之前博主百思不得其解的小米手机的桌面的自定义乱序排放,似乎也可以用这个原理去实现。好了,废话不多说,先上效果图




这里博主就以数字为内容来演示,不同的数字item的背景颜色不同来区分,长按住一个item后可以移动,每次移动,移动的item减1,移动到的item加1。效果还可以吧。好了,上代码,大家一起学习。了解其实现原理的同学完全可以自己修改代码开发可移动item的gridView

完整项目下载地址:http://download.csdn.net/detail/victorfreedom/8326829

(最近网络不给力,github上传有问题,等明天最后一篇自定义view专题讲解完了,再将所有项目一起上传吧,不介意那点分的同学可以先下载)


package com.freedom.gridview;import android.annotation.SuppressLint;import android.content.Context;import android.graphics.Bitmap;import android.graphics.PixelFormat;import android.util.AttributeSet;import android.view.Gravity;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import android.view.ViewGroup;import android.view.WindowManager;import android.view.animation.AnimationUtils;import android.widget.AdapterView;import android.widget.GridView;import android.widget.ImageView;import android.widget.Toast;import com.freedom.gridview.adapter.GridViewAdapter;import com.freedom.gridview.bean.Data;/** * @ClassName: FreedomGridView * @author victor_freedom ([email protected]) * @createddate 2015-1-4 下午10:25:52 * @Description: 可移动item内容的gridView */@SuppressLint("NewApi")public class FreedomGridView extends GridView {	// 是否在移动中	private boolean isMove = false;	// 是否是第一次移动	private boolean isFirst = true;	// 是否是长按	private boolean isLongClick = false;	// 图形	private Bitmap bitmap;	// 移动的视图	private ImageView moveView = null;	// 偏移量	private int offsetX, offsetY;	// 在屏幕中触摸的位置	private int touchPositionInScreen;	// 移动的目的位置	private int moveToPosition;	// 在ITEM中触摸的坐标	private int touchPositionInItemX, touchPositionInItemY;	// 移动速度	private int scaledTouchSlop;	// 移动过程中,上下边距判定自动滑动距离	private int upScrollBounce;	private int downScrollBounce;	// 窗体管理者,用于添加视图	private WindowManager windowManager = null;	private WindowManager.LayoutParams layoutParams = null;	private GridViewAdapter adapter;	public FreedomGridView(Context context) {		super(context);		scaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();	}	public FreedomGridView(Context context, AttributeSet attrs) {		super(context, attrs);	}	public FreedomGridView(Context context, AttributeSet attrs, int defStyle) {		super(context, attrs, defStyle);	}	/**	 * 长按判定	 */	private Runnable longPressRun = new Runnable() {		@Override		public void run() {			isLongClick = true;		}	};	/**	 * @Title: contains	 * @Description: 判断是否触摸坐标是否在视图里面	 * @param v	 * @param xInView	 * @param yInView	 * @return	 * @throws	 */	private boolean contains(View v, int xInView, int yInView) {		if (v instanceof ImageView) {			return ((ImageView) v).getDrawable().getBounds()					.contains(xInView, yInView);		}		return v.getBackground().getBounds().contains(xInView, yInView);	}	@Override	public boolean onTouchEvent(MotionEvent ev) {		// 拿到适配器		if (null == adapter || adapter.isEmpty()) {			adapter = (GridViewAdapter) getAdapter();		}		switch (ev.getAction()) {		case MotionEvent.ACTION_DOWN:			// 拿到相对于触摸视图的坐标			int x = (int) ev.getX();			int y = (int) ev.getY();			// 拿到触摸位置			touchPositionInScreen = moveToPosition = this.pointToPosition(x, y);			// 判断位置是否有效			if (moveToPosition == AdapterView.INVALID_POSITION) {				break;			}			// 拿到当前触摸的可见item			ViewGroup itemView = (ViewGroup) this.getChildAt(moveToPosition					- this.getFirstVisiblePosition());			// 拿到点击位置相对于ITEM视图的偏移量			touchPositionInItemY = y - itemView.getTop();			touchPositionInItemX = x - itemView.getLeft();			// 拿到item视图里面的控件			View view = itemView.findViewById(R.id.desk_back);			// 判断点击位置是否在视图里面			if (this.contains(view, touchPositionInItemX, touchPositionInItemX)) {				try {					int[] locationInScreen = new int[2];					view.getLocationOnScreen(locationInScreen);				} catch (NullPointerException e) {					break;				}			}			// 移动视图时候的偏移量			this.offsetX = (int) (ev.getRawX() - x);			this.offsetY = (int) (ev.getRawY() - y);			// 获取触发当拖动视图到最顶端或者最底端自动滚动视图的边距			upScrollBounce = Math.min(y - scaledTouchSlop, getHeight() / 3);			downScrollBounce = Math.max(y + scaledTouchSlop,					getHeight() * 2 / 3);			itemView.setDrawingCacheEnabled(true);			// 拿item视图的bitmap			bitmap = Bitmap.createBitmap(itemView.getDrawingCache());			itemView.destroyDrawingCache();			postDelayed(longPressRun, 1000);			break;		case MotionEvent.ACTION_MOVE:			if (isLongClick) {				int mx = (int) ev.getX();				int my = (int) ev.getY();				// 第一次移动,创建移动视图				if (isFirst)					initWindowManager(bitmap, mx, my);				onMove(mx, my);				// 移除之前的runable				removeCallbacks(longPressRun);				return true;			}			break;		case MotionEvent.ACTION_UP:			int upY = (int) ev.getY();			int upX = (int) ev.getX();			if (isMove && isLongClick) {				stopMove();				completeMove(upX, upY);				isMove = false;				isLongClick = false;				break;			}			removeCallbacks(longPressRun);		}		return super.onTouchEvent(ev);	}	/**	 * @Title: initWindowManager	 * @Description: 创建移动视图	 * @param bm	 * @param x	 * @param y	 * @throws	 */	public void initWindowManager(Bitmap bm, int x, int y) {		stopMove();		isFirst = false;		layoutParams = new WindowManager.LayoutParams();		layoutParams.gravity = Gravity.TOP | Gravity.LEFT;		layoutParams.horizontalMargin = layoutParams.verticalMargin = 0;		layoutParams.x = x - touchPositionInItemX + offsetX;		layoutParams.y = y - touchPositionInItemY + offsetY;		layoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;		layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;		layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE				| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE				| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON				| WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;		layoutParams.format = PixelFormat.TRANSLUCENT;		layoutParams.windowAnimations = 0;		windowManager = (WindowManager) this.getContext().getSystemService(				"window");		ImageView moveViewTemp = new ImageView(getContext());		moveViewTemp.setImageBitmap(bm);		windowManager = (WindowManager) this.getContext().getSystemService(				"window");		windowManager.addView(moveViewTemp, layoutParams);		moveView = moveViewTemp;	}	/**	 * @Title: stopMove	 * @Description: 停止移动	 * @throws	 */	public void stopMove() {		if (moveView != null) {			windowManager.removeView(moveView);			moveView = null;		}	}	/**	 * @Title: onMove	 * @Description: 视图移动的时候触发的方法	 * @param x	 * @param y	 * @throws	 */	public void onMove(int x, int y) {		isMove = true;		// 避免拖动到无效区域		int tempPosition = this.pointToPosition(x, y);		if (tempPosition != FreedomGridView.INVALID_POSITION) {			this.moveToPosition = tempPosition;		}		// 移动的时候更新视图位置		if (moveView != null) {			layoutParams.alpha = 0.8f;			layoutParams.y = y - touchPositionInItemY + offsetY;			layoutParams.x = x - touchPositionInItemX + offsetX;			windowManager.updateViewLayout(moveView, layoutParams);		}		int scrollHeight = 0;		if (y < upScrollBounce) {			scrollHeight = 30;		} else if (y > downScrollBounce) {			scrollHeight = -30;		}		// 触发自动滚动		if (scrollHeight != 0) {			smoothScrollToPositionFromTop(moveToPosition,					getChildAt(moveToPosition - getFirstVisiblePosition())							.getTop() + scrollHeight, 1);		}	}	/**	 * @Title: completeMove	 * @Description: 移动完成时	 * @param x	 * @param y	 * @throws	 */	public void completeMove(int x, int y) {		isFirst = true;		// 拿到停止的位置		int tempPosition = this.pointToPosition(x, y);		if (tempPosition != FreedomGridView.INVALID_POSITION) {			this.moveToPosition = tempPosition;		}		if (y < getChildAt(0).getTop()) {			return;		} else if (y > getChildAt(getChildCount() - 1).getBottom()) {			moveToPosition = getAdapter().getCount() - 1;			return;		} else {			// 如果在有效位置			if (moveToPosition >= 0 && moveToPosition < getAdapter().getCount()) {				ViewGroup itemView = (ViewGroup) this.getChildAt(moveToPosition						- this.getFirstVisiblePosition());				if (itemView != null) {					ImageView imaveView = (ImageView) itemView							.findViewById(R.id.desk_back);					// 判断是否移入了有效视图里面					boolean isIn = this.contains(imaveView,							x - itemView.getLeft(), y - itemView.getTop());					// 如果已经移入了,并且不是触摸时的起始位置					if (isIn) {						if (moveToPosition != touchPositionInScreen) {							itemView.startAnimation(AnimationUtils									.loadAnimation(getContext(),											R.anim.desk_scale));							Data touchData = ((Data) adapter									.getItem(touchPositionInScreen));							if (touchData.getNum() == 0) {								Toast.makeText(getContext(), "数目为0不可变化",										Toast.LENGTH_SHORT).show();								return;							}							Data toData = (Data) adapter									.getItem(moveToPosition);							if (toData.getNum() == 2) {								Toast.makeText(getContext(), "数目为2不可变化",										Toast.LENGTH_SHORT).show();								return;							}							touchData.setNum(touchData.getNum() - 1);							toData.setNum(toData.getNum() + 1);							adapter.notifyDataSetChanged();						}					}				}			}		}	}}






  相关解决方案