編輯:關於Android編程
下面我們把這個控件內嵌到Layout中做一些動畫和展示,效果圖:
這個子控件可以上下移動,可以左右滑動,如果上下滑動距離大於左右滑動距離,則必須上下滑動<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+1eLR+cC00LRvblRvdWNoysK8/jo8L3A+CjxwPjxwcmUgY2xhc3M9"brush:java;"> @Override
public boolean onTouchEvent(MotionEvent ev) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
int mScrollX = this.getScrollX();
final int action = ev.getAction();
final float x = ev.getX();
final float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
mFlagLimitMove = false;
mFlagLimitUp = false;
/*
* If being flinged and user touches, stop the fling. isFinished
* will be false if being flinged.
*/
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
// Remember where the motion event started
mOriMotionX = x;
mOriMotionY = y;
mLastMotionX = x;
mLastMotionY = y;
mTimeDown = System.currentTimeMillis();
mLastDownX = x;
return true;
case MotionEvent.ACTION_MOVE:
//如果是往後滑動,屏幕向前,那麼mLastMotionX是比x大的,deltaX是正的
int deltaX = (int) (mLastMotionX - x);
int deltaY = (int) (mLastMotionY - y);
// final int moveX = (int) (mOriMotionX - x);
final int moveY = (int) (mOriMotionY - y);
mLastMotionX = x;
mLastMotionY = y;
//X方向的移動更多
if (Math.abs(deltaY) < Math.abs(deltaX)) {
//雖然X方向移動更多,但由於已經判定為上下滑動,所以只能return true,做這種情況左右不能滑動
if (mFlagLimitUp) {
return true;
}
final int buffer = getWidth() / 2;
if (deltaX < 0) {
if (deltaX < -MOVEY_NUM_X) {
//mFlagLimitMove代表X方向確認在滑動了
mFlagLimitMove = true;
}
if (mCurrentScreen == 0 && !mExecuteWhileSnapOut) {
System.out.println("=====deltaX="+deltaX);
deltaX = getSlowDownDelta(deltaX);
System.out.println("=====after deltaX="+deltaX);
}
System.out.println("====mScrollX="+mScrollX+"buffer="+buffer+"deltaX="+deltaX+"x="+(Math.max(-mScrollX - buffer, deltaX)));
scrollBy(Math.max(-mScrollX - buffer, deltaX), 0);
// }
} else if (deltaX > 0) {
int availableToScroll = 0;
if (getChildCount() > 0) { //此時Workspace上可能未加任何item,count == 0
availableToScroll = getChildAt(
getChildCount() - 1).getRight()
- mScrollX - getWidth();
}
if (deltaX > MOVEY_NUM_X) {
mFlagLimitMove = true;
}
if (mCurrentScreen == getChildCount() - 1 && !mExecuteWhileSnapOut) {
deltaX = getSlowDownDelta(deltaX);
}
System.out.println("====availableToScroll="+availableToScroll+"deltaX="+deltaX);
scrollBy(Math.min(availableToScroll + buffer, deltaX), 0);
}
} else {
//如果已經判定為上下滑動或 ,當時X方向也有移動,這種情況也不處理
if (mFlagLimitMove || mFlagLimitUp) {
return true;
}
//deltaY>0說明為往上滑動
if (deltaY > 0 && moveY > MOVEY_NUM) {
if (mHandler != null) {
mFlagLimitUp = true;
mHandler.sendMessage(mHandler
.obtainMessage(DingLayout.MESSAGE_MOVING_UP));
}
} else if (deltaY < 0 && moveY < -MOVEY_NUM) {
if (mHandler != null) {
mFlagLimitUp = true;
mHandler.sendMessage(mHandler
.obtainMessage(DingLayout.MESSAGE_MOVING_DOWN));
}
}
}
return true;
case MotionEvent.ACTION_UP:
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(DEFAULT_VALUE,
mMaximumVelocity);
int velocityX = (int) velocityTracker.getXVelocity();
int velocityY = (int) velocityTracker.getYVelocity();
System.out.println("====mFlagLimitUp="+mFlagLimitUp+"mFlagLimitMove="+mFlagLimitMove);
if (!mFlagLimitUp) {
if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) {
// Fling hard enough to move left
snapToScreen(mCurrentScreen - 1);
} else if (velocityX < -SNAP_VELOCITY
&& mCurrentScreen < getChildCount() - 1) {
// Fling hard enough to move right
snapToScreen(mCurrentScreen + 1);
} else {
snapToDestination(mLastMotionX < mOriMotionX);
}
} else {
snapToDestination(mLastMotionX < mOriMotionX);
}
mTimeUp = System.currentTimeMillis();
//如果x方向移動非常少,並且沒有y方向的移動,我們來判斷是不是點擊事件
if (!mFlagLimitUp && !mFlagLimitMove) {
// 如果點擊時間比較短,而且手指沒有移動很大位置,則認為為點擊事件
if (Math.abs(x - mOriMotionX) < MOVE_LIMIT
&& Math.abs(y - mOriMotionY) < MOVE_LIMIT
&& Math.abs(mTimeUp - mTimeDown) < TIME_LIMIT) {
if (mHandler != null) {
mHandler.sendMessage(mHandler.obtainMessage(
DingLayout.MESSAGE_MOVING_CLICK, y));
return true;
}
}
if (velocityY > Y_RATE_LIMIT
&& Math.abs(velocityX) < X_RATE_LIMIT) {
if (mHandler != null) {
mHandler.sendMessage(mHandler
.obtainMessage(DingLayout.MESSAGE_MOVING_DOWN));
}
} else if (velocityY < -Y_RATE_LIMIT
&& Math.abs(velocityX) < X_RATE_LIMIT) {
if (mHandler != null) {
mHandler.sendMessage(mHandler
.obtainMessage(DingLayout.MESSAGE_MOVING_UP));
}
}
} // end flag
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
mFlagLimitMove = false;
mFlagLimitUp = false;
mTouchState = TOUCH_STATE_REST;
if (Math.abs(mLastDownX - x) > TEN) {
return true;
}
return false;
case MotionEvent.ACTION_CANCEL:
mTouchState = TOUCH_STATE_REST;
return false;
default:
break;
}
return true;
}
activity:
布局:
public class DingLayoutActivity extends Activity implements OnViewChangedListener { DingLayout mDingLayout; Workspace mWorkspace; /** 用inflater來載入layout. */ private LayoutInflater mInflater; int mTotalDingnum; ImageView mBtnRefresh; private int mCurrentDownUrlIndex = 0; public Handler mHandler = new Handler() { public void handleMessage(Message msg) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.main1); mDingLayout = (DingLayout) findViewById(R.id.dinglayout); mDingLayout.setHandlerFormActivity(this.mHandler); mWorkspace = (Workspace) findViewById(R.id.workspace); mWorkspace.setOnViewChangedListener(this); initialWorkspace(); } /** * 初始化workspace. */ private void initialWorkspace() { mInflater = LayoutInflater.from(this); // 該list為內存中的ding列表,列表中元素存儲著ding的A部分數據 DingManager dingMgr = DingManager.getInstance(this); Listlist = dingMgr.getDingList(); mTotalDingnum = list.size(); // 遍歷列表中的各個元素來構造workspace中的view for (int i = 0; i < mTotalDingnum; i++) { View view = mInflater.inflate(R.layout.ding_item, null); DingInfo info = list.get(i); view.setTag(info.getDingId()); String oldContent = info.getContent(); mWorkspace.addView(view); mBtnRefresh = (ImageView) view.findViewById(R.id.btn_refresh); setViewData(info, view, true); info.setContent(oldContent); // end modify } mDingLayout.updateDots(mTotalDingnum, mCurrentDownUrlIndex); } private void setViewData(DingInfo netdingdata, View view, boolean useTitle) { if (view == null) { return; } TextView title = (TextView) view.findViewById(R.id.title); TextView content = (TextView) view.findViewById(R.id.main_content); TextView description = (TextView) view.findViewById(R.id.description); TextView time = (TextView) view.findViewById(R.id.time); title.setText(netdingdata.getTitle()); // 默認值如果為空,不更新 String updateContent = netdingdata.getContent(); if (!TextUtils.isEmpty(updateContent)) { // modify by qiaopu 用title的view if (useTitle) { title.setText(netdingdata.getContent()); content.setText(""); } else { content.setText(netdingdata.getContent()); } // end modify } description.setText(netdingdata.getDescription()); time.setText(netdingdata.getTime()); } @Override public void onViewChanged(int viewIndex) { if (viewIndex < 0 || viewIndex >= mTotalDingnum) { // Log.d(TAG, "invalid mCurrentDownUrlIndex"); return; } if (mCurrentDownUrlIndex != viewIndex) { View view = mWorkspace.getChildAt(mCurrentDownUrlIndex); if (view != null) { } mCurrentDownUrlIndex = viewIndex; mDingLayout.updateDots(mTotalDingnum, mCurrentDownUrlIndex); } } }
public class DingLayout extends RelativeLayout { // /** Context */ // private Context mContext; /** MESSAGE_MOVING_UP表示手勢的動作為向上滑. */ public static final int MESSAGE_MOVING_UP = 0; /** MESSAGE_MOVING_UP表示手勢的動作為向下滑. */ public static final int MESSAGE_MOVING_DOWN = 1; /** MESSAGE_MOVING_UP表示手勢的動作為點擊. */ public static final int MESSAGE_MOVING_CLICK = 2; /** isUp為判斷workspace是否在上方. */ private boolean mIsUp = false; /** isUp為判斷滑動的動畫是否在進行中. */ private boolean mIsMove = false; /** 可上下滑動的Layout,包括Workspace和點點提示。 */ private ViewGroup mUpDownLayout; /** Workspace. */ private Workspace mSpace; /** 點點提示Workspace當前頁的Layout。 */ private LinearLayout mDotsLayout; /** 點點的Y坐標偏移。由於點點需要顯示在DING圖標下面,而DING圖標只有在Workspace的screen中才有,所以用此全局來計算並記住。 */ private int mDotsOffsetY; /** 當前索引。 */ private int mCurrent = -1; /** log tag. */ private static final String TAG = "DingLayout"; /** 動畫運行時間. */ private static final int ANIMATIONTIME = 650; /** mHandlerFromMainActivity從main activity傳進來. */ private Handler mHandlerFromMainActivity; /** 是否是動畫進行中.*/ private boolean isRunning = false; /** Context*/ private Context mContext = null; /** * view的構造函數. * * @param context * context * @param attrs * attrs * */ public DingLayout(Context context, AttributeSet attrs) { super(context, attrs); mIsUp = false; isRunning = false; mContext = context; } /** * @return 為ding在上還是在底下的標識 */ public boolean isUp() { return mIsUp; } /** * 把mainActivity的hander傳入這個view. * @param handlerFromMainActivity HandlerFromMainActivity */ public void setHandlerFormActivity(Handler handlerFromMainActivity) { this.mHandlerFromMainActivity = handlerFromMainActivity; } @Override public boolean dispatchTouchEvent(MotionEvent ev) { //如果在動畫進行中,不進行event的分發 if (isRunning) { return true; } return super.dispatchTouchEvent(ev); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); //下面兩句保證初始化時workspace的位置在上面或是在下面 if (mIsUp) { layoutUp(); } else { layoutDown(); } if (mDotsOffsetY == 0) { View dingView = findViewById(R.id.ding_view); if (dingView != null) { mDotsOffsetY = dingView.getBottom(); System.out.println("=====mDotsOffsetY="+mDotsOffsetY); } } if (mDotsOffsetY > 0) { //需要修改LayoutParams,否則在parent調用Layout的時候,坐標又會被改變。 LayoutParams params = (LayoutParams) mDotsLayout.getLayoutParams(); params.topMargin += mDotsOffsetY; mDotsLayout.layout(mDotsLayout.getLeft(), mDotsLayout.getTop() + mDotsOffsetY, mDotsLayout.getRight(), mDotsLayout.getBottom() + mDotsOffsetY); //只需執行一次。 mDotsOffsetY = -1; } } @Override protected void onFinishInflate() { super.onFinishInflate(); mUpDownLayout = (ViewGroup) findViewById(R.id.ding_updown_layout); mSpace = (Workspace) findViewById(R.id.workspace); mSpace.setHandler(mHandler); // mDotsLayout = (LinearLayout) findViewById(R.id.dots_layout); } /** * 更新點點的狀態,包括總數和當前位置。 * @param total 總數。 * @param current 當前位置。 */ public void updateDots(int total, int current) { Workspace.updateDots(mDotsLayout, total, current, null); } /** * setCurrentScreen. * @param index Index. */ public void setCurrentScreen(int index) { mSpace.setCurrentScreen(index); updateDots(getDingCount(), index); } /** * set IsUp的值. * @param isUp set mIsUp值 */ public void setIsUp(boolean isUp) { this.mIsUp = isUp; } /** * 獲取Ding的數量。 * @return 數量。 */ private int getDingCount() { Listlist = DingManager.getInstance(getContext()) .getDingList(); return list.size(); } /** * 向上移的動畫. */ private void moveUp() { logCat("moveUp mToppanel.getWidth()=" + mUpDownLayout.getWidth() + "mToppanel.getHeight()=" + mUpDownLayout.getHeight()); layoutUp(); Animation upAnimation = new TranslateAnimation(0, 0, getWorkSpaceDownPosition(), 0); upAnimation.setDuration(ANIMATIONTIME); upAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { mIsMove = true; isRunning = true; } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mIsMove = false; isRunning = false; if (mHandlerFromMainActivity != null) { Message msg = mHandlerFromMainActivity.obtainMessage(); msg.what = SearchListener.MSG_ANIMATION_DONE; mHandlerFromMainActivity.handleMessage(msg); mHandlerFromMainActivity .sendEmptyMessage(SearchListener.MSG_DING_UP_FINISHED); mHandlerFromMainActivity .sendEmptyMessage(SearchListener.MSG_DING_MOVE_UP); } } }); if (mHandlerFromMainActivity != null) { Message msg = mHandlerFromMainActivity.obtainMessage(); msg.what = SearchListener.MSG_ANIMATION_PREPARE; mHandlerFromMainActivity.handleMessage(msg); } mUpDownLayout.startAnimation(upAnimation); } /** * 向下移的動畫. */ private void moveDown() { if (mHandlerFromMainActivity != null) { // } logCat("mToppanel.getWidth()=" + mUpDownLayout.getWidth() + "mToppanel.getHeight()=" + mUpDownLayout.getHeight()); layoutDown(); Animation downAnimation = new TranslateAnimation(0, 0, -getWorkSpaceDownPosition(), 0); downAnimation.setDuration(ANIMATIONTIME); downAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { mIsMove = true; isRunning = true; } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { mIsMove = false; isRunning = false; if (mHandlerFromMainActivity != null) { Message msg = mHandlerFromMainActivity.obtainMessage(); msg.what = SearchListener.MSG_ANIMATION_DONE; mHandlerFromMainActivity.handleMessage(msg); } } }); if (mHandlerFromMainActivity != null) { Message msg = mHandlerFromMainActivity.obtainMessage(); msg.what = SearchListener.MSG_ANIMATION_PREPARE; mHandlerFromMainActivity.handleMessage(msg); } mUpDownLayout.startAnimation(downAnimation); } /** * 上移。 */ private void layoutUp() { mUpDownLayout.layout(mUpDownLayout.getLeft(), 0, mUpDownLayout.getRight(), mUpDownLayout.getHeight()); mUpDownLayout.setDrawingCacheEnabled(true); mUpDownLayout.buildDrawingCache(); } /** * 下移。 */ private void layoutDown() { int workSpacePosition = getWorkSpaceDownPosition(); mUpDownLayout.layout(mUpDownLayout.getLeft(), workSpacePosition, mUpDownLayout.getRight(), workSpacePosition + mUpDownLayout.getHeight()); mUpDownLayout.setDrawingCacheEnabled(false); } /** * 獲取workspace下移後的(top)position。 * @return position. */ private int getWorkSpaceDownPosition() { //A部分的高度 int heightPartA = getResources().getDimensionPixelSize(R.dimen.browseraddview_height); return getHeight() - heightPartA; } /** * 打log用. * @param log log */ private void logCat(String log) { } /** * 處理動畫的Handler. */ private Handler mHandler = new Handler() { public void handleMessage(Message msg) { if (mIsMove) { return; } switch (msg.what) { case MESSAGE_MOVING_UP: // top.setVisibility(View.GONE); if (!mIsUp) { mIsUp = true; moveUp(); } break; case MESSAGE_MOVING_DOWN: if (mIsUp) { mIsUp = false; // if(mHandler_fromActivity != null){ // mHandler_fromActivity.sendEmptyMessage(SearchListener.MSG_DING_MOVE_DOWN); // } moveDown(); } break; case MESSAGE_MOVING_CLICK: Object obj = msg.obj; Float t = (Float) obj; int dingLayoutHeight = getResources().getDimensionPixelSize(R.dimen.browseraddview_height); // t
item的布局:
原創博客地址:點擊傳送 AndroidResideMenu 先看看如何使用: 把項目源碼下載下來導入工程,可以看到 ResideMenu為引用工程,再看
廢話不多說直接看代碼需要注意的是ObjectAnimator.ofFloat(xiaoming, “age”, 0f,100f)傳入的是float
最近做的項目有個需求就是判斷一下還 剩多少字符可輸入,也就是對EditText 的文本變化做監聽 ,功能實現了,但是感覺使用組合方式,每次都要編寫,還不如寫
實現zip/tar的壓縮與解壓java中實際是提供了對 zip等壓縮格式的支持,但是為什麼這裡會用到ant呢?原因主要有兩個:1. java提供的類對於包括有