編輯:關於Android編程
獲取view在屏幕上的坐標(view左上角的坐標)
View view = (View) findViewById(R.id.view);
int []location=new int[2];
view.getLocationOnScreen(location);
int x=location[0];//獲取當前位置的橫坐標
int y=location[1];//獲取當前位置的縱坐標
觸控事件使用getRawX(),getRawY()獲得也是Android坐標系的坐標。
獲取view相對父view的坐標(以父view左上角為坐標原點)
View view = (View) findViewById(R.id.view);
int []location=new int[2];
view.getLocationInWindow(location);
int x=location[0];//獲取當前位置的橫坐標
int y=location[1];//獲取當前位置的縱坐標
觸控事件中getX(),getY()獲得坐標是視圖坐標系中的坐標。
拓展閱讀Android View體系
實現思路:觸摸view時,記下當前觸摸點坐標和移動後的觸摸點坐標,從而獲取到偏移量,並通過偏移量來修改View的坐標,從而實現滑動過程。
view在繪制之前,會調用onLayout方法設置顯示的位置。那麼可以改變view的left,top,bottom,right值來改變view的位置。
//視圖坐標方式
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 記錄觸摸點坐標
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
// 計算偏移量
int offsetX = x - lastX;
int offsetY = y - lastY;
// 在當前left、top、right、bottom的基礎上加上偏移量
layout(getLeft() + offsetX,
getTop() + offsetY,
getRight() + offsetX,
getBottom() + offsetY);
// offsetLeftAndRight(offsetX);
// offsetTopAndBottom(offsetY);
break;
}
return true;
}
// 絕對坐標方式
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) (event.getRawX());
int rawY = (int) (event.getRawY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// 記錄觸摸點坐標
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
// 計算偏移量
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
// 在當前left、top、right、bottom的基礎上加上偏移量
layout(getLeft() + offsetX,
getTop() + offsetY,
getRight() + offsetX,
getBottom() + offsetY);
// 重新設置初始坐標
lastX = rawX;
lastY = rawY;
break;
}
return true;
}
這個方法相當於系統提供的一個左右、上下移動的API封裝。只需要把計算出的偏移量傳入即可完成view的移動。偏移量計算與上一個方法相同。
//同時對left和right進行偏移
offsetLeftAndRight(offsetX);
//同時對top和bottom進行偏移
offsetTopAndBottom(offsetY);
LayoutParams保存了一個view的布局參數。通過改變LayoutParams的參數來改變view的位置。
// ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();
layoutParams.leftMargin = getLeft() + offsetX;
layoutParams.topMargin = getTop() + offsetY;
setLayoutParams(layoutParams);
要注意的是,通過getLayoutParams獲取LayoutParams時,要根據view的父view的類型設置不同的類型。例如父布局是LinearLayout時,就可以使用LinearLayout.LayoutParams。而且,前提是要有一個父布局,不然無法獲取LayoutParams。
另外一種方法是使用ViewGroup.MarginLayoutParams,不需要考慮父布局的類型。
srcollTo表示將移動到一個具體的坐標點,scrollBy表示移動偏移量。
但是,scrollTo和scrollBy移動的是view的content(ViewGroup的content是子view,textview的content是文本,imageview的content是drawable對象)。所以要移動一個view時,應該使用父view的scrollTo和scrollBy方法。
另外一個問題是,父view和子view的移動方向是相反的。例如子view想要實現向右移動的效果,偏移量為10。如果調用父view的scrollBy(10,0),子view實際上是向左偏移10單位。原因是父view和子view的相對位置是相反的:父view向右時,子view相對父view是向左的。
((View) getParent()).scrollBy(-offsetX, -offsetY);
Note:書上讀到這兒有點困惑:一邊說scrollBy移動的是viewGroup的內容(即view),一邊又說移動的是ViewGroup本身(所以才有相對位移)。
前面提到的方法都是在觸摸移動過程中不斷修改view的坐標來實現移動,因此移動過程看上去是平滑的。如果要實現這樣一種效果:點擊一個按鈕,讓一個view移動。那麼這個移動過程將是瞬間完成的。要使這樣一個移動過程也變得平滑,就要使用Scroller類。
步驟:
1. 初始化Scroller
mScroller = new Scroller(context);
2. 重寫computeScroll()方法,實現模擬滑動
@Override
public void computeScroll() {
super.computeScroll();
// 判斷Scroller是否執行完畢
if (mScroller.computeScrollOffset()) {
((View) getParent()).scrollTo(
mScroller.getCurrX(),
mScroller.getCurrY());
// 通過重繪來不斷調用computeScroll
invalidate();
}
}
invalidate()方法的作用是循環調用computeScroll。執行流程為:invalidate()–> draw()–> computeScroll()。從而實現不斷調用scrollTo移動一小段距離,實現模擬滑動的效果。當滑動完成後,循環結束。
3. startScroll開啟模擬過程
使用以下兩個重載方法:
public void startScroll(int startX,int startY,int dx,int dy,int duration);
public void startScroll(int startX,int startY,int dx,int dy);
在需要開始移動的方法裡寫入以下代碼:
View viewGroup = ((View) getParent());
mScroller.startScroll(
viewGroup.getScrollX(),
viewGroup.getScrollY(),
-viewGroup.getScrollX(),
-viewGroup.getScrollY());//偏移量仍為相反數
invalidate();
一個功能強大的類:ViewDragHelper。通過它可以實現各種不同的滑動、拖放需求。以下以實現滑動展開側邊菜單欄效果為例說明ViewDragHelper的使用。整個布局分為mMenuView和mMainView。功能為監聽mMainView的觸摸事件實現拖動,拖動完成後根據拖動距離使mMenuView滑動。
1. 初始化ViewDragHelper
mViewDragHelper = ViewDragHelper.create(this, callback);
第一個參數是要監聽的view,通常需要時一個ViewGroup。第二個參數是一個callback回調。
2. 攔截事件
要重寫事件攔截方法,將事件傳遞給ViewDragHelper進行處理。
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//將觸摸事件傳遞給ViewDragHelper,此操作必不可少
mViewDragHelper.processTouchEvent(event);
return true;
}
3. 處理computeScroll()
ViewDragHelper也是使用Scroller來實現平滑移動的。因此也需要重寫computeScroll方法。
@Override
public void computeScroll() {
if (mViewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
4. 處理回調callback
private ViewDragHelper.Callback callback =
new ViewDragHelper.Callback() {
// 何時開始檢測觸摸事件
@Override
public boolean tryCaptureView(View child, int pointerId) {
//如果當前觸摸的child是mMainView時開始檢測,即只有mMainView是可以被拖動的
return mMainView == child;
}
// 觸摸到View後回調
@Override
public void onViewCaptured(View capturedChild,
int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
}
// 當拖拽狀態改變,比如idle,dragging
@Override
public void onViewDragStateChanged(int state) {
super.onViewDragStateChanged(state);
}
// 當位置改變的時候調用,常用與滑動時更改scale等
@Override
public void onViewPositionChanged(View changedView,
int left, int top, int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
}
// 處理垂直滑動
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
// 處理水平滑動
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}
// 拖動結束後調用
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
//手指抬起後緩慢移動到指定位置
if (mMainView.getLeft() < 500) {
//關閉菜單
//相當於Scroller的startScroll方法
mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
} else {
//打開菜單
mViewDragHelper.smoothSlideViewTo(mMainView, 300, 0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}
}
};
clampViewPositionVertical和clampViewPositionHorizontal方法分別對應垂直和水平方向上的滑動。這兩個類必須重寫。因為它們默認返回0,即不滑動。clampViewPositionVertical中的參數top,代表在垂直方向上child移動的距離,dy表示比較前一次的增量。通常情況下,只需要返回top和left即可。需要更加精確的時候,才對top和left進行一些處理。 onViewReleased在拖動結束後,即手指抬起後的處理。這裡實現的是view的移動(繼續展開或者撤回),實現原理和Scroller一樣。 ViewDragHelper其他回調事件舉例:今天又開始我的App開發,因為之前一直做的是SDK,所以涉及到界面UI很少,剛開始做Android應用的時候,沒有對dp,px,sp等概念有一個深入的了解,只知道他們之間
大家都知道,android studio 有一個功能就是使用第三方jar的時候在build.gradle中直接 compile 'com.android.supp
模仿小米安全中心檢測效果廢話少說,咱們先上效果圖:github地址: https://github.com/niniloveyou/GradeProgressView這個
本文實例講述了Android創建可點擊的Button實現方法。分享給大家供大家參考,具體如下:感覺到自己有必要學習下手機開發方面的知識,不論是為了以後的工作需求還是目前的