本文示例所述程序为一个Android Moveview移动视图类。其主要实现主屏左右滑屏拖动功能,并适时显示拖动时候屏幕的显示情况,该代码中还包括完整的逻辑。其完整代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
|
import android.study.shift.ItemView; import android.study.shift.MainView; import android.study.shift.Moveview; import android.content.Context; import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.View.MeasureSpec; public class Moveview extends ViewGroup{ private final static int TOUCH_STATE_REST = 0 ; private final static int TOUCH_STATE_MOVING = 1 ; private final static int MOVE_TO_LEFT = 1 ; //private final static int MOVE_TO_RIGHT = 2; private final static int MOVE_TO_REST = 0 ; public final static int MAIN = 0 ; public final static int LEFT = 1 ; public final static int RIGHT = 2 ; private int touch_state = TOUCH_STATE_REST; private int move_state = MOVE_TO_REST; private int now_state = MAIN; private final float WIDTH_RATE = 0 .18f; private MainView main_show_view; private ItemView left_show_view; private int min_distance = 30 ; //此处只是初始化为30 ,其实不起作用 private int screen_w; private int screen_h; private int move_x_v; private boolean isAimationMoving = false ; private Handler mHandler = new Handler() { public void handleMessage(Message msg) { //处理消息 synchronized (Moveview. this ) { //同步 isAimationMoving = true ; int move_change = ( int ) (screen_w * WIDTH_RATE / 5 ); int left = main_show_view.getView().getLeft(); if (msg.what == 1 ) { //主屏在向右拖曳。。。 move(move_change + left); //参数为拖出来后主屏的坐标。 } if (msg.what == 11 ) { isAimationMoving = false ; moveToLeft( false ); //满足可以显示的要求开始显示,false只是一个判定条件,以区别按钮起的效果 } if (msg.what == 2 ) { //代表主屏向左在拖曳。。。 move(- 1 * move_change + left); } if (msg.what == 12 ) { isAimationMoving = false ; //moveToRight(false); } if (msg.what == 0 ) { if (now_state == LEFT) { //如果现在已经显示左边 move(- 1 * move_x_v); //那么还原成主屏 } else { move(move_x_v); } } if (msg.what == 10 ) { isAimationMoving = false ; moveToMain( false ); } } } }; public Moveview(Context context) { super (context); } public Moveview(Context context, AttributeSet attrs) { super (context, attrs); } public Moveview(Context context, AttributeSet attrs, int defStyle) { super (context, attrs, defStyle); } public void initView() { if (main_show_view == null ) { main_show_view = new MainView( this .getContext(), this ); left_show_view = new ItemView( this .getContext()); //right_show_view = new ItemView(this.getContext(), "aaa"); } this .addView(left_show_view.getView()); //this.addView(right_show_view.getView()); this .addView(main_show_view.getView()); } public void initContent() { } public void move( int start) { //本函数显示拖动的时候屏幕的显示情况。 int left = main_show_view.getView().getLeft(); //left代表主屏左边缘的位置坐标。 if (now_state == MAIN) { if (left > 0 ) { //如果屏幕的左边被移向右,则left变成正数 if (move_state != MOVE_TO_LEFT) { move_state = MOVE_TO_LEFT; } left_show_view.getView().setVisibility(View.VISIBLE); //设置左边可见 //right_show_view.getView().setVisibility(View.GONE); } //else if (left < 0) {//如果屏幕的左边被移向左,则left变成负数 //if (move_state != MOVE_TO_RIGHT) { // move_state = MOVE_TO_RIGHT; //} //right_show_view.getView().setVisibility(View.VISIBLE); //left_show_view.getView().setVisibility(View.GONE); //} else { move_state = MOVE_TO_REST; } main_show_view.getView().layout(start, 0 , start + screen_w, screen_h); //参数依次为左、上、右、下。 } else { left = ( int ) (screen_w * WIDTH_RATE); //left为左边应该留出的控件空间,或者主屏左边应该在的位置 if (now_state == RIGHT) { left = - 1 * left; //若状态是在右边空出来,则主屏的左边为负数 } left = left + start; main_show_view.getView().layout(left, 0 , left + screen_w, screen_h); } } @Override protected void onLayout( boolean arg0, int arg1, int arg2, int arg3, int arg4) { if (move_state == MOVE_TO_REST) { if (now_state == MAIN) { int w = ( int ) (screen_w * WIDTH_RATE); //留下预定的宽度,显示各个view的参数设置。 main_show_view.getView().layout( 0 , 0 , screen_w, screen_h); left_show_view.getView().layout( 0 , 0 , w, screen_h); } else if (now_state == LEFT) { moveToLeft( false ); } else { } } } protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec) { main_show_view.getView().measure(widthMeasureSpec, heightMeasureSpec); left_show_view.getView().measure(MeasureSpec.UNSPECIFIED, //unspecified为未指定的 heightMeasureSpec); left_show_view.setWidth(( int ) (screen_w * WIDTH_RATE)); //设置view宽度 super .onMeasure(widthMeasureSpec, heightMeasureSpec); //调用父类的构造函数 } private int start_x; private int start_y; private boolean isMoved; public boolean dispatchTouchEvent(MotionEvent ev) { //分发触摸消息事件 if (isAimationMoving) { return super .dispatchTouchEvent(ev); } else { int action = ev.getAction(); float x = ev.getX(); float y = ev.getY(); switch (action) { case MotionEvent.ACTION_DOWN: super .dispatchTouchEvent(ev); start_y = ( int ) y; move_x_v = 0 ; if ( this .touch_state == TOUCH_STATE_REST) { this .touch_state = TOUCH_STATE_MOVING; start_x = ( int ) x; isMoved = false ; move_state = MOVE_TO_REST; } break ; case MotionEvent.ACTION_MOVE: int last_y = ( int ) y; int last_x = ( int ) x; super .dispatchTouchEvent(ev); if (!isMoved) { if (Math.abs(last_y - start_y) > Math.abs(last_x - start_x)) { //如果Y上面移动的距离大于X上面移动的距离。 super .onTouchEvent(ev); return true ; } else { //X移动距离大于Y if (Math.abs(last_x - start_x) > 5 ) { //X移动距离大于5就被认为移动了 isMoved = true ; } } } if (isMoved) { if ( this .touch_state == TOUCH_STATE_MOVING) { if (Math.abs(last_x - start_x) > 10 ) { //如果移动的X距离大于10 int left = main_show_view.getView().getLeft(); Log.d( "msg" , "left:" + left); Log.d( "msg" , "x:" + last_x); isMoved = true ; int move_x = last_x - start_x; if (move_x > 0 && now_state == LEFT) { //方向正确的移动才算是移动的状态 isMoved = false ; break ; } if (move_x < 0 && now_state == RIGHT) { //如果现在在显示右边,那么再向右移就不反应。 isMoved = false ; break ; } if (move_x < 0 && now_state ==MAIN){ //如果现在在主屏,向右移动也是无效的 isMoved = false ; break ; } if (move_x > 234 && now_state ==MAIN){ isMoved = true ; //设置为true那么移动还是发生了,break之后还是会在ACTIONUP中起作用 break ; //break之后不会执行下面的move()语句, } if (move_x < - 234 && now_state ==LEFT){ isMoved = true ; break ; } move(move_x); //以移动的距离为参数调用move()实现移动的动态显示 } } return false ; } break ; case MotionEvent.ACTION_UP: // if ( this .touch_state == TOUCH_STATE_MOVING) { if (isMoved) { last_x = ( int ) x; if (Math.abs(last_x - start_x) > min_distance) { // if (now_state == MAIN) { if (move_state == MOVE_TO_LEFT) { this .moveToLeft( false ); } } else { this .moveToMain( false ); } } else { // if (now_state == MAIN) { this .moveToMain( false ); } if (now_state == LEFT) { this .moveToLeft( false ); } if (now_state == RIGHT) { //this.moveToRight(false); } } move_state = MOVE_TO_REST; } else { super .dispatchTouchEvent(ev); this .touch_state = TOUCH_STATE_REST; return false ; // } } super .onTouchEvent(ev); this .touch_state = TOUCH_STATE_REST; break ; } return true ; } } public boolean getIsMoved() { return isMoved; } public void moveToLeft( boolean b) { if (!b) { int move_x = ( int ) (screen_w * WIDTH_RATE); left_show_view.getView().layout( 0 , 0 , screen_w, screen_h); //right_show_view.getView().layout(move_x, 0, move_x * 2, screen_h); main_show_view.getView().layout(move_x, 0 , move_x + screen_w, screen_h); now_state = LEFT; //为什么现在又把now_state赋值为left? } // else {//else以及括号中的语句都是为原来的按钮准备的。。。 // mHandler.postDelayed(new Runnable() {//一个新的可运行的函数 // // @Override // public void run() { // int move_change = (int) (screen_w * WIDTH_RATE / 5);//五分之一要显示的宽度 // int left = (int) (screen_w * WIDTH_RATE - main_show_view // .getView().getLeft());//getleft()返回的是主屏左边缘离左边的距离 // Message msg = new Message(); // if (left > move_change) {//括号里面不懂,起什么作用? // msg.what = 1; // mHandler.sendMessage(msg); // mHandler.postDelayed(this, 10);//又调用自己,基本上非要是小于关系 // } else { // msg.what = 11; // mHandler.sendMessage(msg); // mHandler.removeCallbacks(this); // } // } // }, 0); // } } public void moveToMain( boolean b) { if (!b) { //right_show_view.getView().setVisibility(View.VISIBLE); left_show_view.getView().setVisibility(View.VISIBLE); int w = ( int ) (screen_w * WIDTH_RATE); main_show_view.getView().layout( 0 , 0 , screen_w, screen_h); left_show_view.getView().layout( 0 , 0 , w, screen_h); now_state = MAIN; } } public void initScreenSize( int w, int h) { this .screen_w = w; this .screen_h = h; Log.d( "screen" , "screen_w:" + w); this .setKeepScreenOn( true ); min_distance = ( int ) (screen_w / 12.0 ); //min_distance在这里又被初始化为屏幕的一个比例大小 initView(); initContent(); moveToMain( false ); } public int getNowState() { return this .now_state; } } |