请选择 进入手机版 | 继续访问电脑版
查看: 50601|回复: 38

[Android开发资源分享] Android 高仿项目:网易、今日头条、腾讯视频 附源码DEMO

[复制链接]
发表于 2014-8-8 11:31 | 显示全部楼层 |阅读模式
距离上次发布Android高仿系列项目:今日头条—新闻阅读器(2)6 v: y% h# R; ]( |! x8 |9 T5 z
相关的内容已经半个月了,最近利用空闲时间,把今日头条客户端完善了下。完善的功能一个一个全部实现后,就放整个源码。开发的进度就是按照一个一个功能的思路走的,所以开发一个小的功能,如果有用,就写一个专门的博客以便有人用到独立的功能可以方便使用。
$ n" z3 t8 z3 l9 h% g7 G# h这次实现的功能是很多新闻阅读器(网易,今日头条,360新闻等)以及腾讯视频等里面都会出现的频道管理功能。
4 F, p8 j, p+ u% l9 J7 v4 \
: g) u% x. d4 F9 L1 C6 H- L8 G

3 z: Q2 y  f6 X% g8 M, q下面先上这次实现功能的效果图:(注:这个效果图没有拖拽的时候移动动画,DEMO里面有,可以下载看看), ~) P5 b) R& W5 K: a: ]! y; A
6 o! {. X: q4 B% }# x1 ^$ A
+ d4 P0 k5 F7 D2 D- w& L
1399250647_1821.gif & D( g, f4 y+ T2 X% e( g6 K& k# _
一、开发心里历程: S" y* o  f- e# A/ @: d* g' F! {

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

  z$ d' e2 v/ N, {8 A" x, h8 i' \7 x$ |& E4 n2 u: a* p$ J% a" |

' u0 {8 U$ h: p二、开发前的准备
- C6 h  O% L: M9 u! ?- I1 |  o( I
, z. _; [8 N4 \; d* \9 q2 N, |: {
1.了解重写View的相关知识,并且知道GridView的一些内部方法,如:怎么通过触摸的坐标获取对应的position等(这里我采用的是继承GridView控件)1 k* L3 X0 @, h; u1 L$ f; ~( A7 F2 y* g& H
2.了解屏幕触摸动作传递原理    这里我以前转载的一篇或许会有帮助:Android事件分发机制完全解析,带你从源码的角度彻底理解(全)  A+ ]" r; \9 j4 R3 U; s( ^
) T5 A/ J" O  H" y$ b
3.了解位移动画Animation,本DEMO中主要用到:TranslateAnimation  平移动画
9 e: m! j+ @- t  _4.了解WindowManager的窗口机制,这里的item拖拽等都要设计到这个。
7 _/ ~0 {" k! N( L8 u. M/ C( E5.了解SQLiteDatabase 以及SQLiteOpenHelper等数据库操作相关的类,本DEMO中主要用到数据库进行存储频道信息,如果你要用文档进行存储读取也可以。
% `# n! u9 f  l: v( R  S8 y( g, C' Q
: P+ l4 R0 ?' R- R7 L* W( t) C
三、开发思路1.  获取数据库中频道的列表,如果为空,赋予默认列表,并存入数据库,之后通过对应的适配器赋给对应的GridView8 }2 }( P' V$ T

, p9 t& u4 ^( N( J8 p
( ?5 O/ u4 s; ]5 E+ F
2.  2个GridView--(1.DragGrid   2. OtherGridView)
8 V; w* g1 N7 ]. p* ]( ADragGrid 用于显示我的频道,带有长按拖拽效果
. \1 Y4 @  u# q6 t/ ]& DOtherGridView用于显示更多频道,不带推拽效果
! s) v: _: c: t) c# C4 X9 s注:由于屏幕大小不一定,外层使用ScrollView,所以2者都要重写计算高度7 Y' R% ]  s! r2 i$ X' R

2 q8 K/ i# v+ e+ {7 z$ M

5 B0 |0 j& b+ q( r, i8 x0 Y) |3.  点击2个GridView的时候,根据点击的Item对应的position,获取position对应的view,进行创建一层移动的动画层: B7 z& j* }9 b# Y/ H0 u3 N
起始位置:点击的positiongetLocationInWindow()获取。终点位置:另一个GridView的最后个ITEM 的position + 1的位置。
% g1 \, U5 x! o9 t- d: C并赋予移动动画,等动画结束后对2者对应的频道列表进行数据的remove和add操作。) S7 ~( u! `3 \8 }# a5 z
" g% J& \9 p$ C

9 d, ~& o& u2 f) ^/ `, g) y4.  设置点击和拖动的限制条件,如  推荐  这个ITEM是不允许用户操作的。9 M  [' @' y4 i- [/ g) M
1 X' T9 |% X, J, ?- Q/ `' A- I% Q

. T4 E% ~, _& Q+ z, G5.  拖动的DragGrid的操作:6 z2 F- Q) ?5 T: s# A$ W$ T6 n( j
(1)长按获取长按的ITEM的position  -- dragPosition 以及对应的view ,手指触摸屏幕的时候,调用onInterceptTouchEvent来获取MotionEvent.ACTION_DOWN事件,获取对应的数据。由于这里是继承了GridView,所以长按时间可以通过setOnItemLongClickListener监听来执行,或则你也可以通过计算点击时间来监听是否长按。  Z0 e! b% i& I
(2)通过onTouchEvent(MotionEvent ev)来监听手指的移动和抬起动作。当它移动到 其它的item下面,并且下方的item对应的position  不等于 dragPosition,进行数据交换,并且2者之间的所有item进行移动动画,动画结束后,数据更替刷新界面。& S# Y  E5 H0 F# |& D4 X
(3) 抬起手后,清除掉拖动时候创建的view,让GridView中的数据显示。  T* P' [# @# k+ O' G3 {

* R  O& a! P( r

! Q1 i: H. X! @5 \0 }: s( [& w) f5 {6.  退出时候,将改变后的频道列表存入数据库。: J- [: p6 r3 Y- F

( e3 D* U% ^3 G- R: R2 P0 z
' F5 N* F$ g) {; B% r7 _+ _
四、流程图下面是大体的流程图:7 G/ j5 h$ h" O3 A% B/ @* X
20140504235519968.jpg 5 t9 n  U5 S7 S* v1 A. _& x( K
五、核心代码点击进行添加删除:% n( l* r1 d: P' M. C
  1. /** GRIDVIEW对应的ITEM点击监听接口  */' v, W7 A  B, B
  2.         @Override- Z2 s8 {$ H# k
  3.         public void onItemClick(AdapterView<?> parent, final View view, final int position,long id) {
    6 r5 C' y, Y; N
  4.                 //如果点击的时候,之前动画还没结束,那么就让点击事件无效! |" b- K) z; T, T
  5.                 if(isMove){
    " F6 k- G; w# V
  6.                         return;, I4 O; p* K6 J6 x1 `. L# G2 D+ C
  7.                 }0 d: t9 Q7 a( h. _* h$ k5 S0 ~0 q& w% I- d  t
  8.                 switch (parent.getId()) {
    . U5 }$ ^5 T- g! N. _& x! B0 |
  9.                 case R.id.userGridView:/ B4 ?. z  X  ]1 `' p0 L8 M( _
  10.                         //position为 0,1 的不可以进行任何操作6 t, _. L$ z, n% l
  11.                         if (position != 0 && position != 1) {
    ! i5 @6 S8 h  v9 Z1 |! ~, R. m+ G
  12.                                 final ImageView moveImageView = getView(view);
    . p7 A, b; e9 `) j
  13.                                 if (moveImageView != null) {0 ?7 l! H6 B5 T; A" S' _4 X# i0 z
  14.                                         TextView newTextView = (TextView) view.findViewById(R.id.text_item);
    ; ^% s8 u$ C3 M. G1 R! S
  15.                                         final int[] startLocation = new int[2];
    & |: \) ?% n' X/ a9 o  G1 X7 B
  16.                                         newTextView.getLocationInWindow(startLocation);
    ; `3 b6 A$ w9 |9 c# H* k- }- E  @* k
  17.                                         final ChannelItem channel = ((DragAdapter) parent.getAdapter()).getItem(position);//获取点击的频道内容
    - }( j+ S: x: L7 p9 i: i
  18.                                         otherAdapter.setVisible(false);' l4 J5 Q7 X$ f$ m; [6 g
  19.                                         //添加到最后一个4 L9 b- y9 v% f
  20.                                         otherAdapter.addItem(channel);4 d; f7 t% H. Q( w5 l6 T1 e- _( ?
  21.                                         new Handler().postDelayed(new Runnable() {: P( M  x" i* g: `! e
  22.                                                 public void run() {
    $ d# r2 L6 V4 R
  23.                                                         try {8 w: t# ?9 \) a5 y  a
  24.                                                                 int[] endLocation = new int[2];
    / t- I% p. S/ X5 s3 W/ x+ x
  25.                                                                 //获取终点的坐标' a% G& y6 L; F4 v# U3 y& F. \0 a4 B
  26.                                                                 otherGridView.getChildAt(otherGridView.getLastVisiblePosition()).getLocationInWindow(endLocation);
    $ Z- S; ~9 o8 c, X8 z4 w
  27.                                                                 MoveAnim(moveImageView, startLocation , endLocation, channel,userGridView);6 z3 E( e+ Q9 }: d& M3 [4 i
  28.                                                                 userAdapter.setRemove(position);
    7 Y" Q) l# Y8 Z6 Q1 [$ q
  29.                                                         } catch (Exception localException) {
    " t( q7 V, J- _; N
  30.                                                         }
    & ^/ `7 _5 f$ P9 j+ B
  31.                                                 }
    # \, m9 z9 m" U
  32.                                         }, 50L);- O. I2 b2 C$ Z- f' M- k9 H9 A
  33.                                 }3 p4 }) B9 o# [$ F  }8 b$ }
  34.                         }* m) k0 n% H. z+ Q( `" h
  35.                         break;
    . S" T+ t- r5 y# I
  36.                 case R.id.otherGridView:  x5 V( {$ z* g( ?  J
  37.                         final ImageView moveImageView = getView(view);
    : k/ {" A7 I# i' a  Y
  38.                         if (moveImageView != null){
    1 d' ~* E" R9 J, F) x; K
  39.                                 TextView newTextView = (TextView) view.findViewById(R.id.text_item);
      Z" t% V2 T- }$ [+ U# I6 L
  40.                                 final int[] startLocation = new int[2];2 w, F& ?3 m8 [8 P4 j# U9 d3 v# v
  41.                                 newTextView.getLocationInWindow(startLocation);" z+ n" f) X/ I4 j1 S) O
  42.                                 final ChannelItem channel = ((OtherAdapter) parent.getAdapter()).getItem(position);
    3 Z4 w& {/ \- y& V: d0 i
  43.                                 userAdapter.setVisible(false);6 A& ~. [" l6 [' `
  44.                                 //添加到最后一个3 ^( c3 {5 \" r* x/ ~+ V; v
  45.                                 userAdapter.addItem(channel);5 D4 O) [! F; g& q0 s5 Q* t
  46.                                 new Handler().postDelayed(new Runnable() {
    6 @* Q" k1 B8 E
  47.                                         public void run() {
    ! c% @4 x& p3 R: H# T) `
  48.                                                 try {7 U' n9 P2 X  ^3 f
  49.                                                         int[] endLocation = new int[2];
    : F( U& q8 t% x* J
  50.                                                         //获取终点的坐标6 I( \8 `4 h6 I! T( u  u4 `
  51.                                                         userGridView.getChildAt(userGridView.getLastVisiblePosition()).getLocationInWindow(endLocation);
    8 l* u3 s& H5 {+ |3 |" h' }) c; z
  52.                                                         MoveAnim(moveImageView, startLocation , endLocation, channel,otherGridView);
    $ _# ^$ Y3 X' V* p) @( Y1 @
  53.                                                         otherAdapter.setRemove(position);
    1 N$ z  l- ~$ I/ o
  54.                                                 } catch (Exception localException) {& }( e0 J# s/ z0 d
  55.                                                 }
    5 H+ E+ t7 S& D) V  ]7 g# |
  56.                                         }# ?" g1 V# R/ i5 w+ i
  57.                                 }, 50L);
    & P5 H- i9 X3 N- r' v! @
  58.                         }
    % Y' Z7 _- b; a) A
  59.                         break;: E6 d; n7 \. u/ c7 I  F8 C
  60.                 default:
    6 k( P/ L% v/ O& V8 S
  61.                         break;5 c# ?3 M; V; p6 M5 d
  62.                 }. v2 r$ M& j% F9 q2 s' N
  63.         }
复制代码
移动动画:
+ `0 F% v3 ]. ]0 K# k+ [# b
  1. <span style="font-size:14px;">private void MoveAnim(View moveView, int[] startLocation,int[] endLocation, final ChannelItem moveChannel,
    + [; X7 N, z0 q" q
  2.                         final GridView clickGridView) {+ k* `; e$ C9 L& T! |
  3.                 int[] initLocation = new int[2];, o, ^& X( k% T! ^, P
  4.                 //获取传递过来的VIEW的坐标, v0 [9 Y+ }4 i- m
  5.                 moveView.getLocationInWindow(initLocation);
    0 S7 r& e6 R9 g3 X  g& L% U& _2 p  S+ y8 e
  6.                 //得到要移动的VIEW,并放入对应的容器中
    : Z' V4 o' Y/ R
  7.                 final ViewGroup moveViewGroup = getMoveViewGroup();
    1 P( m! }1 j1 R, P' S3 p
  8.                 final View mMoveView = getMoveView(moveViewGroup, moveView, initLocation);7 v* p8 g& {8 ]! M- `( B
  9.                 //创建移动动画
    8 R+ e( ]# w: A9 m4 p+ u# R
  10.                 TranslateAnimation moveAnimation = new TranslateAnimation(
      b( M2 _0 R+ [' f' |
  11.                                 startLocation[0], endLocation[0], startLocation[1],7 _; ?0 j- Y6 \' G. ]+ }& X+ [
  12.                                 endLocation[1]);
    / P. A9 {* Y% H9 p" R1 f  {
  13.                 moveAnimation.setDuration(300L);//动画时间
    / y1 l. G4 I6 E+ P" C
  14.                 //动画配置2 a4 p; x2 v$ I1 C  @* ^2 J* m6 ]/ \
  15.                 AnimationSet moveAnimationSet = new AnimationSet(true);
    : ?7 e' O/ D, k* M
  16.                 moveAnimationSet.setFillAfter(false);//动画效果执行完毕后,View对象不保留在终止的位置
    % [' A) C6 t$ M5 ~  P$ `# \
  17.                 moveAnimationSet.addAnimation(moveAnimation);
    / |/ D) G) m- x" A% L! N# W3 S
  18.                 mMoveView.startAnimation(moveAnimationSet);2 c. Z' B: T% }! Q( p4 r
  19.                 moveAnimationSet.setAnimationListener(new AnimationListener() {
    ! s0 O! v4 Y8 c3 I* S+ P
  20.                         # s+ ~' i! O5 ~! w2 Z7 _6 d
  21.                         @Override* h4 {& s, W! f1 |$ z! ^4 e* {4 X
  22.                         public void onAnimationStart(Animation animation) {
    * V0 ^8 {! N# M9 q- H2 y, C
  23.                                 isMove = true;2 u4 b  G1 D% }1 i
  24.                         }
    4 W- q5 b' A  k6 X+ r
  25.                         
    ' @6 K+ i, z/ d' _* [
  26.                         @Override5 W! c8 Q. W+ s
  27.                         public void onAnimationRepeat(Animation animation) {
    2 R/ |5 X2 `: E$ Q2 n/ ?
  28.                         }4 q  O* ~7 N* j* C
  29.                         
    8 K( L* N/ S1 e( F) W/ a
  30.                         @Override
    $ |. h, W: b  d% S" @+ m
  31.                         public void onAnimationEnd(Animation animation) {3 R* }8 Q5 R! ]. y
  32.                                 moveViewGroup.removeView(mMoveView);
      I( x' k% |9 \4 s7 G
  33.                                 // instanceof 方法判断2边实例是不是一样,判断点击的是DragGrid还是OtherGridView  G- X+ O! G6 i+ @9 p" Q
  34.                                 if (clickGridView instanceof DragGrid) {3 ?9 n5 V! v5 z% `) E2 i
  35.                                         otherAdapter.setVisible(true);' @5 w" V* ?$ ^& R% A
  36.                                         otherAdapter.notifyDataSetChanged();6 c8 ~: R% p2 ^- x# z% R7 h' W- j
  37.                                         userAdapter.remove();
    / X# o  S, g! r
  38.                                 }else{- M7 G% y: h# r7 H+ ~, F( Q/ ?3 S: @
  39.                                         userAdapter.setVisible(true);6 U8 A" B( k5 r& z. x) K" [' o! T
  40.                                         userAdapter.notifyDataSetChanged();
    3 X- S# O3 g$ o. e# f' M( g
  41.                                         otherAdapter.remove();% t0 k1 U: f% O5 y5 V" F
  42.                                 }4 ?, \- \  m$ g
  43.                                 isMove = false;; y2 L- V; L8 ~7 q
  44.                         }" p3 c. W: h" b' I
  45.                 });+ n1 G$ q' ^! F% J" F: \& G' I
  46.         }</span>
复制代码
3 [: r) @% X7 S( _- K
7 x2 v. \+ h2 m  W" v5 ?

* e1 o+ j- t' e! x4 @/ }7 @
 楼主| 发表于 2014-8-8 11:34 | 显示全部楼层
可拖拽的DragGrid代码:
2 s" k+ c8 n/ h. `. A! i1 l
  1. public class DragGrid extends GridView {8 ]! x' ~2 V# q2 r6 h; s
  2.         /** 点击时候的X位置 */% q% e/ w( \+ d
  3.         public int downX;
    8 R, }+ t( Q* X
  4.         /** 点击时候的Y位置 */; a# A( J, I$ n2 M8 A  L3 h: p; g
  5.         public int downY;
    ( |; l% Z- K' R; |! k6 L% ~7 F
  6.         /** 点击时候对应整个界面的X位置 */- l. J4 y5 I1 P7 M5 l
  7.         public int windowX;4 z9 Q# u, `, o8 B4 u- s
  8.         /** 点击时候对应整个界面的Y位置 */
    5 ~9 l5 C/ O- A# x' K- }, s# u
  9.         public int windowY;- H# F" j- L; s
  10.         /** 屏幕上的X */% G% o6 b) c9 j' R* W1 ?
  11.         private int win_view_x;
    " w6 I% v$ M/ w$ `
  12.         /** 屏幕上的Y */$ I) Q  b- r' a" X
  13.         private int win_view_y;0 K1 n# L. a# R- k3 I8 a' e; s" q
  14.         /** 拖动的里x的距离 */
    7 |) t7 n# m& h. G
  15.         int dragOffsetX;
    9 ]1 k% D, [- E8 C3 _5 n" C
  16.         /** 拖动的里Y的距离 */
    - D4 m5 c) J3 o' [( C; z
  17.         int dragOffsetY;
    5 h% F) g9 V3 d/ m: M7 R; p# |
  18.         /** 长按时候对应postion */
    2 z7 P/ F! E9 w. `5 l& w
  19.         public int dragPosition;" X( ~' J0 J5 E" Y# Y
  20.         /** Up后对应的ITEM的Position */3 B9 {5 }! h; z0 m3 d6 P/ ^/ L
  21.         private int dropPosition;
      D5 C: O0 Z& Y& y4 Z; T$ ?7 s
  22.         /** 开始拖动的ITEM的Position */' y  m' u% B) l: S
  23.         private int startPosition;
    , V) r6 {* w# ~/ ^9 p1 W5 a
  24.         /** item高 */
    * K% R+ O& {: m" S- Y) @
  25.         private int itemHeight;
    + e, E7 M* }! m9 p1 s8 f
  26.         /** item宽 */
    & f$ w9 p( B/ [5 ?
  27.         private int itemWidth;
    : B, `8 T6 b1 o+ R6 V7 I3 `6 V% E
  28.         /** 拖动的时候对应ITEM的VIEW */
    % ?0 q3 V# S! F% E" a; m% v, @
  29.         private View dragImageView = null;
    5 u: `( O# V0 S) M. V' G
  30.         /** 长按的时候ITEM的VIEW */
    ) C& w0 S- [! l/ B5 [, S# P
  31.         private ViewGroup dragItemView = null;
    # w$ u" D5 g( K! c7 c+ b+ {
  32.         /** WindowManager管理器 */
    - H. w- P* L" A. w
  33.         private WindowManager windowManager = null;
    2 K+ O  X$ v' X7 l+ A( Y
  34.         /** */
    % ]7 ]/ _# W$ a$ @# W2 O
  35.         private WindowManager.LayoutParams windowParams = null;
    0 W) H' z# [( g0 V
  36.         /** item总量 */
    8 n7 d' D5 `. S5 R9 c6 {6 a
  37.         private int itemTotalCount;
    ) u7 V, i! m9 D0 u9 o1 c& p
  38.         /** 一行的ITEM数量 */+ u3 u6 \! E, L1 N% Z
  39.         private int nColumns = 4;6 `. U8 ]# n2 B# e( y5 a: \6 ]
  40.         /** 行数 */! V$ w3 A4 ?) K3 z% U* Y! e5 V# d
  41.         private int nRows;
    5 ~; p+ b( w0 P
  42.         /** 剩余部分 */
    . I6 H$ R7 O+ m, J/ v% |" q
  43.         private int Remainder;
    % X; S$ O' i  J' A" ]
  44.         /** 是否在移动 */' p' J# i# y% i5 w
  45.         private boolean isMoving = false;
    % u- H1 Q# V6 d/ Q2 |
  46.         /** *// i. g* [6 Z8 f: R  z' h; m% q- d
  47.         private int holdPosition;& e0 B4 X& d, ?7 x" u6 D
  48.         /** 拖动的时候放大的倍数 */$ B8 ?: n& |* L. C
  49.         private double dragScale = 1.2D;- [2 b9 R! I4 Y+ I
  50.         /** 震动器 */
      T/ ~) D# K0 p, f# h4 E$ @
  51.         private Vibrator mVibrator;
    ) {. C6 a; G7 ?. ~
  52.         /** 每个ITEM之间的水平间距 */
    & Z" j  u- l4 Q0 Z' P+ a
  53.         private int mHorizontalSpacing = 15;( r7 B$ a( e# }( Q' S5 Q) W
  54.         /** 每个ITEM之间的竖直间距 */4 Q6 @  f9 h2 U0 b& ~- |
  55.         private int mVerticalSpacing = 15;" ^: r/ |+ ]6 g  Q* R3 J
  56.         /* 移动时候最后个动画的ID */
    * W1 r. ^: c" L4 e8 }& h
  57.         private String LastAnimationID;
    # X- |+ N. Q  i) Q
  58. 3 w" g# b* l! K  K
  59.         public DragGrid(Context context) {
    3 b( j3 I" `9 w9 P* }, |5 l
  60.                 super(context);- f) z2 w) _9 x* O- Y
  61.                 init(context);3 E3 l3 a3 ]) N# e
  62.         }! O/ h% H" w! x6 p' \- m$ h1 _
  63. 4 v/ q8 Z8 p% W. y3 J) ~  F+ ]
  64.         public DragGrid(Context context, AttributeSet attrs, int defStyle) {. ^' R& x) g/ L- R
  65.                 super(context, attrs, defStyle);
    2 ~) D& A* @+ Q  M& H5 E8 L! c
  66.                 init(context);
    5 v* E2 o# W) x5 g% w  r' G
  67.         }
    4 i! _* a7 r) ~9 _  F
  68. 1 `$ g, V' d& e7 @0 |/ W1 Q
  69.         public DragGrid(Context context, AttributeSet attrs) {
    2 S' ]9 h* a: V& z
  70.                 super(context, attrs);! O- \7 q' d2 j$ \* F
  71.                 init(context);& i. }+ U4 j$ H8 S9 q7 K/ k' M
  72.         }
    7 ~' S' F7 A* m# J' a' h3 d

  73. 1 R: z, U6 V# N  Z  \7 ]7 p
  74.         public void init(Context context) {
    7 q- g( z8 c5 ^+ x# F/ b
  75.                 mVibrator = (Vibrator) context
    2 q; g! `7 N. u$ M9 J" w4 |
  76.                                 .getSystemService(Context.VIBRATOR_SERVICE);
    8 r' W9 Y# _& R; O1 M* v+ n
  77.                 // 将布局文件中设置的间距dip转为px$ G+ V2 W# J3 c4 ?) |& e% |2 q% s
  78.                 mHorizontalSpacing = DataTools.dip2px(context, mHorizontalSpacing);- A8 L8 ?$ C3 [' p+ @
  79.         }
    " @* G6 O4 h2 ?# w, `+ J4 l

  80. 8 q4 J+ h, {5 j- A7 X
  81.         @Override
    8 x8 \" ?" T  `; s% Q8 x
  82.         public boolean onInterceptTouchEvent(MotionEvent ev) {2 x, V8 _4 Z* K6 _" F. w8 X
  83.                 // TODO Auto-generated method stub/ s% X. w. U" \" N0 U
  84.                 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
    ' a. L' H# l* r' r- g# F$ G) Z: }
  85.                         downX = (int) ev.getX();
    " L9 q9 ~8 ?- X; x: k6 D$ n* O
  86.                         downY = (int) ev.getY();
    / w! {" @* ^$ X  O" r9 @1 X
  87.                         windowX = (int) ev.getX();) K4 \% h8 b9 R& l% e/ @0 E+ S, I
  88.                         windowY = (int) ev.getY();
    . d: r" o: ~* x# {8 R
  89.                         setOnItemClickListener(ev);: {" `' D5 c  K- p! d
  90.                 }
    - q( @, w. T2 x1 j. G8 ~- ~1 B0 x
  91.                 return super.onInterceptTouchEvent(ev);
    % Q) V$ s0 Y2 X- ]! V3 m/ F
  92.         }2 T- l3 e& K" }+ \) N

  93. ( G7 M$ ^) U  v+ v- G2 n  f
  94.         @Override' X7 p3 i/ t( x
  95.         public boolean onTouchEvent(MotionEvent ev) {% }8 N9 C1 f9 o6 b
  96.                 // TODO Auto-generated method stub
    , c7 q! u; N/ K) P2 C
  97.                 boolean bool = true;
    5 Z3 ?% A9 ~; U8 r2 e6 |6 K5 L
  98.                 if (dragImageView != null
    3 r' ^( [7 `8 M* v
  99.                                 && dragPosition != AdapterView.INVALID_POSITION) {
    % S0 |4 {5 F0 ]" s, H3 `
  100.                         // 移动时候的对应x,y位置3 t. P6 W. F0 F- p9 s( U3 i
  101.                         bool = super.onTouchEvent(ev);
    # D+ n( |: e3 `. n' d& S
  102.                         int x = (int) ev.getX();' g6 s% q8 ~3 n3 s/ H6 Z# X& U
  103.                         int y = (int) ev.getY();# s: f; Q$ T% K+ |' K9 U
  104.                         switch (ev.getAction()) {
    " `  }$ c5 }7 b/ `  p
  105.                         case MotionEvent.ACTION_DOWN:
    * k" o/ B0 P4 z7 F+ `
  106.                                 downX = (int) ev.getX();* ]6 X1 D9 ?4 c/ X6 Z6 H
  107.                                 windowX = (int) ev.getX();4 @+ `2 _: V% Z6 w
  108.                                 downY = (int) ev.getY();
    ) e6 b& J, C" G3 L! C3 P8 y
  109.                                 windowY = (int) ev.getY();
    1 V% q% y9 n/ e' S
  110.                                 break;: Z0 O0 y& O' [2 B0 O1 l+ g
  111.                         case MotionEvent.ACTION_MOVE:
    . R2 P9 k. ^1 {
  112.                                 onDrag(x, y, (int) ev.getRawX(), (int) ev.getRawY());
    1 i; X" d1 F' b7 h, x& q+ ~! t
  113.                                 if (!isMoving) {; @  W. s' {1 P+ d1 l! c& Q  f
  114.                                         OnMove(x, y);3 e! V6 ^& [: k, c0 `& j
  115.                                 }5 E. {, Y$ h9 w+ A, p  W' b0 G
  116.                                 if (pointToPosition(x, y) != AdapterView.INVALID_POSITION) {( \2 r9 p% F1 [- r: w9 Y
  117.                                         break;
    " V) a7 p) h, r7 J- G( ?4 J
  118.                                 }! O3 E, W+ }2 _0 t8 A2 R
  119.                                 break;
    ! j/ c4 S+ `. m( p9 G. D/ |/ K
  120.                         case MotionEvent.ACTION_UP:! K; Q4 i- b3 v) a- D
  121.                                 stopDrag();
    + |2 `: b' F* I$ y0 j6 ~
  122.                                 onDrop(x, y);( G, x+ ]4 E! Z$ Y, Y$ J& [; X7 D" G
  123.                                 requestDisallowInterceptTouchEvent(false);+ ^1 t0 ]% K$ u0 o. L
  124.                                 break;
    ; g( L) m. N1 q" d  E

  125. ( L  T' O. i" Y
  126.                         default:
    + J% V5 J% L- y  b% ^% o" l
  127.                                 break;3 D" o3 N% X  o+ a* b" h/ D$ ]: W' {
  128.                         }, f% p, K4 |0 f& P) |
  129.                 }
    ' w& H9 n  i+ ^' w. }9 Y. ]
  130.                 return super.onTouchEvent(ev);
      I( j; u. P# E: F! A% b5 Z' w' D0 c
  131.         }
    1 p# A! M8 r5 V& d$ `- h
  132. ; Q5 @, D% H7 U2 j* ?7 T* Z4 Q
  133.         /** 在拖动的情况 */& P% i9 \# G3 H8 l* W1 n
  134.         private void onDrag(int x, int y, int rawx, int rawy) {
    1 D7 P5 I$ j% f0 s
  135.                 if (dragImageView != null) {
    + {! `# z! x+ r! s& V
  136.                         windowParams.alpha = 0.6f;" T# Z0 i" Q1 V. G7 P
  137.                         windowParams.x = rawx - win_view_x;
    2 x3 A- z# u3 F: v3 v5 G
  138.                         windowParams.y = rawy - win_view_y;
    ( o1 m, e2 G4 f5 L( l- t- j* T
  139.                         windowManager.updateViewLayout(dragImageView, windowParams);
    ; K* u) \1 Q+ H! b& [9 H
  140.                 }
    4 y; R6 S* ^$ z+ p3 Z7 e) A$ k' p
  141.         }
    ( w# ^' A4 `8 A/ x

  142.   z4 B/ [; t. U1 y& a. E# Z% g
  143.         /** 在松手下放的情况 */
    # }; s4 h9 H1 _+ [/ m$ s
  144.         private void onDrop(int x, int y) {, q1 l% m' M8 Z& s3 k: S; g  p! N
  145.                 // 根据拖动到的x,y坐标获取拖动位置下方的ITEM对应的POSTION1 n, L9 u/ u/ v: K6 w0 ~9 g8 t
  146.                 int tempPostion = pointToPosition(x, y);9 f2 p# u7 q$ [9 A7 p
  147.                 dropPosition = tempPostion;
    ! ?9 Y! m* W( @2 p# E
  148.                 DragAdapter mDragAdapter = (DragAdapter) getAdapter();
    - s4 f0 }1 C9 Z3 e
  149.                 // 显示刚拖动的ITEM
    ; ^* I- }# y* y$ m
  150.                 mDragAdapter.setShowDropItem(true);# g- I; ?5 D* F1 O
  151.                 // 刷新适配器,让对应的ITEM显示; k8 O$ t" @/ U7 ~' d7 w+ y6 v8 @
  152.                 mDragAdapter.notifyDataSetChanged();
    4 b; a1 Q: m; s
  153.         }% T% b. U; A$ \: P1 r

  154.   a2 `1 S1 G7 c
  155.         /**; v' J; ?% f, Y' o/ |0 G% @: J$ v
  156.          * 长按点击监听) I  d0 X" b0 x# `8 z+ c' X
  157.          * @param ev
    ( Q# P4 F. E1 N9 B4 M) A5 [1 d
  158.          */, _# y+ x! n5 s4 r9 y
  159.         public void setOnItemClickListener(final MotionEvent ev) {
    ) N6 Q% m, p: M5 ?; Q4 P
  160.                 setOnItemLongClickListener(new OnItemLongClickListener() {4 P' F" H: e- f4 e! }1 C# F
  161. 6 h( W* J% q2 b
  162.                         @Override+ l( R" _! i3 v0 k
  163.                         public boolean onItemLongClick(AdapterView<?> parent, View view,, G# q( \0 K1 Y' p" P
  164.                                         int position, long id) {  |" T* \& @% l4 ]) G
  165.                                 int x = (int) ev.getX();// 长安事件的X位置
    ; B7 e( I! ?( j* N" R) W
  166.                                 int y = (int) ev.getY();// 长安事件的y位置
    0 B2 \, d8 v; ?, ?7 C0 {. D/ o
  167.                                 startPosition = position;// 第一次点击的postion3 ^& Q, {. G% w  w4 f) J4 P+ n
  168.                                 dragPosition = position;
    % c0 {: F8 l0 W% R
  169.                                 if (startPosition <= 1) {
    6 T* k/ Y/ ~0 v- }& n( @; @4 H5 {
  170.                                         return false;1 K) N$ V. p( Z% ?7 m$ i9 I
  171.                                 }- g! o0 ~- ]. \+ {% i# T
  172.                                 ViewGroup dragViewGroup = (ViewGroup) getChildAt(dragPosition4 ]$ R6 h* I6 i1 y' ]
  173.                                                 - getFirstVisiblePosition());
    8 Y3 v( p( m! c5 x/ p6 \
  174.                                 TextView dragTextView = (TextView) dragViewGroup
    1 Q0 J* I6 l# S
  175.                                                 .findViewById(R.id.text_item);
    & L; u. e3 k& Z7 Q4 P" q
  176.                                 dragTextView.setSelected(true);, j; I. a0 I/ k+ [. W3 S
  177.                                 dragTextView.setEnabled(false);. y. F) m1 \1 z! q+ e
  178.                                 itemHeight = dragViewGroup.getHeight();0 U2 ?: U. z" M$ o$ U3 C9 _' B" f& q7 w
  179.                                 itemWidth = dragViewGroup.getWidth();
    ) {) y, z$ ?4 ?
  180.                                 itemTotalCount = DragGrid.this.getCount();7 K* g; P3 b, ~' n6 |
  181.                                 int row = itemTotalCount / nColumns;// 算出行数
    ( I: \7 w! |9 O
  182.                                 Remainder = (itemTotalCount % nColumns);// 算出最后一行多余的数量
    4 E$ B" P' {$ B5 b" y$ I& M5 R
  183.                                 if (Remainder != 0) {# n6 Z6 ]5 o- M/ a3 j
  184.                                         nRows = row + 1;" A2 a2 l1 B8 G
  185.                                 } else {
    + o4 \2 j8 M) o
  186.                                         nRows = row;! L$ w" q$ B" W8 x
  187.                                 }. N! n" r' P* [9 {9 `
  188.                                 // 如果特殊的这个不等于拖动的那个,并且不等于-1
    7 T  j! k& U$ g  X% q* E6 D
  189.                                 if (dragPosition != AdapterView.INVALID_POSITION) {
    ) a* U, ^* T" b3 ?
  190.                                         // 释放的资源使用的绘图缓存。如果你调用buildDrawingCache()手动没有调用setDrawingCacheEnabled(真正的),你应该清理缓存使用这种方法。" @& X0 A8 r4 D% U$ t
  191.                                         win_view_x = windowX - dragViewGroup.getLeft();// VIEW相对自己的X,半斤
    $ T' J- {7 P# f" }0 O
  192.                                         win_view_y = windowY - dragViewGroup.getTop();// VIEW相对自己的y,半斤, O) l% G* d. |& q& o
  193.                                         dragOffsetX = (int) (ev.getRawX() - x);// 手指在屏幕的上X位置-手指在控件中的位置就是距离最左边的距离
    % g' U3 A, c/ _% X- A
  194.                                         dragOffsetY = (int) (ev.getRawY() - y);// 手指在屏幕的上y位置-手指在控件中的位置就是距离最上边的距离
    ' r2 V  W6 r2 C% Z) w4 H) t: _# \
  195.                                         dragItemView = dragViewGroup;5 Y; R' p0 S  D1 a/ H0 s
  196.                                         dragViewGroup.destroyDrawingCache();, X  N1 y( p- z+ y. H. i
  197.                                         dragViewGroup.setDrawingCacheEnabled(true);! U! d3 w. X$ ]
  198.                                         Bitmap dragBitmap = Bitmap.createBitmap(dragViewGroup( \- i) U# e- I( D3 t- I9 [
  199.                                                         .getDrawingCache());
      e5 G6 k1 n/ w. U3 C* k  U( M
  200.                                         mVibrator.vibrate(50);// 设置震动时间4 M! \. O2 G0 R: D0 l0 X
  201.                                         startDrag(dragBitmap, (int) ev.getRawX(),
    3 _3 M- Y8 L0 B* g( p
  202.                                                         (int) ev.getRawY());
    , n/ g/ N* ?: i7 j1 a/ [
  203.                                         hideDropItem();; R4 z) T- V; [' h; B( J# L
  204.                                         dragViewGroup.setVisibility(View.INVISIBLE);
    3 o  G$ @3 n( R1 Q+ z& d+ M; {
  205.                                         isMoving = false;
    7 z. e6 {9 t4 C
  206.                                         requestDisallowInterceptTouchEvent(true);
    " P# |0 C1 J. `% c6 q" B; J9 _0 C
  207.                                         return true;
    7 d- y  d1 N  q4 p3 ?; ^! K
  208.                                 }
    # a9 t0 q/ U" W- y
  209.                                 return false;5 n5 p6 d/ B2 t8 V! Y
  210.                         }4 w5 e3 h( V/ A+ n
  211.                 });3 p4 \+ F* M% Q# Q8 v; c1 K
  212.         }! |' [: t/ i: a! A6 q) a+ u

  213. - ~8 Y& @0 h& v3 Z! l
  214.         public void startDrag(Bitmap dragBitmap, int x, int y) {
    ! R7 W" ]* C% E# l1 j
  215.                 stopDrag();3 j" F9 d9 p; j0 b/ z6 C% @' v
  216.                 windowParams = new WindowManager.LayoutParams();// 获取WINDOW界面的
    - f: `# p8 p7 z; n  N/ y- F% f. J
  217.                 // Gravity.TOP|Gravity.LEFT;这个必须加$ }8 o7 c5 i& ], |# z
  218.                 windowParams.gravity = Gravity.TOP | Gravity.LEFT;
    7 z5 ^7 P, p4 O
  219.                 // 得到preview左上角相对于屏幕的坐标" C  ^4 m4 j2 D
  220.                 windowParams.x = x - win_view_x;, m! C' n; I( W; E0 Y- }9 |
  221.                 windowParams.y = y - win_view_y;
    ; O% T( ^7 b9 O' M
  222.                 // 设置拖拽item的宽和高% s: h8 f1 [9 P! x2 u/ t
  223.                 windowParams.width = (int) (dragScale * dragBitmap.getWidth());// 放大dragScale倍,可以设置拖动后的倍数
    ( ]4 _( D: s( U" Q/ T# j
  224.                 windowParams.height = (int) (dragScale * dragBitmap.getHeight());// 放大dragScale倍,可以设置拖动后的倍数9 O' ^5 a- U0 }4 f
  225.                 this.windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    + j: U2 U. I- ~/ t
  226.                                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; f+ B9 s2 T3 r
  227.                                 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON( R* u) }, w8 I5 B! s
  228.                                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
    - p( x# w5 _& [- D5 J9 i1 G
  229.                 this.windowParams.format = PixelFormat.TRANSLUCENT;
    + d/ c3 T2 o# V: M
  230.                 this.windowParams.windowAnimations = 0;! N. H2 S7 J3 N8 [- N
  231.                 ImageView iv = new ImageView(getContext());% ~7 R9 Y" t+ l4 |/ U; F3 [
  232.                 iv.setImageBitmap(dragBitmap);) W: v5 }7 w- p: h: N0 y( T6 j1 c
  233.                 windowManager = (WindowManager) getContext().getSystemService(
    ( I0 h) f' G1 s! _6 O5 e0 P" }# j
  234.                                 Context.WINDOW_SERVICE);// "window"  [3 H4 U3 h8 _" r! W
  235.                 windowManager.addView(iv, windowParams);
    & n8 y6 i* u# w4 }  y  }7 Y
  236.                 dragImageView = iv;
    & h0 A; s+ y& m6 U) ~
  237.         }- h5 }# A# X- \9 L, F. ^
  238. , g. X8 \! Q! o% |0 s0 {3 I. }
  239.         /** 停止拖动 ,释放并初始化 */
    3 \6 P( T3 B& z6 B
  240.         private void stopDrag() {( g  \; K% j5 U) `6 u1 X
  241.                 if (dragImageView != null) {  @, \' t( O  H
  242.                         windowManager.removeView(dragImageView);4 o' O! h8 c( [
  243.                         dragImageView = null;
    4 R4 {( K$ C3 `( n" G8 @
  244.                 }# P+ D9 u0 U) I0 S1 l
  245.         }# ^% E$ B5 P2 t
  246. 3 r; N4 u! P5 A
  247.         /** 在ScrollView内,所以要进行计算高度 */
    ( e, ^0 O% @* I9 w/ U7 F" g
  248.         @Override, u; `2 z. Y  f; P* w' X: R6 p, A
  249.         public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    ' @( c# N* j8 i
  250.                 int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,7 _; Y. W/ b4 e" ?( I
  251.                                 MeasureSpec.AT_MOST);
    % H0 P" L3 \4 b) z2 D0 y1 K, u# |) |
  252.                 super.onMeasure(widthMeasureSpec, expandSpec);
    4 f" {: i  b& J: @8 |% c: z
  253.         }  t- ~, \4 g) D  q
  254. $ D' A* R2 U8 H1 _0 M! b. G- c( ~
  255.         /** 隐藏 放下 的ITEM */
    % ~: U+ X- B0 V( Q+ J
  256.         private void hideDropItem() {- E) Z0 y1 I* e
  257.                 ((DragAdapter) getAdapter()).setShowDropItem(false);9 k- y4 D: j% T. E/ f5 j
  258.         }
    ; ^+ \* L/ _% }4 e* o* O8 e

  259. : w" X$ @- q3 f1 p
  260.         /** 获取移动动画 */
    + v) d6 |. J3 l$ C- J7 t6 u
  261.         public Animation getMoveAnimation(float toXValue, float toYValue) {0 a  O2 a, f4 n5 m  |) m% p, x
  262.                 TranslateAnimation mTranslateAnimation = new TranslateAnimation(
    6 F% t6 J! Z( Z7 h# y! n& d. u/ @" `
  263.                                 Animation.RELATIVE_TO_SELF, 0.0F, Animation.RELATIVE_TO_SELF,, Y( c% s, P4 Q& W" V. s
  264.                                 toXValue, Animation.RELATIVE_TO_SELF, 0.0F,
    ; Q6 f& w# \2 V' Q1 M; g
  265.                                 Animation.RELATIVE_TO_SELF, toYValue);// 当前位置移动到指定位置
    % E. J; B0 ]* g# ^5 Z
  266.                 mTranslateAnimation.setFillAfter(true);// 设置一个动画效果执行完毕后,View对象保留在终止的位置。  R  Q' ~  C# d
  267.                 mTranslateAnimation.setDuration(300L);
    ; M# g8 y) v" z# x# u" i
  268.                 return mTranslateAnimation;9 ]% p3 s3 U: u! h5 f
  269.         }; s: b/ |- h2 ~- G; w# _6 A6 O+ g1 f% |' U

  270.   p2 F8 h, Q& g& ?8 d
  271.         /** 移动的时候触发 */) Q& m! j% d/ m, p* `1 i
  272.         public void OnMove(int x, int y) {
    * F3 n# ]3 c. i2 c
  273.                 // 拖动的VIEW下方的POSTION" s# N1 C8 v) a4 j$ b: g
  274.                 int dPosition = pointToPosition(x, y);
    ( T, u4 y: ?5 ?( I) @. z" N
  275.                 // 判断下方的POSTION是否是最开始2个不能拖动的
    + F* q* M3 ~5 b6 ^9 X0 t
  276.                 if (dPosition > 1) {
    . I4 x" t4 R9 f; w( r
  277.                         if ((dPosition == -1) || (dPosition == dragPosition)) {
    2 s- J/ X6 U$ Z
  278.                                 return;# K3 z' m. t( f# R
  279.                         }
    $ \3 j* S# Z) m& N, A4 B' s- h
  280.                         dropPosition = dPosition;
    % J" E" ]3 R0 T& x0 Q# y
  281.                         if (dragPosition != startPosition) {( a6 ~* X  N, ]7 o7 s4 G$ s
  282.                                 dragPosition = startPosition;5 ]0 J2 D1 a2 o, }! H5 Z, |
  283.                         }; o. W1 l9 v, y1 V" z
  284.                         int movecount;
    4 D  N' z0 e0 n8 K+ k6 }1 o* ]! N
  285.                         // 拖动的=开始拖的,并且 拖动的 不等于放下的6 i7 B( a5 b0 P
  286.                         if ((dragPosition == startPosition)
    ; M+ R7 w( O0 F# c+ \
  287.                                         || (dragPosition != dropPosition)) {
    ) X8 d+ \$ R$ P* g. c0 Q; L
  288.                                 // 移需要移动的动ITEM数量
    * }# M9 ]0 |7 X. O) H2 Y
  289.                                 movecount = dropPosition - dragPosition;
    3 V2 a  K& i- r+ d0 n
  290.                         } else {
    . s4 K) I1 x9 z' @
  291.                                 // 移需要移动的动ITEM数量为0
    / B2 T9 k4 T& J' _/ u
  292.                                 movecount = 0;; S0 J- I7 S( O7 \
  293.                         }& D/ F! B$ w: O8 }2 B4 J( \
  294.                         if (movecount == 0) {
    , [: c3 G1 l. q0 o: }
  295.                                 return;
    ) D- n. [3 B2 s- S6 x
  296.                         }: K& W5 z+ t6 Z! c6 _& I7 [
  297. 3 `) U" ]/ _$ _& \( c
  298.                         int movecount_abs = Math.abs(movecount);: j1 Z4 d/ ^% ]
  299. 2 n5 v% Z( x* k/ [) V8 g$ K
  300.                         if (dPosition != dragPosition) {
    - T, h4 X! S! d* g$ y% \8 {$ {. u
  301.                                 // dragGroup设置为不可见: o3 Q4 \- f" g  N: m
  302.                                 ViewGroup dragGroup = (ViewGroup) getChildAt(dragPosition);+ y* H4 M5 s7 ?! W
  303.                                 dragGroup.setVisibility(View.INVISIBLE);
    6 U, G: U* t* q9 c# O! C$ r
  304.                                 float to_x = 1;// 当前下方positon9 |8 h5 f" n& _* N8 K
  305.                                 float to_y;// 当前下方右边positon
    $ V' V% X; k/ C; S; p9 ]* E. a
  306.                                 // x_vlaue移动的距离百分比(相对于自己长度的百分比)1 `+ O0 n5 l/ B# G$ w
  307.                                 float x_vlaue = ((float) mHorizontalSpacing / (float) itemWidth) + 1.0f;4 C1 R4 D+ {3 d
  308.                                 // y_vlaue移动的距离百分比(相对于自己宽度的百分比)
    6 X. N7 j; e+ h
  309.                                 float y_vlaue = ((float) mVerticalSpacing / (float) itemHeight) + 1.0f;& @5 N8 i+ B( E* h0 z: J: G: c
  310.                                 Log.d("x_vlaue", "x_vlaue = " + x_vlaue);
    . T! F  E3 H8 J  Z: F8 r
  311.                                 for (int i = 0; i < movecount_abs; i++) {! N0 C% B1 y1 S& H) _- k
  312.                                         to_x = x_vlaue;; }/ |/ ~: a# c  F) e6 g8 P- ^. z! |
  313.                                         to_y = y_vlaue;) W  N% G* W  Z4 z; a0 ?
  314.                                         // 像左! K3 e/ a9 u( K) o% U5 B
  315.                                         if (movecount > 0) {
    ) h' T, I' a! N# |; C1 w
  316.                                                 // 判断是不是同一行的& q5 w5 H5 ?! r2 A+ U' l
  317.                                                 holdPosition = dragPosition + i + 1;/ Z9 R, w' b4 g
  318.                                                 if (dragPosition / nColumns == holdPosition / nColumns) {0 V5 H0 }( k1 D& t. n
  319.                                                         to_x = -x_vlaue;
    % L, `2 d' t' l3 e! u
  320.                                                         to_y = 0;
    ! f: H7 I' v- W* Q, w
  321.                                                 } else if (holdPosition % 4 == 0) {
    ! J+ ]- `4 |& I+ X1 G
  322.                                                         to_x = 3 * x_vlaue;
    / m4 p4 B/ {5 y/ `( `) T, s( c
  323.                                                         to_y = -y_vlaue;1 G$ ~3 A: \" S
  324.                                                 } else {
    . R( k  p5 H+ ]/ p
  325.                                                         to_x = -x_vlaue;9 y& `+ J) p/ W# A( {" a; K
  326.                                                         to_y = 0;
    , [- q) X- Z" \' H
  327.                                                 }
    ! ?7 U  J$ d3 M4 Y* m
  328.                                         } else {
    * ?5 L( f$ J- _
  329.                                                 // 向右,下移到上,右移到左/ h4 p) _9 R6 P' B' y
  330.                                                 holdPosition = dragPosition - i - 1;" v' K# N# D/ H+ M! P( j
  331.                                                 if (dragPosition / nColumns == holdPosition / nColumns) {
    5 G5 Q7 W0 z7 y% I: Z
  332.                                                         to_x = x_vlaue;
    7 A. @* r3 F% B
  333.                                                         to_y = 0;
    5 z. }2 {# ~7 A6 ^
  334.                                                 } else if ((holdPosition + 1) % 4 == 0) {' I& _' g& C6 J! ~/ S
  335.                                                         to_x = -3 * x_vlaue;7 V% H0 p. _% t+ @" s
  336.                                                         to_y = y_vlaue;( B2 I; M& f1 H! Y2 A
  337.                                                 } else {. x& g! S+ a% F0 Q% \+ `2 i
  338.                                                         to_x = x_vlaue;1 n* f2 p1 r2 Q* ]8 |2 @
  339.                                                         to_y = 0;
    & I. b" q. v! i% I: E$ h/ ?( d3 X, p: ~
  340.                                                 }
    ) `8 E, U5 x& F! ~. k
  341.                                         }
    , Z- d3 b5 S8 I' J8 @
  342.                                         ViewGroup moveViewGroup = (ViewGroup) getChildAt(holdPosition);
    ! d5 R+ z1 i. n: g! Z
  343.                                         Animation moveAnimation = getMoveAnimation(to_x, to_y);
    6 E+ A) O( x4 U* N: x) y: r
  344.                                         moveViewGroup.startAnimation(moveAnimation);2 ?  {5 ?8 s( ]0 o& H1 S
  345.                                         // 如果是最后一个移动的,那么设置他的最后个动画ID为LastAnimationID
    3 V. H/ a/ K. I1 B  t1 H
  346.                                         if (holdPosition == dropPosition) {
    . W- ]! B9 n4 j# x/ i- z3 w" {5 H
  347.                                                 LastAnimationID = moveAnimation.toString();
    + b) M! J5 h# o9 Y
  348.                                         }
    ! ~, u( a' A! i) q( o$ ~
  349.                                         moveAnimation.setAnimationListener(new AnimationListener() {
    ' \% U( x& l+ o, H$ @8 s6 }

  350. 2 J' ]# @4 E2 t
  351.                                                 @Override* S1 d; w9 s" Y# I% U2 U- r; @
  352.                                                 public void onAnimationStart(Animation animation) {6 R6 X4 }" ^/ ^
  353.                                                         // TODO Auto-generated method stub1 _$ k2 ?4 A: `
  354.                                                         isMoving = true;
    . Z( D# u, l9 F; N$ u7 _
  355.                                                 }
    - z4 W; q: x8 o" Q* h. v, g

  356. * ~! F3 w) u. K
  357.                                                 @Override
    , U# C/ i! N2 U  W6 z8 R8 X  }
  358.                                                 public void onAnimationRepeat(Animation animation) {
    3 S) Q/ e# S+ z( F# Z* v0 f
  359.                                                         // TODO Auto-generated method stub
    1 j, q. {0 h0 H5 D- [5 H& q
  360. % C; u! t' R# P7 f
  361.                                                 }+ c; C( F! @4 a( L( ]

  362. ) Z  V2 }) ?8 [* t
  363.                                                 @Override$ b# X7 ~% `, [" D9 a( [
  364.                                                 public void onAnimationEnd(Animation animation) {
    ( ?: e; l" _9 c: [
  365.                                                         // TODO Auto-generated method stub- H" p% x; T; r# {. F3 v
  366.                                                         // 如果为最后个动画结束,那执行下面的方法$ u- ~9 d; {- J9 n, F; e3 ^0 i
  367.                                                         if (animation.toString().equalsIgnoreCase(
    : e9 J; g; N& w6 I* j
  368.                                                                         LastAnimationID)) {
    8 U5 O3 H% E8 m
  369.                                                                 DragAdapter mDragAdapter = (DragAdapter) getAdapter();/ a% S' @+ y0 L' i0 O
  370.                                                                 mDragAdapter.exchange(startPosition,
    . b- y! k3 `2 E& `: ~1 Y
  371.                                                                                 dropPosition);* z: Z3 e. R; \5 Y+ E
  372.                                                                 startPosition = dropPosition;
    6 F; a: U/ p. Z6 V* ?  R+ H
  373.                                                                 dragPosition = dropPosition;
    7 \3 E5 K( E. R7 H7 l
  374.                                                                 isMoving = false;
    + u1 @' O: i, v9 c) Q; D- M
  375.                                                         }
    : d* f7 o( k9 B- }0 H
  376.                                                 }  i, k% L" t0 U7 D1 k7 s( S& i
  377.                                         });
    # Z) b1 S  e  J" k2 [" J: C4 R& q
  378.                                 }
    ( o5 |& m  s- I4 S7 g& O
  379.                         }
    % h% E9 v3 R, ?. t
  380.                 }4 l, T6 B$ X2 U5 a1 A; `8 Z% |- l; }
  381.         }/ h5 f" _0 {: o% w$ E# |% m8 i/ M
  382. }
复制代码
数据库SQLHelper文件
; M- C* Y6 A" o0 l" E
  1. public class SQLHelper extends SQLiteOpenHelper {9 i4 h6 V4 x1 R/ V
  2.         public static final String DB_NAME = "database.db";// 数据库名称
    5 [2 E4 _# ?1 L. [' [
  3.         public static final int VERSION = 1;
    : \/ ]( ?- Y- j+ g* Z
  4.        
    / ~! C( Y* S2 v2 u
  5.         public static final String TABLE_CHANNEL = "channel";//数据表 0 r/ C, Y6 b4 C6 T2 _
  6. 7 ~% \5 V+ W1 I
  7.         public static final String ID = "id";//2 h2 B) D6 o! Y8 {4 ]$ q/ j' I
  8.         public static final String NAME = "name";
    2 P8 o7 P# L0 o- R& s
  9.         public static final String ORDERID = "orderId";
    0 o& S2 S/ o( d: {3 O. T# [, K
  10.         public static final String SELECTED = "selected";( Q3 J5 r! Q/ u0 i3 k
  11.         private Context context;
    ; E; H2 _0 Z2 }0 S( D7 A. ~
  12.         public SQLHelper(Context context) {
    5 M6 @+ k% n" R* q5 R1 k
  13.                 super(context, DB_NAME, null, VERSION);
    " ^$ p! e3 x$ M# c5 K: T( N
  14.                 this.context = context;
      w7 l; N7 r6 b# z8 h% |
  15.         }
    1 e- z% [% e" ?4 w2 x3 w

  16. 9 D, g, i. p& d; V4 R7 V4 V+ G
  17.         public Context getContext(){
    ) u$ M1 t: i) f- a" v1 H# ~  ]! m- v& ^
  18.                 return context;
    0 B& m" E5 d8 B; H# ~1 r6 L0 `
  19.         }
    ( T1 I* [8 ~6 s) R  `. g5 e
  20.        
    ; u) s; U. H4 C: q: c) @) J& `: J
  21.         @Override; ?& b$ O/ B6 l' Y% _0 M4 t( u  Q
  22.         public void onCreate(SQLiteDatabase db) {- i0 V* q9 L0 B
  23.                 // TODO 创建数据库后,对数据库的操作
      Q. L: o- |7 _. N
  24.                 String sql = "create table if not exists "+TABLE_CHANNEL +* c, Q# R. {8 `4 g
  25.                                 "(_id INTEGER PRIMARY KEY AUTOINCREMENT, " +- I# V0 ]% s+ @. a( p
  26.                                 ID + " INTEGER , " +& J9 \8 Y" n# X, _, f8 A
  27.                                 NAME + " TEXT , " +9 r: ]9 K; E6 _, ~$ v, Q" V
  28.                                 ORDERID + " INTEGER , " +
    : j, f# x9 l* {  |" C
  29.                                 SELECTED + " SELECTED)";
    # Q/ v( Z8 L& \4 I
  30.                 db.execSQL(sql);" j: p; H% Z. j) D
  31.         }/ c1 N, w4 ?& z2 A

  32. + l1 W5 t6 g% A" Q
  33.         @Override
    1 o9 j, }( `) L, U. z1 n( m
  34.         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    8 q* A( a9 S/ x
  35.                 // TODO 更改数据库版本的操作
    ! X9 k& g) k* z
  36.                 onCreate(db);
    : h9 t3 q) n, A( R: \
  37.         }
    # T: X" i' i1 R2 ]) {, X

  38. 7 f5 n1 w. Y5 G2 w/ S$ W2 F
  39. }
    5 q- j" c2 k" K( K& q
复制代码
注:本DEMO中,加入了长按震动,所以在权限里面记得加上“
5 Y. m- w6 `* v- ?3 P8 I& x: k9 F' U
  1.     <!-- 在SDCard中创建与删除文件权限 -->% \/ V3 v$ f) k( ^+ `" p
  2.     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />! F; J7 Y5 N- G& j% I6 Q3 `
  3.     <!-- 往SDCard写入数据权限 -->& c0 R6 U0 j: ~0 g5 |4 _
  4.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />9 O9 S+ n# I0 n0 a4 W+ q
  5.     <!-- 震动权限 -->! d/ I- [1 V6 z7 I) K5 |
  6.     <uses-permission android:name="android.permission.VIBRATE"/>
复制代码

7 ]+ I8 E2 i* w! L# X6 l1 L& M4 I% B& }) _六、源码下载源码DEMO下载地址如下:
7 }& O' g: Y" N* z- ?
游客,如果您要查看本帖隐藏内容请回复
1 g9 j5 S; b& S* b1 ^) ?
1 O# Q) s1 K2 c3 D; f

% _* m! z# M6 @# l7 Z* n% j* b
发表于 2014-8-9 18:03 | 显示全部楼层
ttedgdfgdfg
发表于 2014-9-5 10:03 | 显示全部楼层
谢谢分享                    
发表于 2014-9-30 10:07 | 显示全部楼层

1 \+ L; k  d2 q* x谢谢分享   
发表于 2014-10-27 21:58 | 显示全部楼层
必须支持楼主
发表于 2014-11-3 16:40 | 显示全部楼层
谢谢楼主,,分享,,下载看看
您需要登录后才可以回帖 登录 | 注册

本版积分规则

© 2001-2014Comsenz Inc.

快速回复 返回顶部 返回列表