zoukankan      html  css  js  c++  java
  • Android 高仿 频道管理----网易、今日头条、腾讯视频 (可以拖动的GridView)附源码DEMO

    距离上次发布(android高仿系列)今日头条 --新闻阅读器 (二)

    相关的内容已经半个月了,最近利用空闲时间,把今日头条客户端完善了下。完善的功能一个一个全部实现后,就放整个源码。开发的进度就是按照一个一个功能的思路走的,所以开发一个小的功能,如果有用,就写一个专门的博客以便有人用到独立的功能可以方便使用。

    这次实现的功能是很多新闻阅读器(网易,今日头条,360新闻等)以及腾讯视频等里面都会出现的频道管理功能。

     

    下面先上这次实现功能的效果图:(注:这个效果图没有拖拽的时候移动动画,DEMO里面有,可以下载看看)

    一、开发心里历程

    刚开始接触这个的时候,不知道要如何实现,去网上翻了一大堆资料,懂了个大概,就是目前可以找到的都是拖拽的时候,不带移动动画的,和线上的客户端交互效果相差甚远,在反反复复的尝试查看相关东西,大致的做了出来,目前在模拟器上似乎有一点小BUG,真机测试没有问题,就先放上来,如果发现问题在修改优化。代码反面,没有好好的修改调整,可能会有点乱,请见谅哈。

     

    二、开发前的准备

    1.了解重写View的相关知识,并且知道GridView的一些内部方法,如:怎么通过触摸的坐标获取对应的position等(这里我采用的是继承GridView控件)

    2.了解屏幕触摸动作传递原理    这里我以前转载的一篇或许会有帮助:Android事件分发机制完全解析,带你从源码的角度彻底理解(全)

    3.了解位移动画Animation,本DEMO中主要用到:TranslateAnimation  平移动画

    4.了解WindowManager的窗口机制,这里的item拖拽等都要设计到这个。

    5.了解SQLiteDatabase 以及SQLiteOpenHelper等数据库操作相关的类,本DEMO中主要用到数据库进行存储频道信息,如果你要用文档进行存储读取也可以。

     

    三、开发思路

    1.  获取数据库中频道的列表,如果为空,赋予默认列表,并存入数据库,之后通过对应的适配器赋给对应的GridView

     

    2.  2个GridView--(1.DragGrid   2. OtherGridView)

    DragGrid 用于显示我的频道,带有长按拖拽效果

    OtherGridView用于显示更多频道,不带推拽效果

    注:由于屏幕大小不一定,外层使用ScrollView,所以2者都要重写计算高度

     

    3.  点击2个GridView的时候,根据点击的Item对应的position,获取position对应的view,进行创建一层移动的动画层

    起始位置:点击的positiongetLocationInWindow()获取。终点位置:另一个GridView的最后个ITEM 的position + 1的位置。

    并赋予移动动画,等动画结束后对2者对应的频道列表进行数据的remove和add操作。

     

    4.  设置点击和拖动的限制条件,如  推荐  这个ITEM是不允许用户操作的。

     

    5.  拖动的DragGrid的操作:

    (1)长按获取长按的ITEM的position  -- dragPosition 以及对应的view ,手指触摸屏幕的时候,调用onInterceptTouchEvent来获取MotionEvent.ACTION_DOWN事件,获取对应的数据。由于这里是继承了GridView,所以长按时间可以通过setOnItemLongClickListener监听来执行,或则你也可以通过计算点击时间来监听是否长按。

    (2)通过onTouchEvent(MotionEvent ev)来监听手指的移动和抬起动作。当它移动到 其它的item下面,并且下方的item对应的position  不等于 dragPosition,进行数据交换,并且2者之间的所有item进行移动动画,动画结束后,数据更替刷新界面。

    (3) 抬起手后,清除掉拖动时候创建的view,让GridView中的数据显示。

     

    6.  退出时候,将改变后的频道列表存入数据库。

     

    四、流程图

    下面是大体的流程图:

     

    五、核心代码

    点击进行添加删除:
    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. /** GRIDVIEW对应的ITEM点击监听接口  */  
    2.     @Override  
    3.     public void onItemClick(AdapterView<?> parent, final View view, final int position,long id) {  
    4.         //如果点击的时候,之前动画还没结束,那么就让点击事件无效  
    5.         if(isMove){  
    6.             return;  
    7.         }  
    8.         switch (parent.getId()) {  
    9.         case R.id.userGridView:  
    10.             //position为 0,1 的不可以进行任何操作  
    11.             if (position != 0 && position != 1) {  
    12.                 final ImageView moveImageView = getView(view);  
    13.                 if (moveImageView != null) {  
    14.                     TextView newTextView = (TextView) view.findViewById(R.id.text_item);  
    15.                     final int[] startLocation = new int[2];  
    16.                     newTextView.getLocationInWindow(startLocation);  
    17.                     final ChannelItem channel = ((DragAdapter) parent.getAdapter()).getItem(position);//获取点击的频道内容  
    18.                     otherAdapter.setVisible(false);  
    19.                     //添加到最后一个  
    20.                     otherAdapter.addItem(channel);  
    21.                     new Handler().postDelayed(new Runnable() {  
    22.                         public void run() {  
    23.                             try {  
    24.                                 int[] endLocation = new int[2];  
    25.                                 //获取终点的坐标  
    26.                                 otherGridView.getChildAt(otherGridView.getLastVisiblePosition()).getLocationInWindow(endLocation);  
    27.                                 MoveAnim(moveImageView, startLocation , endLocation, channel,userGridView);  
    28.                                 userAdapter.setRemove(position);  
    29.                             } catch (Exception localException) {  
    30.                             }  
    31.                         }  
    32.                     }, 50L);  
    33.                 }  
    34.             }  
    35.             break;  
    36.         case R.id.otherGridView:  
    37.             final ImageView moveImageView = getView(view);  
    38.             if (moveImageView != null){  
    39.                 TextView newTextView = (TextView) view.findViewById(R.id.text_item);  
    40.                 final int[] startLocation = new int[2];  
    41.                 newTextView.getLocationInWindow(startLocation);  
    42.                 final ChannelItem channel = ((OtherAdapter) parent.getAdapter()).getItem(position);  
    43.                 userAdapter.setVisible(false);  
    44.                 //添加到最后一个  
    45.                 userAdapter.addItem(channel);  
    46.                 new Handler().postDelayed(new Runnable() {  
    47.                     public void run() {  
    48.                         try {  
    49.                             int[] endLocation = new int[2];  
    50.                             //获取终点的坐标  
    51.                             userGridView.getChildAt(userGridView.getLastVisiblePosition()).getLocationInWindow(endLocation);  
    52.                             MoveAnim(moveImageView, startLocation , endLocation, channel,otherGridView);  
    53.                             otherAdapter.setRemove(position);  
    54.                         } catch (Exception localException) {  
    55.                         }  
    56.                     }  
    57.                 }, 50L);  
    58.             }  
    59.             break;  
    60.         default:  
    61.             break;  
    62.         }  
    63.     }  
     
     
    移动动画:
    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <span style="font-size:14px;">private void MoveAnim(View moveView, int[] startLocation,int[] endLocation, final ChannelItem moveChannel,  
    2.             final GridView clickGridView) {  
    3.         int[] initLocation = new int[2];  
    4.         //获取传递过来的VIEW的坐标  
    5.         moveView.getLocationInWindow(initLocation);  
    6.         //得到要移动的VIEW,并放入对应的容器中  
    7.         final ViewGroup moveViewGroup = getMoveViewGroup();  
    8.         final View mMoveView = getMoveView(moveViewGroup, moveView, initLocation);  
    9.         //创建移动动画  
    10.         TranslateAnimation moveAnimation = new TranslateAnimation(  
    11.                 startLocation[0], endLocation[0], startLocation[1],  
    12.                 endLocation[1]);  
    13.         moveAnimation.setDuration(300L);//动画时间  
    14.         //动画配置  
    15.         AnimationSet moveAnimationSet = new AnimationSet(true);  
    16.         moveAnimationSet.setFillAfter(false);//动画效果执行完毕后,View对象不保留在终止的位置  
    17.         moveAnimationSet.addAnimation(moveAnimation);  
    18.         mMoveView.startAnimation(moveAnimationSet);  
    19.         moveAnimationSet.setAnimationListener(new AnimationListener() {  
    20.               
    21.             @Override  
    22.             public void onAnimationStart(Animation animation) {  
    23.                 isMove = true;  
    24.             }  
    25.               
    26.             @Override  
    27.             public void onAnimationRepeat(Animation animation) {  
    28.             }  
    29.               
    30.             @Override  
    31.             public void onAnimationEnd(Animation animation) {  
    32.                 moveViewGroup.removeView(mMoveView);  
    33.                 // instanceof 方法判断2边实例是不是一样,判断点击的是DragGrid还是OtherGridView  
    34.                 if (clickGridView instanceof DragGrid) {  
    35.                     otherAdapter.setVisible(true);  
    36.                     otherAdapter.notifyDataSetChanged();  
    37.                     userAdapter.remove();  
    38.                 }else{  
    39.                     userAdapter.setVisible(true);  
    40.                     userAdapter.notifyDataSetChanged();  
    41.                     otherAdapter.remove();  
    42.                 }  
    43.                 isMove = false;  
    44.             }  
    45.         });  
    46.     }</span>  

    可拖拽的DragGrid代码: 
    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. public class DragGrid extends GridView {  
    2.     /** 点击时候的X位置 */  
    3.     public int downX;  
    4.     /** 点击时候的Y位置 */  
    5.     public int downY;  
    6.     /** 点击时候对应整个界面的X位置 */  
    7.     public int windowX;  
    8.     /** 点击时候对应整个界面的Y位置 */  
    9.     public int windowY;  
    10.     /** 屏幕上的X */  
    11.     private int win_view_x;  
    12.     /** 屏幕上的Y */  
    13.     private int win_view_y;  
    14.     /** 拖动的里x的距离 */  
    15.     int dragOffsetX;  
    16.     /** 拖动的里Y的距离 */  
    17.     int dragOffsetY;  
    18.     /** 长按时候对应postion */  
    19.     public int dragPosition;  
    20.     /** Up后对应的ITEM的Position */  
    21.     private int dropPosition;  
    22.     /** 开始拖动的ITEM的Position */  
    23.     private int startPosition;  
    24.     /** item高 */  
    25.     private int itemHeight;  
    26.     /** item宽 */  
    27.     private int itemWidth;  
    28.     /** 拖动的时候对应ITEM的VIEW */  
    29.     private View dragImageView = null;  
    30.     /** 长按的时候ITEM的VIEW */  
    31.     private ViewGroup dragItemView = null;  
    32.     /** WindowManager管理器 */  
    33.     private WindowManager windowManager = null;  
    34.     /** */  
    35.     private WindowManager.LayoutParams windowParams = null;  
    36.     /** item总量 */  
    37.     private int itemTotalCount;  
    38.     /** 一行的ITEM数量 */  
    39.     private int nColumns = 4;  
    40.     /** 行数 */  
    41.     private int nRows;  
    42.     /** 剩余部分 */  
    43.     private int Remainder;  
    44.     /** 是否在移动 */  
    45.     private boolean isMoving = false;  
    46.     /** */  
    47.     private int holdPosition;  
    48.     /** 拖动的时候放大的倍数 */  
    49.     private double dragScale = 1.2D;  
    50.     /** 震动器 */  
    51.     private Vibrator mVibrator;  
    52.     /** 每个ITEM之间的水平间距 */  
    53.     private int mHorizontalSpacing = 15;  
    54.     /** 每个ITEM之间的竖直间距 */  
    55.     private int mVerticalSpacing = 15;  
    56.     /* 移动时候最后个动画的ID */  
    57.     private String LastAnimationID;  
    58.   
    59.     public DragGrid(Context context) {  
    60.         super(context);  
    61.         init(context);  
    62.     }  
    63.   
    64.     public DragGrid(Context context, AttributeSet attrs, int defStyle) {  
    65.         super(context, attrs, defStyle);  
    66.         init(context);  
    67.     }  
    68.   
    69.     public DragGrid(Context context, AttributeSet attrs) {  
    70.         super(context, attrs);  
    71.         init(context);  
    72.     }  
    73.   
    74.     public void init(Context context) {  
    75.         mVibrator = (Vibrator) context  
    76.                 .getSystemService(Context.VIBRATOR_SERVICE);  
    77.         // 将布局文件中设置的间距dip转为px  
    78.         mHorizontalSpacing = DataTools.dip2px(context, mHorizontalSpacing);  
    79.     }  
    80.   
    81.     @Override  
    82.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
    83.         // TODO Auto-generated method stub  
    84.         if (ev.getAction() == MotionEvent.ACTION_DOWN) {  
    85.             downX = (int) ev.getX();  
    86.             downY = (int) ev.getY();  
    87.             windowX = (int) ev.getX();  
    88.             windowY = (int) ev.getY();  
    89.             setOnItemClickListener(ev);  
    90.         }  
    91.         return super.onInterceptTouchEvent(ev);  
    92.     }  
    93.   
    94.     @Override  
    95.     public boolean onTouchEvent(MotionEvent ev) {  
    96.         // TODO Auto-generated method stub  
    97.         boolean bool = true;  
    98.         if (dragImageView != null  
    99.                 && dragPosition != AdapterView.INVALID_POSITION) {  
    100.             // 移动时候的对应x,y位置  
    101.             bool = super.onTouchEvent(ev);  
    102.             int x = (int) ev.getX();  
    103.             int y = (int) ev.getY();  
    104.             switch (ev.getAction()) {  
    105.             case MotionEvent.ACTION_DOWN:  
    106.                 downX = (int) ev.getX();  
    107.                 windowX = (int) ev.getX();  
    108.                 downY = (int) ev.getY();  
    109.                 windowY = (int) ev.getY();  
    110.                 break;  
    111.             case MotionEvent.ACTION_MOVE:  
    112.                 onDrag(x, y, (int) ev.getRawX(), (int) ev.getRawY());  
    113.                 if (!isMoving) {  
    114.                     OnMove(x, y);  
    115.                 }  
    116.                 if (pointToPosition(x, y) != AdapterView.INVALID_POSITION) {  
    117.                     break;  
    118.                 }  
    119.                 break;  
    120.             case MotionEvent.ACTION_UP:  
    121.                 stopDrag();  
    122.                 onDrop(x, y);  
    123.                 requestDisallowInterceptTouchEvent(false);  
    124.                 break;  
    125.   
    126.             default:  
    127.                 break;  
    128.             }  
    129.         }  
    130.         return super.onTouchEvent(ev);  
    131.     }  
    132.   
    133.     /** 在拖动的情况 */  
    134.     private void onDrag(int x, int y, int rawx, int rawy) {  
    135.         if (dragImageView != null) {  
    136.             windowParams.alpha = 0.6f;  
    137.             windowParams.x = rawx - win_view_x;  
    138.             windowParams.y = rawy - win_view_y;  
    139.             windowManager.updateViewLayout(dragImageView, windowParams);  
    140.         }  
    141.     }  
    142.   
    143.     /** 在松手下放的情况 */  
    144.     private void onDrop(int x, int y) {  
    145.         // 根据拖动到的x,y坐标获取拖动位置下方的ITEM对应的POSTION  
    146.         int tempPostion = pointToPosition(x, y);  
    147.         dropPosition = tempPostion;  
    148.         DragAdapter mDragAdapter = (DragAdapter) getAdapter();  
    149.         // 显示刚拖动的ITEM  
    150.         mDragAdapter.setShowDropItem(true);  
    151.         // 刷新适配器,让对应的ITEM显示  
    152.         mDragAdapter.notifyDataSetChanged();  
    153.     }  
    154.   
    155.     /** 
    156.      * 长按点击监听 
    157.      * @param ev 
    158.      */  
    159.     public void setOnItemClickListener(final MotionEvent ev) {  
    160.         setOnItemLongClickListener(new OnItemLongClickListener() {  
    161.   
    162.             @Override  
    163.             public boolean onItemLongClick(AdapterView<?> parent, View view,  
    164.                     int position, long id) {  
    165.                 int x = (int) ev.getX();// 长安事件的X位置  
    166.                 int y = (int) ev.getY();// 长安事件的y位置  
    167.                 startPosition = position;// 第一次点击的postion  
    168.                 dragPosition = position;  
    169.                 if (startPosition <= 1) {  
    170.                     return false;  
    171.                 }  
    172.                 ViewGroup dragViewGroup = (ViewGroup) getChildAt(dragPosition  
    173.                         - getFirstVisiblePosition());  
    174.                 TextView dragTextView = (TextView) dragViewGroup  
    175.                         .findViewById(R.id.text_item);  
    176.                 dragTextView.setSelected(true);  
    177.                 dragTextView.setEnabled(false);  
    178.                 itemHeight = dragViewGroup.getHeight();  
    179.                 itemWidth = dragViewGroup.getWidth();  
    180.                 itemTotalCount = DragGrid.this.getCount();  
    181.                 int row = itemTotalCount / nColumns;// 算出行数  
    182.                 Remainder = (itemTotalCount % nColumns);// 算出最后一行多余的数量  
    183.                 if (Remainder != 0) {  
    184.                     nRows = row + 1;  
    185.                 } else {  
    186.                     nRows = row;  
    187.                 }  
    188.                 // 如果特殊的这个不等于拖动的那个,并且不等于-1  
    189.                 if (dragPosition != AdapterView.INVALID_POSITION) {  
    190.                     // 释放的资源使用的绘图缓存。如果你调用buildDrawingCache()手动没有调用setDrawingCacheEnabled(真正的),你应该清理缓存使用这种方法。  
    191.                     win_view_x = windowX - dragViewGroup.getLeft();// VIEW相对自己的X,半斤  
    192.                     win_view_y = windowY - dragViewGroup.getTop();// VIEW相对自己的y,半斤  
    193.                     dragOffsetX = (int) (ev.getRawX() - x);// 手指在屏幕的上X位置-手指在控件中的位置就是距离最左边的距离  
    194.                     dragOffsetY = (int) (ev.getRawY() - y);// 手指在屏幕的上y位置-手指在控件中的位置就是距离最上边的距离  
    195.                     dragItemView = dragViewGroup;  
    196.                     dragViewGroup.destroyDrawingCache();  
    197.                     dragViewGroup.setDrawingCacheEnabled(true);  
    198.                     Bitmap dragBitmap = Bitmap.createBitmap(dragViewGroup  
    199.                             .getDrawingCache());  
    200.                     mVibrator.vibrate(50);// 设置震动时间  
    201.                     startDrag(dragBitmap, (int) ev.getRawX(),  
    202.                             (int) ev.getRawY());  
    203.                     hideDropItem();  
    204.                     dragViewGroup.setVisibility(View.INVISIBLE);  
    205.                     isMoving = false;  
    206.                     requestDisallowInterceptTouchEvent(true);  
    207.                     return true;  
    208.                 }  
    209.                 return false;  
    210.             }  
    211.         });  
    212.     }  
    213.   
    214.     public void startDrag(Bitmap dragBitmap, int x, int y) {  
    215.         stopDrag();  
    216.         windowParams = new WindowManager.LayoutParams();// 获取WINDOW界面的  
    217.         // Gravity.TOP|Gravity.LEFT;这个必须加  
    218.         windowParams.gravity = Gravity.TOP | Gravity.LEFT;  
    219.         // 得到preview左上角相对于屏幕的坐标  
    220.         windowParams.x = x - win_view_x;  
    221.         windowParams.y = y - win_view_y;  
    222.         // 设置拖拽item的宽和高  
    223.         windowParams.width = (int) (dragScale * dragBitmap.getWidth());// 放大dragScale倍,可以设置拖动后的倍数  
    224.         windowParams.height = (int) (dragScale * dragBitmap.getHeight());// 放大dragScale倍,可以设置拖动后的倍数  
    225.         this.windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE  
    226.                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE  
    227.                 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON  
    228.                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;  
    229.         this.windowParams.format = PixelFormat.TRANSLUCENT;  
    230.         this.windowParams.windowAnimations = 0;  
    231.         ImageView iv = new ImageView(getContext());  
    232.         iv.setImageBitmap(dragBitmap);  
    233.         windowManager = (WindowManager) getContext().getSystemService(  
    234.                 Context.WINDOW_SERVICE);// "window"  
    235.         windowManager.addView(iv, windowParams);  
    236.         dragImageView = iv;  
    237.     }  
    238.   
    239.     /** 停止拖动 ,释放并初始化 */  
    240.     private void stopDrag() {  
    241.         if (dragImageView != null) {  
    242.             windowManager.removeView(dragImageView);  
    243.             dragImageView = null;  
    244.         }  
    245.     }  
    246.   
    247.     /** 在ScrollView内,所以要进行计算高度 */  
    248.     @Override  
    249.     public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
    250.         int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,  
    251.                 MeasureSpec.AT_MOST);  
    252.         super.onMeasure(widthMeasureSpec, expandSpec);  
    253.     }  
    254.   
    255.     /** 隐藏 放下 的ITEM */  
    256.     private void hideDropItem() {  
    257.         ((DragAdapter) getAdapter()).setShowDropItem(false);  
    258.     }  
    259.   
    260.     /** 获取移动动画 */  
    261.     public Animation getMoveAnimation(float toXValue, float toYValue) {  
    262.         TranslateAnimation mTranslateAnimation = new TranslateAnimation(  
    263.                 Animation.RELATIVE_TO_SELF, 0.0F, Animation.RELATIVE_TO_SELF,  
    264.                 toXValue, Animation.RELATIVE_TO_SELF, 0.0F,  
    265.                 Animation.RELATIVE_TO_SELF, toYValue);// 当前位置移动到指定位置  
    266.         mTranslateAnimation.setFillAfter(true);// 设置一个动画效果执行完毕后,View对象保留在终止的位置。  
    267.         mTranslateAnimation.setDuration(300L);  
    268.         return mTranslateAnimation;  
    269.     }  
    270.   
    271.     /** 移动的时候触发 */  
    272.     public void OnMove(int x, int y) {  
    273.         // 拖动的VIEW下方的POSTION  
    274.         int dPosition = pointToPosition(x, y);  
    275.         // 判断下方的POSTION是否是最开始2个不能拖动的  
    276.         if (dPosition > 1) {  
    277.             if ((dPosition == -1) || (dPosition == dragPosition)) {  
    278.                 return;  
    279.             }  
    280.             dropPosition = dPosition;  
    281.             if (dragPosition != startPosition) {  
    282.                 dragPosition = startPosition;  
    283.             }  
    284.             int movecount;  
    285.             // 拖动的=开始拖的,并且 拖动的 不等于放下的  
    286.             if ((dragPosition == startPosition)  
    287.                     || (dragPosition != dropPosition)) {  
    288.                 // 移需要移动的动ITEM数量  
    289.                 movecount = dropPosition - dragPosition;  
    290.             } else {  
    291.                 // 移需要移动的动ITEM数量为0  
    292.                 movecount = 0;  
    293.             }  
    294.             if (movecount == 0) {  
    295.                 return;  
    296.             }  
    297.   
    298.             int movecount_abs = Math.abs(movecount);  
    299.   
    300.             if (dPosition != dragPosition) {  
    301.                 // dragGroup设置为不可见  
    302.                 ViewGroup dragGroup = (ViewGroup) getChildAt(dragPosition);  
    303.                 dragGroup.setVisibility(View.INVISIBLE);  
    304.                 float to_x = 1;// 当前下方positon  
    305.                 float to_y;// 当前下方右边positon  
    306.                 // x_vlaue移动的距离百分比(相对于自己长度的百分比)  
    307.                 float x_vlaue = ((float) mHorizontalSpacing / (float) itemWidth) + 1.0f;  
    308.                 // y_vlaue移动的距离百分比(相对于自己宽度的百分比)  
    309.                 float y_vlaue = ((float) mVerticalSpacing / (float) itemHeight) + 1.0f;  
    310.                 Log.d("x_vlaue", "x_vlaue = " + x_vlaue);  
    311.                 for (int i = 0; i < movecount_abs; i++) {  
    312.                     to_x = x_vlaue;  
    313.                     to_y = y_vlaue;  
    314.                     // 像左  
    315.                     if (movecount > 0) {  
    316.                         // 判断是不是同一行的  
    317.                         holdPosition = dragPosition + i + 1;  
    318.                         if (dragPosition / nColumns == holdPosition / nColumns) {  
    319.                             to_x = -x_vlaue;  
    320.                             to_y = 0;  
    321.                         } else if (holdPosition % 4 == 0) {  
    322.                             to_x = 3 * x_vlaue;  
    323.                             to_y = -y_vlaue;  
    324.                         } else {  
    325.                             to_x = -x_vlaue;  
    326.                             to_y = 0;  
    327.                         }  
    328.                     } else {  
    329.                         // 向右,下移到上,右移到左  
    330.                         holdPosition = dragPosition - i - 1;  
    331.                         if (dragPosition / nColumns == holdPosition / nColumns) {  
    332.                             to_x = x_vlaue;  
    333.                             to_y = 0;  
    334.                         } else if ((holdPosition + 1) % 4 == 0) {  
    335.                             to_x = -3 * x_vlaue;  
    336.                             to_y = y_vlaue;  
    337.                         } else {  
    338.                             to_x = x_vlaue;  
    339.                             to_y = 0;  
    340.                         }  
    341.                     }  
    342.                     ViewGroup moveViewGroup = (ViewGroup) getChildAt(holdPosition);  
    343.                     Animation moveAnimation = getMoveAnimation(to_x, to_y);  
    344.                     moveViewGroup.startAnimation(moveAnimation);  
    345.                     // 如果是最后一个移动的,那么设置他的最后个动画ID为LastAnimationID  
    346.                     if (holdPosition == dropPosition) {  
    347.                         LastAnimationID = moveAnimation.toString();  
    348.                     }  
    349.                     moveAnimation.setAnimationListener(new AnimationListener() {  
    350.   
    351.                         @Override  
    352.                         public void onAnimationStart(Animation animation) {  
    353.                             // TODO Auto-generated method stub  
    354.                             isMoving = true;  
    355.                         }  
    356.   
    357.                         @Override  
    358.                         public void onAnimationRepeat(Animation animation) {  
    359.                             // TODO Auto-generated method stub  
    360.   
    361.                         }  
    362.   
    363.                         @Override  
    364.                         public void onAnimationEnd(Animation animation) {  
    365.                             // TODO Auto-generated method stub  
    366.                             // 如果为最后个动画结束,那执行下面的方法  
    367.                             if (animation.toString().equalsIgnoreCase(  
    368.                                     LastAnimationID)) {  
    369.                                 DragAdapter mDragAdapter = (DragAdapter) getAdapter();  
    370.                                 mDragAdapter.exchange(startPosition,  
    371.                                         dropPosition);  
    372.                                 startPosition = dropPosition;  
    373.                                 dragPosition = dropPosition;  
    374.                                 isMoving = false;  
    375.                             }  
    376.                         }  
    377.                     });  
    378.                 }  
    379.             }  
    380.         }  
    381.     }  
    382. }  
     
    数据库SQLHelper文件
    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. public class SQLHelper extends SQLiteOpenHelper {  
    2.     public static final String DB_NAME = "database.db";// 数据库名称  
    3.     public static final int VERSION = 1;  
    4.       
    5.     public static final String TABLE_CHANNEL = "channel";//数据表   
    6.   
    7.     public static final String ID = "id";//  
    8.     public static final String NAME = "name";  
    9.     public static final String ORDERID = "orderId";  
    10.     public static final String SELECTED = "selected";  
    11.     private Context context;  
    12.     public SQLHelper(Context context) {  
    13.         super(context, DB_NAME, null, VERSION);  
    14.         this.context = context;  
    15.     }  
    16.   
    17.     public Context getContext(){  
    18.         return context;  
    19.     }  
    20.       
    21.     @Override  
    22.     public void onCreate(SQLiteDatabase db) {  
    23.         // TODO 创建数据库后,对数据库的操作  
    24.         String sql = "create table if not exists "+TABLE_CHANNEL +  
    25.                 "(_id INTEGER PRIMARY KEY AUTOINCREMENT, " +  
    26.                 ID + " INTEGER , " +  
    27.                 NAME + " TEXT , " +  
    28.                 ORDERID + " INTEGER , " +  
    29.                 SELECTED + " SELECTED)";  
    30.         db.execSQL(sql);  
    31.     }  
    32.   
    33.     @Override  
    34.     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
    35.         // TODO 更改数据库版本的操作  
    36.         onCreate(db);  
    37.     }  
    38.   
    39. }  
     
    注:本DEMO中,加入了长按震动,所以在权限里面记得加上“
    [java] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. <!-- 在SDCard中创建与删除文件权限 -->  
    2. <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  
    3. <!-- 往SDCard写入数据权限 -->  
    4. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />  
    5. <!-- 震动权限 -->  
    6. <uses-permission android:name="android.permission.VIBRATE"/>  


    六、源码下载

    源码DEMO下载地址如下:下载地址

     

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    sbt设置
    scala高级内容(二)
    scala高级内容(一) Case Class
    xubuntu手记
    ScalaTour 2.函数
    ScalaTour-1.基础
    springboot对jsp模板引擎的支持
    springboot对Thymeleaf模板引擎的支持
    SpringBoot接收参数的七种方式
    idea快捷代码提示和修改
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4785075.html
Copyright © 2011-2022 走看看