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

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

[复制链接]
发表于 2014-8-8 11:31 | 显示全部楼层 |阅读模式
距离上次发布Android高仿系列项目:今日头条—新闻阅读器(2)
7 V8 y  ?2 x( Z, I$ E' r相关的内容已经半个月了,最近利用空闲时间,把今日头条客户端完善了下。完善的功能一个一个全部实现后,就放整个源码。开发的进度就是按照一个一个功能的思路走的,所以开发一个小的功能,如果有用,就写一个专门的博客以便有人用到独立的功能可以方便使用。% Z. [: f9 J, L$ L+ d7 n
这次实现的功能是很多新闻阅读器(网易,今日头条,360新闻等)以及腾讯视频等里面都会出现的频道管理功能。
2 R4 n& ^' B% N- r0 F+ P) q4 ^* O+ L% B2 g6 x/ k, W- |

  ^& x2 c: e% R3 a下面先上这次实现功能的效果图:(注:这个效果图没有拖拽的时候移动动画,DEMO里面有,可以下载看看)
& f6 C3 C' n+ H  s+ B4 B( h" s4 ?1 Y2 ^* o8 @7 C3 D% `* i* Y9 c. _
$ P3 T7 z1 m- V" U7 }' ?
1399250647_1821.gif , N7 |' c9 p, q8 L
一、开发心里历程4 V" a& O7 B0 H! y$ P

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

* S. D. P# j; y. O; q8 f. J& j, |, K, t! u  W& \
" m* ^( D& t' I6 L' K
二、开发前的准备( k$ \1 }( N7 P
/ R0 F4 k7 Q, ~
1.了解重写View的相关知识,并且知道GridView的一些内部方法,如:怎么通过触摸的坐标获取对应的position等(这里我采用的是继承GridView控件)9 \: G4 y. b* E9 F3 |
2.了解屏幕触摸动作传递原理    这里我以前转载的一篇或许会有帮助:Android事件分发机制完全解析,带你从源码的角度彻底理解(全)
2 R, Q- b( V! [, Z) U" }$ P

5 F" o. k# n  J; |: f3.了解位移动画Animation,本DEMO中主要用到:TranslateAnimation  平移动画
+ t, c8 s1 c0 S4.了解WindowManager的窗口机制,这里的item拖拽等都要设计到这个。5 v) V4 N% Y- Q3 Q! z! [) C
5.了解SQLiteDatabase 以及SQLiteOpenHelper等数据库操作相关的类,本DEMO中主要用到数据库进行存储频道信息,如果你要用文档进行存储读取也可以。3 v4 d/ V1 |( ~- ~6 ?

8 h9 j: W# C, e3 H
6 g7 ^7 D  U5 B& n2 n$ s
三、开发思路1.  获取数据库中频道的列表,如果为空,赋予默认列表,并存入数据库,之后通过对应的适配器赋给对应的GridView6 U$ V: y* W" U, i

/ _1 B# p% D! a
- d( B$ ]- M4 J: C) A
2.  2个GridView--(1.DragGrid   2. OtherGridView)1 ]' h& u. f$ @
DragGrid 用于显示我的频道,带有长按拖拽效果
# H/ P1 _: |  G. TOtherGridView用于显示更多频道,不带推拽效果
3 G( W% C8 }; C( V7 B注:由于屏幕大小不一定,外层使用ScrollView,所以2者都要重写计算高度& G. j- F2 Z; s, \' R- O% X7 A

  g$ r: o: r! m, i* U. m0 B# F, \

; W3 I0 o' i; h( o# i3.  点击2个GridView的时候,根据点击的Item对应的position,获取position对应的view,进行创建一层移动的动画层
8 f% U8 y" e" [& A" I起始位置:点击的positiongetLocationInWindow()获取。终点位置:另一个GridView的最后个ITEM 的position + 1的位置。
8 @( Q+ [. V6 U0 x) k8 u9 f并赋予移动动画,等动画结束后对2者对应的频道列表进行数据的remove和add操作。
7 Z9 L" B5 M  b; O: X% F  {3 R* F, N1 U1 ^
9 q+ ^; ]; _% I# M# ^
4.  设置点击和拖动的限制条件,如  推荐  这个ITEM是不允许用户操作的。3 v0 u* e' h1 X

9 F5 H9 `2 ]; c% ^2 J
9 K3 r4 y: e! N/ z, X- H
5.  拖动的DragGrid的操作:( I* L2 ~$ P2 K+ y4 v
(1)长按获取长按的ITEM的position  -- dragPosition 以及对应的view ,手指触摸屏幕的时候,调用onInterceptTouchEvent来获取MotionEvent.ACTION_DOWN事件,获取对应的数据。由于这里是继承了GridView,所以长按时间可以通过setOnItemLongClickListener监听来执行,或则你也可以通过计算点击时间来监听是否长按。. c6 j3 b" c) w7 v$ U) T9 [" g. K
(2)通过onTouchEvent(MotionEvent ev)来监听手指的移动和抬起动作。当它移动到 其它的item下面,并且下方的item对应的position  不等于 dragPosition,进行数据交换,并且2者之间的所有item进行移动动画,动画结束后,数据更替刷新界面。! h  e2 G2 w! Z" s0 X
(3) 抬起手后,清除掉拖动时候创建的view,让GridView中的数据显示。
2 `% V. H( \  F. j& Y( j. C7 `2 ?8 `* s7 z  u6 N7 Z

+ H  t( C; c" U5 \9 m6.  退出时候,将改变后的频道列表存入数据库。' w- P$ _1 |% V4 f

' S1 w2 {) y2 P6 W0 `7 @7 Y

2 u9 v) J& U/ `5 r# f/ n5 o四、流程图下面是大体的流程图:/ h# H1 c$ q7 A
20140504235519968.jpg
- ~* D, m( e  p% E# e  z; K+ i6 V- T五、核心代码点击进行添加删除:  B% }5 g3 O9 |5 z7 x& |
  1. /** GRIDVIEW对应的ITEM点击监听接口  */
    * O; l2 S9 r1 `, M1 S  n  @
  2.         @Override# J  Z( \9 ]1 v& p! U4 y2 N
  3.         public void onItemClick(AdapterView<?> parent, final View view, final int position,long id) {
    ) i9 g! I! P& {0 ~
  4.                 //如果点击的时候,之前动画还没结束,那么就让点击事件无效
    / `$ c2 |3 j: w
  5.                 if(isMove){
    ! l7 M  E0 Q! ~
  6.                         return;# u, Q: e' y/ P) v( H
  7.                 }0 d- m/ c( ]2 X5 o9 j  p
  8.                 switch (parent.getId()) {
    / c7 `( f) `3 C
  9.                 case R.id.userGridView:6 ^$ v' m8 p9 W: D
  10.                         //position为 0,1 的不可以进行任何操作
    * R6 _& Q0 k3 `; W% p0 `7 \
  11.                         if (position != 0 && position != 1) {
    ) z& Y6 \% p! {! F' Y' E
  12.                                 final ImageView moveImageView = getView(view);: t1 N' N8 `3 i2 w; N+ _2 J
  13.                                 if (moveImageView != null) {3 Z2 s" z& [7 J: e
  14.                                         TextView newTextView = (TextView) view.findViewById(R.id.text_item);- H- A7 E5 @; ?9 m7 ^1 L& k
  15.                                         final int[] startLocation = new int[2];
    ! m0 s) t1 b0 l* F) I
  16.                                         newTextView.getLocationInWindow(startLocation);8 v% U: @$ \3 j( V3 L9 P/ z
  17.                                         final ChannelItem channel = ((DragAdapter) parent.getAdapter()).getItem(position);//获取点击的频道内容: A9 N) l& Q9 k6 E
  18.                                         otherAdapter.setVisible(false);
    1 @% \/ s' r! y, H
  19.                                         //添加到最后一个( ^/ |) O; e- H3 l( ?
  20.                                         otherAdapter.addItem(channel);
    ' f) p% }: z, l
  21.                                         new Handler().postDelayed(new Runnable() {
    $ M  L! E$ G8 I0 J9 w" y' c
  22.                                                 public void run() {
    3 d: a( X$ X% Z
  23.                                                         try {
      o3 w" v5 R  t3 H) c1 S. f
  24.                                                                 int[] endLocation = new int[2];
    4 C: v6 J# I! F9 D! R( e. U
  25.                                                                 //获取终点的坐标
    , J$ ^" R" o$ X! c: ~- [
  26.                                                                 otherGridView.getChildAt(otherGridView.getLastVisiblePosition()).getLocationInWindow(endLocation);
    . S; f; Y% d& t0 m3 B) f; A
  27.                                                                 MoveAnim(moveImageView, startLocation , endLocation, channel,userGridView);
    ' G) ?/ J& z# f* ~1 a7 Z: F, L
  28.                                                                 userAdapter.setRemove(position);
    7 u2 _- V6 p) L2 ~8 N
  29.                                                         } catch (Exception localException) {
    * d9 W8 X$ j" {6 ~- v1 Q
  30.                                                         }
    ; u1 A, m( n" W* w# E/ k
  31.                                                 }
    ; \9 J5 P6 M/ F) ]# n- {
  32.                                         }, 50L);
    . w1 V8 Q! l5 l
  33.                                 }
    % l* E6 h+ R9 A9 N/ g
  34.                         }/ X5 K' \; m, R1 e3 [2 U
  35.                         break;' ]( m& Q  l; {# _
  36.                 case R.id.otherGridView:; e9 A+ v( A6 [( B/ h' g
  37.                         final ImageView moveImageView = getView(view);
    6 G, W0 I: |: s- D+ M: {% D# j' h7 ^
  38.                         if (moveImageView != null){
    " I: P% N$ a' G  W# ?) P8 S6 L% n
  39.                                 TextView newTextView = (TextView) view.findViewById(R.id.text_item);
    % G, B7 A1 ], B
  40.                                 final int[] startLocation = new int[2];
    0 s2 q1 o; T, _4 q* T0 a" C2 i& i
  41.                                 newTextView.getLocationInWindow(startLocation);9 e1 ~; n, O2 D& t
  42.                                 final ChannelItem channel = ((OtherAdapter) parent.getAdapter()).getItem(position);
      O( f1 E3 E9 f( B
  43.                                 userAdapter.setVisible(false);
    + t$ H0 v) D! [1 k
  44.                                 //添加到最后一个
    4 _1 l7 j* x: e% X, T& n+ z
  45.                                 userAdapter.addItem(channel);" q6 [# i3 K) f4 T, x
  46.                                 new Handler().postDelayed(new Runnable() {
      s6 U9 E2 x; L  ]7 W
  47.                                         public void run() {
    ; ?+ S& c9 ]& U* t" a4 N5 v
  48.                                                 try {
    ' D/ f4 Z3 U; a3 B" v* M3 {
  49.                                                         int[] endLocation = new int[2];
    8 l% q0 w* s) k9 c. V
  50.                                                         //获取终点的坐标
    6 i* w; a+ R6 I+ F! S: l
  51.                                                         userGridView.getChildAt(userGridView.getLastVisiblePosition()).getLocationInWindow(endLocation);
    / Z+ x( _2 o8 D( s+ [; z
  52.                                                         MoveAnim(moveImageView, startLocation , endLocation, channel,otherGridView);; U9 c' T0 M; X+ I  B
  53.                                                         otherAdapter.setRemove(position);( a& a# f6 d% a& w  N. M- r. J
  54.                                                 } catch (Exception localException) {: N: _. |$ q  N3 C5 l: G
  55.                                                 }+ t0 a( I/ z5 r
  56.                                         }
    " z2 P! V8 G4 e9 X  Y
  57.                                 }, 50L);- B3 c/ y% y/ g1 W$ B7 a; y/ m, J' z
  58.                         }& e( ]1 o9 S8 E
  59.                         break;; b7 N: _- V. m0 o$ Y" ^4 b! U
  60.                 default:( T% B! w5 b% y4 x( q' i& F+ p  O
  61.                         break;5 [8 o# g# \+ o" Y
  62.                 }" C, b& r3 ]) ?5 B  U
  63.         }
复制代码
移动动画:
/ C$ Z- q) J4 }8 t3 g+ E2 Q
  1. <span style="font-size:14px;">private void MoveAnim(View moveView, int[] startLocation,int[] endLocation, final ChannelItem moveChannel,
    $ X1 |; [; ^7 p8 G5 _7 V5 \
  2.                         final GridView clickGridView) {
    / R4 H. u6 j. h, x6 S* Y: \
  3.                 int[] initLocation = new int[2];0 i( z8 Z# C# y9 c+ @3 V1 n
  4.                 //获取传递过来的VIEW的坐标. G7 z9 ~2 u& \% }7 ~1 p0 [2 N
  5.                 moveView.getLocationInWindow(initLocation);4 @. v7 q0 l1 F+ h2 t# x
  6.                 //得到要移动的VIEW,并放入对应的容器中
    6 {5 n# I# X/ |5 q2 ~& l
  7.                 final ViewGroup moveViewGroup = getMoveViewGroup();
    & m' p2 \" n+ d  h. X
  8.                 final View mMoveView = getMoveView(moveViewGroup, moveView, initLocation);
    * g; S7 g( z2 s& K
  9.                 //创建移动动画  K% y, R" q: h
  10.                 TranslateAnimation moveAnimation = new TranslateAnimation(
    8 v6 k1 S' L, y0 N6 j0 z
  11.                                 startLocation[0], endLocation[0], startLocation[1],: i+ D) Q+ M! d! k( B+ }
  12.                                 endLocation[1]);$ g9 t& U* m) g! _8 T
  13.                 moveAnimation.setDuration(300L);//动画时间
    1 [2 x5 V- c$ N
  14.                 //动画配置! x6 E1 S5 a5 K% W
  15.                 AnimationSet moveAnimationSet = new AnimationSet(true);
    * U1 r6 [# E4 s- `) Z5 P4 q3 w# ?
  16.                 moveAnimationSet.setFillAfter(false);//动画效果执行完毕后,View对象不保留在终止的位置3 r$ C- a# U+ j: p2 y9 n
  17.                 moveAnimationSet.addAnimation(moveAnimation);
    & [. b6 V; B! |& J* N
  18.                 mMoveView.startAnimation(moveAnimationSet);7 @" Z1 g+ _8 E% `2 o) Z
  19.                 moveAnimationSet.setAnimationListener(new AnimationListener() {
    8 e. n" y( m- w+ P  T
  20.                         
    ( ?  M" ~4 K; J* B' I
  21.                         @Override* m  L% H8 E2 G3 \/ L; ^1 J
  22.                         public void onAnimationStart(Animation animation) {3 D2 W' r+ g7 d' g) N' t7 h
  23.                                 isMove = true;# J4 \+ J1 {" H* j4 K( @- A
  24.                         }# G, p; x0 V2 v/ z! e
  25.                         3 _6 ]4 [2 c# I7 K# @
  26.                         @Override
    * \9 l' u3 X! B6 O- D" s
  27.                         public void onAnimationRepeat(Animation animation) {" D5 \+ l2 j8 I4 `9 x# F
  28.                         }
      y6 U) H4 w1 h5 U
  29.                         & a1 N! B& _( M
  30.                         @Override
    ( _0 a" }1 K! X8 o( d+ Y
  31.                         public void onAnimationEnd(Animation animation) {/ c3 R$ m0 ^, m$ Z
  32.                                 moveViewGroup.removeView(mMoveView);5 r: a# {1 e& e/ l4 |) y
  33.                                 // instanceof 方法判断2边实例是不是一样,判断点击的是DragGrid还是OtherGridView% ^, q7 q% G2 U% A
  34.                                 if (clickGridView instanceof DragGrid) {' x6 ?6 f* f& g% M1 @# |
  35.                                         otherAdapter.setVisible(true);
    + f( f& I' ]5 e' b8 A' y/ O9 _
  36.                                         otherAdapter.notifyDataSetChanged();
    5 g+ n  J1 b! W( A" N
  37.                                         userAdapter.remove();
    ) ~' d9 x+ t8 O
  38.                                 }else{. Y. E  F6 X/ Q- N: C  H1 c
  39.                                         userAdapter.setVisible(true);
    & R; ?# q( Z& k; f. A
  40.                                         userAdapter.notifyDataSetChanged();
    . t2 R. ~! ~7 A" v
  41.                                         otherAdapter.remove();
    / A8 [8 y- n' d
  42.                                 }6 N" e4 }; Y( _0 Q
  43.                                 isMove = false;6 \  n8 ?) i- z; r0 l
  44.                         }2 K, ~" t+ l9 E+ B5 Q' `
  45.                 });
    : C- b+ A" s% t+ D- S' S+ }( F# B1 O
  46.         }</span>
复制代码

7 A9 ]  g7 H$ p- U/ d) m( A: R7 M. p; ], P4 g

3 ^0 y$ D; i: O6 ?7 W3 `
 楼主| 发表于 2014-8-8 11:34 | 显示全部楼层
可拖拽的DragGrid代码:0 ^" b) w6 R9 Q( w0 j
  1. public class DragGrid extends GridView {7 ^2 o4 b7 e) ?& Y) ?0 z9 [- ]
  2.         /** 点击时候的X位置 */
    1 k6 c% r& S! I1 z( A9 P% _
  3.         public int downX;( x" o; A1 s+ F9 [
  4.         /** 点击时候的Y位置 */6 r$ [- m: q# E4 k! a9 s
  5.         public int downY;9 ^( R. Q! e/ S# q
  6.         /** 点击时候对应整个界面的X位置 */
    * }3 ]$ n2 F4 E8 ~8 w
  7.         public int windowX;
    6 |8 A0 \) J' q: _3 q
  8.         /** 点击时候对应整个界面的Y位置 */
    # o% ~+ U- W  U
  9.         public int windowY;2 I1 {( n* }! \2 H( W: h
  10.         /** 屏幕上的X */' C5 b; W+ H. P6 S+ z; I# @1 q
  11.         private int win_view_x;
    % B4 X) u$ Y/ n5 k
  12.         /** 屏幕上的Y */' {- y9 X/ x; j1 o1 r0 m
  13.         private int win_view_y;4 P; [, L" [( p
  14.         /** 拖动的里x的距离 */
      }+ y* v4 ~9 E6 s
  15.         int dragOffsetX;1 E" t% V# G. L
  16.         /** 拖动的里Y的距离 */
    2 T/ @! s1 @" w8 `! A
  17.         int dragOffsetY;4 S$ F2 r: E! q7 ^
  18.         /** 长按时候对应postion */( `. i* ~0 H- J, Q" X
  19.         public int dragPosition;
    " f3 f. u; ~( Y. @
  20.         /** Up后对应的ITEM的Position */6 G8 B6 L/ @+ N+ z7 d
  21.         private int dropPosition;/ t/ d- J) P! r) u
  22.         /** 开始拖动的ITEM的Position *// n& ?6 D6 U# r' A$ |
  23.         private int startPosition;) b" z' T+ y( L" @% |( t6 `; B
  24.         /** item高 */
    , M" G& d7 C- F2 R$ q, ~* g
  25.         private int itemHeight;; ^9 J6 E3 T8 b* C
  26.         /** item宽 */
    8 z7 `' C* c2 }% [+ \( a8 n, O
  27.         private int itemWidth;
    6 N9 q2 v4 K, p9 v& j& }' ]6 c# B
  28.         /** 拖动的时候对应ITEM的VIEW */8 m' h( I- @, {* _7 n) x" Z4 J
  29.         private View dragImageView = null;
    . l% V% a3 ^7 {$ P  j, }
  30.         /** 长按的时候ITEM的VIEW */" b/ M% p7 Q1 ?! x
  31.         private ViewGroup dragItemView = null;
    . L$ S8 \% X' ]# u" f* E
  32.         /** WindowManager管理器 */
    ! k; H: u* Z/ e. Y
  33.         private WindowManager windowManager = null;& w; I5 I, o" K
  34.         /** */$ `+ o: l( N. ]$ D7 j9 X$ b# N& e
  35.         private WindowManager.LayoutParams windowParams = null;
    7 b% w- I; e" f0 q9 R/ Q
  36.         /** item总量 */
    5 l$ ^- B* M, J
  37.         private int itemTotalCount;
    ' d9 Z& b4 M1 a  ?
  38.         /** 一行的ITEM数量 */3 Z) Q5 Q9 C2 b/ Y4 J" C
  39.         private int nColumns = 4;
    , E' P! s& J% ~" r7 b  @
  40.         /** 行数 */
    : C6 q6 i1 s! _5 l- [- N' W5 d
  41.         private int nRows;/ G/ u' Z1 G' h7 C, a8 l: G( a
  42.         /** 剩余部分 */
    6 [4 E" R) V& H# P
  43.         private int Remainder;7 Y, j' }2 h  O) {3 E- m
  44.         /** 是否在移动 */: b1 \. d& u; C3 z( R, f
  45.         private boolean isMoving = false;) @  Y2 o0 G& T' j0 ?' W
  46.         /** */
    . F" ~* W  E, h: x. i4 D  H
  47.         private int holdPosition;
    : S5 m8 n' _7 @$ F  H4 e+ G
  48.         /** 拖动的时候放大的倍数 */4 c3 N2 a7 _3 p9 J# ]1 D$ Z
  49.         private double dragScale = 1.2D;
    ; r1 ]3 z1 |) v) j
  50.         /** 震动器 */! G; x5 L  s) ]- ?" ]6 e: a
  51.         private Vibrator mVibrator;
    9 _' Y9 z' V0 ^! ?& H, r
  52.         /** 每个ITEM之间的水平间距 */
    ; K. n3 a9 ^6 Y; Y5 F9 {7 e
  53.         private int mHorizontalSpacing = 15;3 Y5 M, f$ o  t' b' e" g: K1 N
  54.         /** 每个ITEM之间的竖直间距 */
    / v7 ?6 Z. T. P' e
  55.         private int mVerticalSpacing = 15;: W  {0 u+ O6 s" e5 i2 a1 h2 s) z
  56.         /* 移动时候最后个动画的ID */
    1 A9 {; g2 o$ D: q( [
  57.         private String LastAnimationID;
    % \7 j" F* T" A0 Y% ?3 L

  58. : H$ y) o7 \* C; y; r. R# t9 ~
  59.         public DragGrid(Context context) {* W5 Y! }& J" G" o5 }
  60.                 super(context);2 C! o/ c5 z" R, z( P
  61.                 init(context);
    5 G5 F5 U( C% [) q) w# C3 @1 L
  62.         }
    0 J9 F- T$ |& b# @+ [9 U
  63. ) C8 u2 D9 W" M1 J
  64.         public DragGrid(Context context, AttributeSet attrs, int defStyle) {
    ! }! r( S2 m* l' U  [
  65.                 super(context, attrs, defStyle);
    - j+ O& c8 @: h0 W+ x
  66.                 init(context);1 x' K; W, X$ f4 T, _4 {, X
  67.         }
    $ j) _0 I- Z& K4 }

  68. * I/ J$ N$ u1 Y5 |4 ?5 `, H* V
  69.         public DragGrid(Context context, AttributeSet attrs) {6 l9 y/ h: W0 t# m4 `( h
  70.                 super(context, attrs);; V8 N/ L2 c% H: i
  71.                 init(context);
    ; B/ S9 F/ q3 u) {; h
  72.         }) d: b% A/ l) b& W
  73. , O3 f7 Z) u- s7 W' s. @" n- [; _
  74.         public void init(Context context) {
    4 j; R/ G+ X) S5 z3 x0 _
  75.                 mVibrator = (Vibrator) context/ h  ?, d0 H& ^; ^! I* }0 V
  76.                                 .getSystemService(Context.VIBRATOR_SERVICE);
    9 c1 q3 E- K+ z5 J6 Y
  77.                 // 将布局文件中设置的间距dip转为px
    " b+ t& [( Z, f- K: c7 W
  78.                 mHorizontalSpacing = DataTools.dip2px(context, mHorizontalSpacing);
    ) N  l9 _1 P. G  f
  79.         }! {$ @8 ^3 l4 K6 @9 v( q9 w1 z
  80. / X& f# E& s; F6 L! D' F' U
  81.         @Override
    " k; i- }. l% h1 P2 z3 B. [
  82.         public boolean onInterceptTouchEvent(MotionEvent ev) {' z/ k+ M/ G! l+ j1 q
  83.                 // TODO Auto-generated method stub' ]/ o1 o9 |6 Y
  84.                 if (ev.getAction() == MotionEvent.ACTION_DOWN) {1 W7 K5 x/ [1 L+ o
  85.                         downX = (int) ev.getX();
    " \6 p3 d3 z7 x" n8 m" @) {- [
  86.                         downY = (int) ev.getY();; F* f' U8 I" |: g9 D
  87.                         windowX = (int) ev.getX();& Q7 w5 Y4 t/ X' ?! B' Y
  88.                         windowY = (int) ev.getY();! |3 v6 ^3 B9 E+ a
  89.                         setOnItemClickListener(ev);1 l5 r, u1 E: v- t
  90.                 }
    $ ?; R- `( o" N4 |# C* ]
  91.                 return super.onInterceptTouchEvent(ev);
    3 i# g( Z/ z9 ^& K' Y) N
  92.         }
    9 @* P4 G( p1 g; f

  93. # J3 c7 A  i) B
  94.         @Override
    1 C- _: f- A" s
  95.         public boolean onTouchEvent(MotionEvent ev) {
    7 w% v  C) M: Q; Z
  96.                 // TODO Auto-generated method stub7 r( @7 T, Q. \) ~
  97.                 boolean bool = true;
    # l) y. h3 m+ G- z9 n! x- j
  98.                 if (dragImageView != null
    + d& ^( r8 f6 q! d. N
  99.                                 && dragPosition != AdapterView.INVALID_POSITION) {0 @9 [2 M5 m3 H+ h2 f% t
  100.                         // 移动时候的对应x,y位置) a0 g$ X) Q: T* d
  101.                         bool = super.onTouchEvent(ev);
    . L7 J7 Y8 n3 a
  102.                         int x = (int) ev.getX();$ ?8 _$ V7 N# W; }) h
  103.                         int y = (int) ev.getY();
    0 h# {( e, v6 {2 y: c
  104.                         switch (ev.getAction()) {
    ) M$ Q3 T8 m3 x& O4 M
  105.                         case MotionEvent.ACTION_DOWN:
    ' _6 D: D& J$ z
  106.                                 downX = (int) ev.getX();; _4 [% O0 w- y" w8 N) B" w" y
  107.                                 windowX = (int) ev.getX();
    6 h- i5 z$ ]% j. b( _" \
  108.                                 downY = (int) ev.getY();9 s: h) J# e4 m% s2 D
  109.                                 windowY = (int) ev.getY();
    ! y$ s' B" V' F6 M$ K
  110.                                 break;
    / H% u- F5 d& Y+ |
  111.                         case MotionEvent.ACTION_MOVE:* j. Q: @  d* d0 j; s9 O6 P
  112.                                 onDrag(x, y, (int) ev.getRawX(), (int) ev.getRawY());
    + ?' j- {* `) I
  113.                                 if (!isMoving) {
    4 r% _1 W2 l6 Y/ t- `0 v6 n
  114.                                         OnMove(x, y);3 k- j* n) n, I6 m  f& `
  115.                                 }" }+ |: q/ U$ ]; H) }2 ^2 ]( _1 E
  116.                                 if (pointToPosition(x, y) != AdapterView.INVALID_POSITION) {
    8 r' T# Z  F+ x5 [$ ~+ \
  117.                                         break;
    9 N% Z6 u) \$ c  P
  118.                                 }
    3 D0 k/ ?" G; m- {
  119.                                 break;& O) V/ @/ m. E3 r" S+ [2 L
  120.                         case MotionEvent.ACTION_UP:
    5 B7 ^$ r4 H% u4 u
  121.                                 stopDrag();
    $ }, R. U( o/ U- i: K, s
  122.                                 onDrop(x, y);
    4 K" y+ x/ ]9 M
  123.                                 requestDisallowInterceptTouchEvent(false);# z" b- M! f) y; n. H0 G7 W
  124.                                 break;5 Z* _" ~6 m5 `0 o, q
  125. , Q! ?  X6 k$ x0 U" _' R
  126.                         default:
    + ^: P' I, a! d* H5 T8 I
  127.                                 break;
    1 d) M6 A! K; V; p8 V3 ?  }* r
  128.                         }2 v4 A% C1 c% U7 V( v
  129.                 }0 o. ^& @: S. e
  130.                 return super.onTouchEvent(ev);
    + F0 A, l3 p6 d8 E  N8 v) w
  131.         }
    5 j( J- N4 Y: a$ G# K

  132. % K& b9 k- b, A& a! k/ h2 ~7 }
  133.         /** 在拖动的情况 */
    ( s: f. B" X- k9 ~! \" l
  134.         private void onDrag(int x, int y, int rawx, int rawy) {
    - Z! u  e# k7 h( J8 W. @0 M
  135.                 if (dragImageView != null) {
    1 v6 |) s+ p  ^) p  s
  136.                         windowParams.alpha = 0.6f;
    6 x) d+ Q" g; V/ w: F2 O' g$ t6 |
  137.                         windowParams.x = rawx - win_view_x;& O  D0 m% K' [6 |- P& l3 ~3 n' J
  138.                         windowParams.y = rawy - win_view_y;
    / B: _" h( I+ g) P) A
  139.                         windowManager.updateViewLayout(dragImageView, windowParams);
    2 ^( h! j9 J; q' _
  140.                 }
    1 m- [+ [1 r9 j+ Y7 j" x9 q( K
  141.         }6 [; U! z  l: M, q+ u$ u8 |

  142. * S& t( [  F  @$ H; f: |/ C
  143.         /** 在松手下放的情况 */
    6 I3 |! L: |, c* r
  144.         private void onDrop(int x, int y) {
    9 u# K% H  g! R) Z7 Q
  145.                 // 根据拖动到的x,y坐标获取拖动位置下方的ITEM对应的POSTION  t) D8 ~3 D. s  ?' _! [) d: f8 p
  146.                 int tempPostion = pointToPosition(x, y);
    4 A7 i- g% k0 E; s1 X  o) X9 g
  147.                 dropPosition = tempPostion;
    3 |2 l/ t  Q' k, F* R  Z
  148.                 DragAdapter mDragAdapter = (DragAdapter) getAdapter();! d( P& g8 y% |3 G; X/ N) e, H
  149.                 // 显示刚拖动的ITEM
    : Y4 w; d% \( K) @2 j
  150.                 mDragAdapter.setShowDropItem(true);
    ' z$ S: A: E) g/ G8 T0 @: m
  151.                 // 刷新适配器,让对应的ITEM显示
    * W5 u% r% P/ X6 G( I/ W! S
  152.                 mDragAdapter.notifyDataSetChanged();
    1 N4 `( K; Q$ \8 n% f/ @
  153.         }8 Q! Q9 O0 w8 b% o' u8 ^( y  r

  154. 7 m9 \0 {: X2 r
  155.         /**
    1 e" `0 ~& F' `4 U6 k
  156.          * 长按点击监听) b! u) C! l/ G4 n$ Q, P  u  S
  157.          * @param ev
    $ Q* X# |7 g/ G. U4 Y  e' @1 ^
  158.          */
    / \) f- O$ d4 _( k+ C. @
  159.         public void setOnItemClickListener(final MotionEvent ev) {9 U" W  s: h: b7 L# q! x
  160.                 setOnItemLongClickListener(new OnItemLongClickListener() {
    8 c6 }2 I; h! ?9 m; G

  161. : M* k  N# `$ S- j% `' g1 L
  162.                         @Override
    ' q" x4 D+ i2 v1 o
  163.                         public boolean onItemLongClick(AdapterView<?> parent, View view,
    ! v8 l$ {* m$ y$ Z4 o
  164.                                         int position, long id) {# B( H3 {; E7 z5 y9 l* j
  165.                                 int x = (int) ev.getX();// 长安事件的X位置
    3 P6 `& e, t- N- E
  166.                                 int y = (int) ev.getY();// 长安事件的y位置
    6 c8 y0 d1 g! y9 @9 k5 {
  167.                                 startPosition = position;// 第一次点击的postion
    & {& e& H7 t6 R% Q7 ]8 m; x
  168.                                 dragPosition = position;
    9 p' L$ ^4 B+ q4 l
  169.                                 if (startPosition <= 1) {7 t1 ~% x" Q# i! T* ?6 r
  170.                                         return false;4 i8 M' v8 F; f; V
  171.                                 }) g* j& |7 i5 l& ]1 w! J9 g
  172.                                 ViewGroup dragViewGroup = (ViewGroup) getChildAt(dragPosition
    ) c. _& A; @7 s# G) s+ y' b
  173.                                                 - getFirstVisiblePosition());
    % D- I% ^9 c- U+ o* Y
  174.                                 TextView dragTextView = (TextView) dragViewGroup4 @. u+ N  d( Y
  175.                                                 .findViewById(R.id.text_item);$ u) S6 `' ?  S5 ~, U# ^
  176.                                 dragTextView.setSelected(true);
    ! d; e$ o# I% R" h& N2 T
  177.                                 dragTextView.setEnabled(false);" L6 Z0 U5 D4 `  S0 C: _
  178.                                 itemHeight = dragViewGroup.getHeight();% N% r+ [1 }8 {7 l# R
  179.                                 itemWidth = dragViewGroup.getWidth();
    2 H) X$ }. P! o3 v
  180.                                 itemTotalCount = DragGrid.this.getCount();! K! W5 b) D# S) U
  181.                                 int row = itemTotalCount / nColumns;// 算出行数
    , g; B$ f* A7 c, @
  182.                                 Remainder = (itemTotalCount % nColumns);// 算出最后一行多余的数量* t; i7 i# G( e
  183.                                 if (Remainder != 0) {7 d( f0 H, G' Y/ k5 i6 ^
  184.                                         nRows = row + 1;3 C( _. @  i* x8 P5 }# K1 ?
  185.                                 } else {& D( `9 B: m4 K$ ]& L
  186.                                         nRows = row;
      y; F. ~# C( H" d1 G
  187.                                 }
    : A) a/ d7 C% T* a) M
  188.                                 // 如果特殊的这个不等于拖动的那个,并且不等于-1
    + S/ b9 u) Q% f6 S: P; i
  189.                                 if (dragPosition != AdapterView.INVALID_POSITION) {; r* X, n/ o2 u
  190.                                         // 释放的资源使用的绘图缓存。如果你调用buildDrawingCache()手动没有调用setDrawingCacheEnabled(真正的),你应该清理缓存使用这种方法。
    + \2 p8 [( S2 P! B( Y
  191.                                         win_view_x = windowX - dragViewGroup.getLeft();// VIEW相对自己的X,半斤, m" a7 p! g$ j9 f; N" j
  192.                                         win_view_y = windowY - dragViewGroup.getTop();// VIEW相对自己的y,半斤
    5 }* ^" O2 G) ]' l
  193.                                         dragOffsetX = (int) (ev.getRawX() - x);// 手指在屏幕的上X位置-手指在控件中的位置就是距离最左边的距离
    % }- a4 _/ _: A' n* C8 _
  194.                                         dragOffsetY = (int) (ev.getRawY() - y);// 手指在屏幕的上y位置-手指在控件中的位置就是距离最上边的距离
      m" ~' B! @: J$ H( O4 K! k6 n% N4 X
  195.                                         dragItemView = dragViewGroup;
    # H" v0 R& j: C
  196.                                         dragViewGroup.destroyDrawingCache();
    / l% r0 e% F+ t
  197.                                         dragViewGroup.setDrawingCacheEnabled(true);
    0 m, ~# v/ n9 L- J
  198.                                         Bitmap dragBitmap = Bitmap.createBitmap(dragViewGroup+ G5 N) p# D- W8 J. N: S
  199.                                                         .getDrawingCache());
    : A7 q9 H; c  I: c1 ^" I
  200.                                         mVibrator.vibrate(50);// 设置震动时间
    7 {. U5 N6 y' {5 D7 ?( [/ Q0 ?, \
  201.                                         startDrag(dragBitmap, (int) ev.getRawX(),
    6 V  p' o( q, c
  202.                                                         (int) ev.getRawY());' Q. O1 L' d% Z' q
  203.                                         hideDropItem();
    # q  r( |& B! E! m# L. }
  204.                                         dragViewGroup.setVisibility(View.INVISIBLE);
    + _  _5 f# p  A. y% n  Z) I
  205.                                         isMoving = false;
    ; p6 z) J6 _  Y  [. F5 \
  206.                                         requestDisallowInterceptTouchEvent(true);
    4 T/ ?  u# j, R) Y
  207.                                         return true;: k1 G8 y# {# b+ n0 u  Y! @
  208.                                 }
    5 p$ f) t9 \3 }/ t1 e7 V% [8 u0 k1 k% ^
  209.                                 return false;
    1 |# I: X6 ~  w* R" n" t* H
  210.                         }
    * N8 m* M8 Q0 r
  211.                 });! S' o0 j2 L2 w& K7 l# @/ Z
  212.         }% Q+ I3 N1 d, {2 ]1 I

  213. $ C- |6 ?4 P$ h7 [. T  Z
  214.         public void startDrag(Bitmap dragBitmap, int x, int y) {
    ' V6 Y% n% G8 a+ {
  215.                 stopDrag();
    & Q4 z* k" {# j" y% J
  216.                 windowParams = new WindowManager.LayoutParams();// 获取WINDOW界面的. _8 y2 x0 _. A$ }* x4 x* W7 S
  217.                 // Gravity.TOP|Gravity.LEFT;这个必须加
    ) ]  A* `. u  y" y+ ~6 L, {4 i
  218.                 windowParams.gravity = Gravity.TOP | Gravity.LEFT;
    $ R' K# V& q$ F" k; e" A0 }
  219.                 // 得到preview左上角相对于屏幕的坐标7 I# Q0 @% w7 N+ q5 f, S
  220.                 windowParams.x = x - win_view_x;. y3 K' D9 N) e1 x; I' Z8 _6 D, S2 ?
  221.                 windowParams.y = y - win_view_y;2 g8 L& i* B2 j
  222.                 // 设置拖拽item的宽和高
    4 L8 O5 c7 q( R. k) k3 j& \
  223.                 windowParams.width = (int) (dragScale * dragBitmap.getWidth());// 放大dragScale倍,可以设置拖动后的倍数: Z$ Q4 _; ^# [$ B
  224.                 windowParams.height = (int) (dragScale * dragBitmap.getHeight());// 放大dragScale倍,可以设置拖动后的倍数
    3 m4 I  n8 G) }9 W# ?
  225.                 this.windowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
    % ^* c+ {6 O4 k2 O' i) W* X
  226.                                 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
    ! l; I+ f' D% ~% {& ?# M
  227.                                 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON5 r1 F% w$ m' ]; g
  228.                                 | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;0 ^9 y6 Q' W2 H+ {  e) q+ S+ Q9 s
  229.                 this.windowParams.format = PixelFormat.TRANSLUCENT;; `3 T6 o( ]5 a0 ]! _4 i/ R. |
  230.                 this.windowParams.windowAnimations = 0;
    ; N) `+ \. j$ E
  231.                 ImageView iv = new ImageView(getContext());0 @4 n& q1 J1 ~
  232.                 iv.setImageBitmap(dragBitmap);) E/ C! B! t& ]8 R. M- J! h" I
  233.                 windowManager = (WindowManager) getContext().getSystemService(
    + O& |, W5 X) p, @6 b4 U6 K0 x
  234.                                 Context.WINDOW_SERVICE);// "window"$ M/ e: `2 X$ g
  235.                 windowManager.addView(iv, windowParams);6 u3 ^3 A+ }  P, {; M6 k
  236.                 dragImageView = iv;
    % ?; Q. E  C% w5 M- b5 }7 s7 Q' F) X, u
  237.         }" Y. S; ]# }3 X; Y: l4 G3 U
  238. * [3 P0 m3 a0 L
  239.         /** 停止拖动 ,释放并初始化 */4 n: d: _( m$ T1 o
  240.         private void stopDrag() {
    ( Q! N7 j& `$ X0 V) ^
  241.                 if (dragImageView != null) {
    , V' Z8 {! J5 @" B% }9 u
  242.                         windowManager.removeView(dragImageView);7 e0 t* x, J5 r0 C
  243.                         dragImageView = null;
    3 b- x( w5 W$ j- h4 D2 a  f, P7 i" R
  244.                 }
    6 _5 n4 s0 T' u8 x
  245.         }
    " o: v% _" x% I' f9 d; ?

  246. " H* b9 o6 ], I% j6 D
  247.         /** 在ScrollView内,所以要进行计算高度 */
    7 E/ P/ V. D" R
  248.         @Override
    / w% l6 m7 a% U9 l/ i
  249.         public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {7 J  }$ a! P& m" X
  250.                 int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
    ! W8 x3 |8 E% L; U) f& k
  251.                                 MeasureSpec.AT_MOST);
    & r' |3 Q7 a  j9 c
  252.                 super.onMeasure(widthMeasureSpec, expandSpec);
    : @, D- |# v; Z( F3 T+ l2 R
  253.         }2 H$ `- [. R, [

  254. 7 q2 H5 A8 n5 t" V9 U, b- x* J4 a$ V
  255.         /** 隐藏 放下 的ITEM */6 @6 f6 N( E  X! b0 p
  256.         private void hideDropItem() {7 m' s! A& {2 T+ I! X
  257.                 ((DragAdapter) getAdapter()).setShowDropItem(false);
    ( x$ g) G: N# V" E: h
  258.         }6 ^  ^" J; D( D, @! u

  259. 2 o' |4 V$ }+ ?& W9 l: p- Z
  260.         /** 获取移动动画 */9 k1 @' V. M+ l" ~8 j) p
  261.         public Animation getMoveAnimation(float toXValue, float toYValue) {; d  X( a1 A) ~) J1 Q( I
  262.                 TranslateAnimation mTranslateAnimation = new TranslateAnimation(& X" I4 k( [9 m1 x5 I& K
  263.                                 Animation.RELATIVE_TO_SELF, 0.0F, Animation.RELATIVE_TO_SELF,8 C  Z6 D8 f1 ^9 m
  264.                                 toXValue, Animation.RELATIVE_TO_SELF, 0.0F,4 t6 E" U9 ?( r8 N5 D4 x- K
  265.                                 Animation.RELATIVE_TO_SELF, toYValue);// 当前位置移动到指定位置
    % A& D1 G4 U/ g! v9 M' Q- I) b( O8 o
  266.                 mTranslateAnimation.setFillAfter(true);// 设置一个动画效果执行完毕后,View对象保留在终止的位置。
    ( C" V1 v; c( c, w" i4 w: d% K7 P
  267.                 mTranslateAnimation.setDuration(300L);  h2 P4 M1 J5 S# I$ g
  268.                 return mTranslateAnimation;
    6 _$ W, C3 T6 ]3 N
  269.         }
    - k- B$ D$ Z5 [/ h: w. a

  270. ' g8 z1 N6 q$ P% i3 e% Z
  271.         /** 移动的时候触发 */
    / C0 q4 c& p  H% ]- U+ k/ C8 L/ \
  272.         public void OnMove(int x, int y) {
    + Z5 K9 U# l' |5 c" O/ V& q
  273.                 // 拖动的VIEW下方的POSTION2 D6 H5 u# w! m
  274.                 int dPosition = pointToPosition(x, y);, j  @- k3 I0 |
  275.                 // 判断下方的POSTION是否是最开始2个不能拖动的3 t, I: i8 {' Z2 e/ [4 l
  276.                 if (dPosition > 1) {
    9 L6 }+ N2 W& ^7 ^7 V
  277.                         if ((dPosition == -1) || (dPosition == dragPosition)) {; H* ?$ B: }1 h* Z8 g5 x) S
  278.                                 return;" x: ~1 g( V' g" s
  279.                         }1 M6 N' q2 l: L6 a4 U" W
  280.                         dropPosition = dPosition;' S# B0 V7 H# R9 j/ u
  281.                         if (dragPosition != startPosition) {
    ' I) h- w9 V" J/ p$ K+ O
  282.                                 dragPosition = startPosition;
    ) {& R# x. b" K9 r/ N
  283.                         }
    5 o1 i! Y9 H3 R4 ^5 q6 ~
  284.                         int movecount;3 o; Y6 S! X4 E4 {( S- Z
  285.                         // 拖动的=开始拖的,并且 拖动的 不等于放下的
    7 d& n2 y5 F  j- W$ w0 R
  286.                         if ((dragPosition == startPosition), K7 c4 p$ O" |: D* X
  287.                                         || (dragPosition != dropPosition)) {$ F/ t4 @6 {$ \+ k/ I2 a
  288.                                 // 移需要移动的动ITEM数量. x$ `' }! p) j! S* H0 Y
  289.                                 movecount = dropPosition - dragPosition;
    ' q" j5 ~2 M! ]' k- b
  290.                         } else {
    0 f5 V1 E) u8 C5 A
  291.                                 // 移需要移动的动ITEM数量为0
    . ~) B2 ?( @6 c* U$ ]
  292.                                 movecount = 0;6 Y2 W. d% n2 }3 b
  293.                         }1 I2 d, s/ Q$ a; T: ^
  294.                         if (movecount == 0) {
    0 y+ e& h7 C! K6 j
  295.                                 return;/ V& z9 q% P- U
  296.                         }
    - S7 P( q7 x9 P/ x& j
  297. 7 f; S( f  g0 H  u  @- a# t
  298.                         int movecount_abs = Math.abs(movecount);
    1 `/ S6 M+ q, w5 A( d
  299. + U  M2 A% V* G* r" T
  300.                         if (dPosition != dragPosition) {9 l2 u8 G/ o4 @, _2 k
  301.                                 // dragGroup设置为不可见8 F; c& }2 I& @! ^
  302.                                 ViewGroup dragGroup = (ViewGroup) getChildAt(dragPosition);- s7 ]  c# ?# H( E/ C) d* }
  303.                                 dragGroup.setVisibility(View.INVISIBLE);2 T, c" G. T4 N
  304.                                 float to_x = 1;// 当前下方positon6 Y; m' B5 \) L* Z9 v7 C, f
  305.                                 float to_y;// 当前下方右边positon
      L; Y# b2 C7 O$ ~' Z
  306.                                 // x_vlaue移动的距离百分比(相对于自己长度的百分比)* Q+ s$ M- k: Y% a+ X
  307.                                 float x_vlaue = ((float) mHorizontalSpacing / (float) itemWidth) + 1.0f;
    5 q, ]+ Q  Y4 c$ d2 ^. k$ O5 Q1 d
  308.                                 // y_vlaue移动的距离百分比(相对于自己宽度的百分比)! \% ]: ]! A  R, u9 T% p' A# w9 o
  309.                                 float y_vlaue = ((float) mVerticalSpacing / (float) itemHeight) + 1.0f;; j, ]& \3 u$ x8 P/ ~" ~3 K/ V
  310.                                 Log.d("x_vlaue", "x_vlaue = " + x_vlaue);+ N! w( P% k3 D/ x' l
  311.                                 for (int i = 0; i < movecount_abs; i++) {' G( N% s% L3 p- y# X' X
  312.                                         to_x = x_vlaue;" E7 L/ S# v/ J" i" B
  313.                                         to_y = y_vlaue;4 }) [( @) U( d, i4 y' T
  314.                                         // 像左
    # I( v$ \" y4 Z6 @! B3 M7 s% x
  315.                                         if (movecount > 0) {
    0 X1 S( @  R7 D) }7 {
  316.                                                 // 判断是不是同一行的: Y' {, A+ m' T4 e( L' M+ a: x+ d
  317.                                                 holdPosition = dragPosition + i + 1;
    " y/ Z! r3 V9 V; P
  318.                                                 if (dragPosition / nColumns == holdPosition / nColumns) {  B, W( V4 D; u% G
  319.                                                         to_x = -x_vlaue;
    2 K4 j7 i# g. d+ P; ]* m( f
  320.                                                         to_y = 0;7 @- ?7 ?+ l. @5 c# p. j4 L
  321.                                                 } else if (holdPosition % 4 == 0) {
    + u! R" p, p' f8 d9 d8 I! R
  322.                                                         to_x = 3 * x_vlaue;
    0 i7 m1 c1 R" A/ V4 {8 O$ l! y
  323.                                                         to_y = -y_vlaue;
    1 l6 J7 x) P( [
  324.                                                 } else {
    % I! x3 V8 W: W& _- b8 z
  325.                                                         to_x = -x_vlaue;: {) a# M4 ]. B  P
  326.                                                         to_y = 0;
    - d0 g/ J, _' }/ F( A+ i
  327.                                                 }( C, [* T. T$ o& s' r8 Q
  328.                                         } else {
    2 I+ J3 ]- F8 y2 n& t. c# a
  329.                                                 // 向右,下移到上,右移到左
    ' V( a: X+ q0 h& S) ^
  330.                                                 holdPosition = dragPosition - i - 1;
    ( z3 m$ Z( S; ]
  331.                                                 if (dragPosition / nColumns == holdPosition / nColumns) {
    - K$ Y) C" L3 X: [1 j* G  e
  332.                                                         to_x = x_vlaue;. W0 j! B; n! j' a8 ]
  333.                                                         to_y = 0;) _1 D/ h+ R5 |9 F. x6 @: I
  334.                                                 } else if ((holdPosition + 1) % 4 == 0) {* u* h/ C2 r1 Y" c+ c8 |
  335.                                                         to_x = -3 * x_vlaue;
    , ~0 H9 _  X7 [
  336.                                                         to_y = y_vlaue;
    ) q, r! O2 p5 I* t
  337.                                                 } else {
    6 x, f" G! |: Y1 s5 N# q
  338.                                                         to_x = x_vlaue;
    ; f; _% `& z; K1 W' Z- R" e
  339.                                                         to_y = 0;( H  D' ?, M8 z
  340.                                                 }
    ) R  ^) g; d$ k! S3 W* @- {
  341.                                         }
    5 ?2 B. j6 Z8 G( [1 W8 `
  342.                                         ViewGroup moveViewGroup = (ViewGroup) getChildAt(holdPosition);
    2 r2 }8 C0 g2 ?; T+ Y
  343.                                         Animation moveAnimation = getMoveAnimation(to_x, to_y);' h; ]3 V6 ~1 p" f/ t6 y
  344.                                         moveViewGroup.startAnimation(moveAnimation);6 C- ]" J0 v; D3 }; f
  345.                                         // 如果是最后一个移动的,那么设置他的最后个动画ID为LastAnimationID$ N* }6 w& u' K: c  z( K& i
  346.                                         if (holdPosition == dropPosition) {$ i4 C( V; g/ B1 `) i1 }3 ?
  347.                                                 LastAnimationID = moveAnimation.toString();
    ' [/ n; Z! v, [* G! V$ h
  348.                                         }
    1 M- d3 t. w- B
  349.                                         moveAnimation.setAnimationListener(new AnimationListener() {
    . `% v7 J  a7 K4 E# S1 c

  350. : ?+ b2 y- p7 E1 Q( N4 h) a9 M3 p
  351.                                                 @Override
    ! x; r, O0 Q" p
  352.                                                 public void onAnimationStart(Animation animation) {. X7 H. ^  V; _8 Y
  353.                                                         // TODO Auto-generated method stub) o: q0 \( B$ C2 \) V# {
  354.                                                         isMoving = true;
    % }% ?1 u" @/ F8 G
  355.                                                 }
    . G6 {( x! l5 ^$ ~5 Q7 [

  356. + t  B- D  d, @# c/ V" W- W
  357.                                                 @Override9 R7 ^5 z6 q$ ?! ^5 M2 B' h+ W# q
  358.                                                 public void onAnimationRepeat(Animation animation) {: R7 x, i: K! X. B  I
  359.                                                         // TODO Auto-generated method stub
    0 n2 b; @$ S9 }: x7 b

  360. 4 b' |; l9 q/ p0 A5 q
  361.                                                 }- q0 q8 K$ \0 t
  362. ) E: J5 e9 Q) i9 c
  363.                                                 @Override5 R4 F. u( V& j, W9 s, D
  364.                                                 public void onAnimationEnd(Animation animation) {
      j9 j: L: n2 T9 [( ?4 W, z
  365.                                                         // TODO Auto-generated method stub
    ' J( w  F6 n* T
  366.                                                         // 如果为最后个动画结束,那执行下面的方法
    8 f* M- w; ^; K4 S% e( }
  367.                                                         if (animation.toString().equalsIgnoreCase(
    ! u# B9 D# _( y- ~. q
  368.                                                                         LastAnimationID)) {7 U2 f( u) W2 S0 \6 K4 A* h
  369.                                                                 DragAdapter mDragAdapter = (DragAdapter) getAdapter();5 W0 N) J- ~+ @" k
  370.                                                                 mDragAdapter.exchange(startPosition,5 c( E8 A& }$ x4 V/ g+ [/ i/ V6 C
  371.                                                                                 dropPosition);2 G9 B: C6 z; s
  372.                                                                 startPosition = dropPosition;" }: a" e- g' ~$ x: W5 f
  373.                                                                 dragPosition = dropPosition;4 W* R6 x; j; \2 P- T
  374.                                                                 isMoving = false;) Z5 O+ b0 K- T9 x
  375.                                                         }  p2 d1 E0 v# s( I" j
  376.                                                 }
    " O% \! X; A0 c, j
  377.                                         });
    $ h( f& \$ ^( A6 |( m0 O9 H
  378.                                 }' n  A2 o) @! e0 ?: G1 W
  379.                         }
    ( C' b, Z% K6 y. u
  380.                 }
    $ c% y% @* _7 j( T
  381.         }2 ?4 C. Q, {% p: g9 e7 X
  382. }
复制代码
数据库SQLHelper文件+ x/ k% _) H* G  t9 V. E
  1. public class SQLHelper extends SQLiteOpenHelper {
    3 c5 J, v$ f+ p
  2.         public static final String DB_NAME = "database.db";// 数据库名称* ?; T4 }" t$ @' l" T; g$ U
  3.         public static final int VERSION = 1;
    4 O8 \9 i3 \0 W9 `
  4.         ! @! k1 x5 Y1 n4 M* d
  5.         public static final String TABLE_CHANNEL = "channel";//数据表 1 J" o: p, y2 N: ]# B/ b, o$ C! f6 F

  6. " N7 h5 @1 B# g9 Y
  7.         public static final String ID = "id";//
    ! Z1 `& A- z9 p( Z9 m$ ]+ D) K
  8.         public static final String NAME = "name";
    4 E$ D. V/ D( }! G
  9.         public static final String ORDERID = "orderId";2 v+ m0 A+ y. E
  10.         public static final String SELECTED = "selected";$ Y1 t, c0 h/ U% Q+ ]: _4 ~! T
  11.         private Context context;5 v; i8 r" i$ H* @3 m
  12.         public SQLHelper(Context context) {! L0 e3 N( T) ^- f; }
  13.                 super(context, DB_NAME, null, VERSION);3 d9 N9 k9 e. A
  14.                 this.context = context;1 C2 D, I- G" Z/ Q3 ?( ~& x
  15.         }
    * t  `3 z. [4 f; P9 D5 G
  16. 6 J: g& P! J4 L/ H
  17.         public Context getContext(){* i# {; ]% d7 I5 d
  18.                 return context;7 U2 {) Y- o7 v
  19.         }
    5 R% y" Z; d* S
  20.        
    , |1 |0 k4 N5 b. c% [; Y
  21.         @Override% N; K2 u; {6 F& I4 H) Y$ ~3 J) I
  22.         public void onCreate(SQLiteDatabase db) {
    , ~! Y0 V+ L; B$ Y! F$ T
  23.                 // TODO 创建数据库后,对数据库的操作
    9 I' `4 z6 [2 N3 O) X9 e0 a
  24.                 String sql = "create table if not exists "+TABLE_CHANNEL +) a8 l: P4 W6 q! {& F" q, y& \
  25.                                 "(_id INTEGER PRIMARY KEY AUTOINCREMENT, " +7 R' P1 z1 G! C8 |2 ]- d
  26.                                 ID + " INTEGER , " +
    ( F0 V/ [& ~2 }6 j) f4 Z
  27.                                 NAME + " TEXT , " +
    / N$ R: [2 k% `4 a
  28.                                 ORDERID + " INTEGER , " +
    + W& Y( V3 V. f6 k% o( m
  29.                                 SELECTED + " SELECTED)";
    % x* y$ m. F) Z% V8 S7 `/ ^' T* L
  30.                 db.execSQL(sql);( o" T3 D9 x! }7 f
  31.         }1 d, E! c# h8 n1 j. J7 R7 F

  32. ! d( ^7 ^; z- ~. j/ ^3 t+ x
  33.         @Override$ Q1 L1 c! N0 i7 p- ?
  34.         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {0 ]7 ~% F4 D* c% a) Q! @8 J+ L
  35.                 // TODO 更改数据库版本的操作
    4 U: R9 `; D% `( x# ]% n5 ~& ?
  36.                 onCreate(db);
    8 K* Y: m: u6 ]! K$ V2 K
  37.         }
    - R$ p4 K* m6 |/ U
  38. * m! Z5 V* i, @; e' H4 ~" h2 e0 Q
  39. }/ ]$ C) F" @2 ~: [+ [4 I& t% N
复制代码
注:本DEMO中,加入了长按震动,所以在权限里面记得加上“
# ]0 h" }7 U; a1 L- B% h5 E
  1.     <!-- 在SDCard中创建与删除文件权限 -->
    3 N6 c( ?/ i' k) t% ]
  2.     <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />  e6 W) T) N6 W  y, ?4 Q. u
  3.     <!-- 往SDCard写入数据权限 -->
      {5 l& g% y1 G  W" f0 m, X5 o! ~2 A
  4.     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />. m/ G0 t9 T+ Z2 U$ m
  5.     <!-- 震动权限 -->
    4 R  ~( m1 j4 P8 K
  6.     <uses-permission android:name="android.permission.VIBRATE"/>
复制代码
% p% V) O: y8 c; x; {8 s
六、源码下载源码DEMO下载地址如下:
9 v6 G/ {# n$ @$ d; y% B
游客,如果您要查看本帖隐藏内容请回复
! o+ j8 x+ b, E5 @4 E, |( v+ F
7 R3 E+ s/ n* A& y8 h1 H& j+ ~  R8 @
) w" _7 Y) e7 _7 O
发表于 2014-8-9 18:03 | 显示全部楼层
ttedgdfgdfg
发表于 2014-9-5 10:03 | 显示全部楼层
谢谢分享                    
发表于 2014-9-30 10:07 | 显示全部楼层
* Q$ v; v2 X3 \: n6 g
谢谢分享   
发表于 2014-10-27 21:58 | 显示全部楼层
必须支持楼主
发表于 2014-11-3 16:40 | 显示全部楼层
谢谢楼主,,分享,,下载看看
您需要登录后才可以回帖 登录 | 注册

本版积分规则

© 2001-2014Comsenz Inc.

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