Android開發之自訂View專題(三):自訂GridView

來源:互聯網
上載者:User

Android開發之自訂View專題(三):自訂GridView

gridview作為android開發中常用的組件,其功能十分強大。但是,我們有時候有很多特殊的需求,需要在其基礎上進行改造。有時候會有移動gridView中item位置的需求,這個網上已經有很多例子,博主就不在描述。今天博主講的是移動gridView中item中的內容。博主沒看過網上那些移動item位置的demo,不知道其原理是不是和博主想的一樣。博主思考過,似乎博主的這種實現原理似乎也可以用作實現移動item位置。而之前博主百思不得其解的小米手機的案頭的自訂亂序排放,似乎也可以用這個原理去實現。好了,廢話不多說,先上

 

這裡博主就以數字為內容來示範,不同的數字item的背景顏色不同來區分,長按住一個item後可以移動,每次移動,移動的item減1,移動到的item加1。效果還可以吧。好了,上代碼,大家一起學習。瞭解其實現原理的同學完全可以自己修改代碼開發可移動item的gridView

完整項目:www.bkjia.com

(最近網路不給力,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 (x_freedom_reddevil@126.com) * @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() {@Overridepublic 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);}@Overridepublic 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;}// 拿到當前觸摸的可見itemViewGroup 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視圖的bitmapbitmap = 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);// 移除之前的runableremoveCallbacks(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();}}}}}}}


 

 

 

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.