1:子控件跟着手指移動
2:快速撥動一下,根據撥動的速度 滑動過去
3:拖過頭,放手後彈回去
但是用listView或者GridView又不好實現項目要求的其他效果..於是繼承viewGroup實現以上效果。
既然要獲取撥動速度,並以此滑動。首先想到了OnGestureListener 這個接口,實現這個接口並實現其onFling方法.
還要控制拖動。重寫onTouchEvent方法,並在其中控制內容控件的拖動,反彈等效果
這時候基本已經完成了。。。。測試了一下了,發現了一個問題,當手指點在viewGroup上
進行 拖動是沒問題的,但是在子控件上就不行了,這是事件響應的問題 那麼還要做如面的處
理:實現onInterceptTouchEvent方法,判斷是拖動事件時 ,將事件傳遞下去。
package com.android.moveViewGroup;
import android.app.Activity;
import android.os.Bundle;
public class MoveViewGroupActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new Workspace(this));
}
}
package com.android.moveViewGroup;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
public class Workspace extends ViewGroup {
public Workspace(Context context) {
super(context);
// TODO Auto-generated constructor stub
addView(new MyViewGroup(context));
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
child.measure(r - l, b - t);
child.layout(0, 0, 320, 480);
}
}
}
package com.android.moveViewGroup;
import java.util.List;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.GestureDetector.OnGestureListener;
import android.widget.Button;
import android.widget.Scroller;
import android.widget.Toast;
public class MyViewGroup extends ViewGroup implements OnGestureListener {
private float mLastMotionY;// 最後點擊的點
private GestureDetector detector;
int move = 0;// 移動距離
int MAXMOVE = 850;// 最大允許的移動距離
private Scroller mScroller;
int up_excess_move = 0;// 往上多移的距離
int down_excess_move = 0;// 往下多移的距離
private final static int TOUCH_STATE_REST = 0;
private final static int TOUCH_STATE_SCROLLING = 1;
private int mTouchSlop;
private int mTouchState = TOUCH_STATE_REST;
Context mContext;
public MyViewGroup(Context context) {
super(context);
mContext = context;
// TODO Auto-generated constructor stub
//setBackgroundResource(R.drawable.pic);
mScroller = new Scroller(context);
detector = new GestureDetector(this);
final ViewConfiguration configuration = ViewConfiguration.get(context);
// 獲得可以認爲是滾動的距離
mTouchSlop = configuration.getScaledTouchSlop();
// 添加子View
for (int i = 0; i < 48; i++) {
final Button MButton = new Button(context);
MButton.setText("" + (i + 1));
MButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(mContext, MButton.getText(), Toast.LENGTH_SHORT).show();
}
});
addView(MButton);
}
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
// 返回當前滾動X方向的偏移
scrollTo(0, mScroller.getCurrY());
postInvalidate();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
final float y = ev.getY();
switch (ev.getAction())
{
case MotionEvent.ACTION_DOWN:
mLastMotionY = y;
mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST
: TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_MOVE:
final int yDiff = (int) Math.abs(y - mLastMotionY);
boolean yMoved = yDiff > mTouchSlop;
// 判斷是否是移動
if (yMoved) {
mTouchState = TOUCH_STATE_SCROLLING;
}
break;
case MotionEvent.ACTION_UP:
mTouchState = TOUCH_STATE_REST;
break;
}
return mTouchState != TOUCH_STATE_REST;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// final int action = ev.getAction();
final float y = ev.getY();
switch (ev.getAction())
{
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished()) {
mScroller.forceFinished(true);
move = mScroller.getFinalY();
}
mLastMotionY = y;
break;
case MotionEvent.ACTION_MOVE:
if (ev.getPointerCount() == 1) {
// 隨手指 拖動的代碼
int deltaY = 0;
deltaY = (int) (mLastMotionY - y);
mLastMotionY = y;
Log.d("move", "" + move);
if (deltaY < 0) {
// 下移
// 判斷上移 是否滑過頭
if (up_excess_move == 0) {
if (move > 0) {
int move_this = Math.max(-move, deltaY);
move = move + move_this;
scrollBy(0, move_this);
} else if (move == 0) {// 如果已經是最頂端 繼續往下拉
Log.d("down_excess_move", "" + down_excess_move);
down_excess_move = down_excess_move - deltaY / 2;// 記錄下多往下拉的值
scrollBy(0, deltaY / 2);
}
} else if (up_excess_move > 0)// 之前有上移過頭
{
if (up_excess_move >= (-deltaY)) {
up_excess_move = up_excess_move + deltaY;
scrollBy(0, deltaY);
} else {
up_excess_move = 0;
scrollBy(0, -up_excess_move);
}
}
} else if (deltaY > 0) {
// 上移
if (down_excess_move == 0) {
if (MAXMOVE - move > 0) {
int move_this = Math.min(MAXMOVE - move, deltaY);
move = move + move_this;
scrollBy(0, move_this);
} else if (MAXMOVE - move == 0) {
if (up_excess_move <= 100) {
up_excess_move = up_excess_move + deltaY / 2;
scrollBy(0, deltaY / 2);
}
}
} else if (down_excess_move > 0) {
if (down_excess_move >= deltaY) {
down_excess_move = down_excess_move - deltaY;
scrollBy(0, deltaY);
} else {
down_excess_move = 0;
scrollBy(0, down_excess_move);
}
}
}
}
break;
case MotionEvent.ACTION_UP:
// 多滾是負數 記錄到move裏
if (up_excess_move > 0) {
// 多滾了 要彈回去
scrollBy(0, -up_excess_move);
invalidate();
up_excess_move = 0;
}
if (down_excess_move > 0) {
// 多滾了 要彈回去
scrollBy(0, down_excess_move);
invalidate();
down_excess_move = 0;
}
mTouchState = TOUCH_STATE_REST;
break;
}
return this.detector.onTouchEvent(ev);
}
int Fling_move = 0;
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
//隨手指 快速撥動的代碼
Log.d("onFling", "onFling");
if (up_excess_move == 0 && down_excess_move == 0) {
int slow = -(int) velocityY * 3 / 4;
mScroller.fling(0, move, 0, slow, 0, 0, 0, MAXMOVE);
move = mScroller.getFinalY();
computeScroll();
}
return false;
}
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return true;
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
return false;
}
public void onShowPress(MotionEvent e) {
// // TODO Auto-generated method stub
}
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
int childTop = 0;
int childLeft = 0;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
child.setVisibility(View.VISIBLE);
child.measure(r - l, b - t);
child.layout(childLeft, childTop, childLeft + 80,
childTop + 80);
if (childLeft < 160) {
childLeft += 80;
} else {
childLeft = 0;
childTop += 80;
}
}
}
}
}