Android 露珠/水滴 拖拽 效果實現
阿新 • • 發佈:2018-11-10
解釋一下標題:
露珠拖拽/水滴拖拽:就是一個View不但能跟著手滑動。還能根據滑動速度,改變形狀,像露珠或者水滴那樣。
具體實現就是如下一個Java檔案 DewdropView.java
package com.demo.dewdropdemo;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
public class DewdropView extends View{
private final String TAG = "dewdrop";
//View的寬和高
private int width;
private int height;
//是否正在拖拽
private boolean isDraging = false;
//手指觸控位置
private int touchPX;
private int touchPY;
//上一次統計的位置
private int mLastX = 0;
private int mLastY = 0;
//露珠效果大小
private final int rate = 2;
//要繪製的圖片資源
private Resources mRes;
private Drawable mDrawable;
//View的位置描述:Left、Top、Right、Bottom
private int l,t,r,b;
//手機螢幕尺寸
private int mScrrenWidth;
private int mScrrenHeight;
public DewdropView(Activity context) {
super(context);
// TODO Auto-generated constructor stub
init(context);
}
/**
* @title init
* @author [email protected]
* @description TODO 初始化
* @param context
* @date 2013-11-05 4:03:05 PM
*/
private void init(Activity context){
mRes = context.getResources();
getScrrenSize(context);
}
/**
* @title getScrrenSize
* @author [email protected]
* @description TODO 獲得手機螢幕大小
* @param context
* @date 2013-11-05 4:03:24 PM
*/
private void getScrrenSize(Activity context){
DisplayMetrics dm = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(dm);
mScrrenWidth = dm.widthPixels;
mScrrenHeight = dm.heightPixels;
}
/**
* @title setSize
* @author [email protected]
* @description TODO 設定View的顯示大小
* @param w
* @param h
* @date 2013-11-05 4:03:46 PM
*/
public void setSize(int w, int h){
if(w > mScrrenWidth){
w = mScrrenWidth;
}
if(h > mScrrenHeight){
h = mScrrenHeight;
}
width = w;
height = h;
r = l + width;
b = t + height;
validPos();
}
/**
* @title onDraging
* @author [email protected]
* @description TODO 拖拽事件處理
* @date 2013-11-05 4:08:56 PM
*/
private void onDraging(){
if(!isDraging){
return;
}
l = touchPX - width/2;
t = touchPY - height/2;
r = l + width;
b = t + height;
int speedX = getSpeedX(touchPX)*rate;
mLastX = touchPX;
int speedY = getSpeedY(touchPY)*rate;
mLastY = touchPY;
boolean isXValid = false;
if(speedX > speedY){
isXValid = true;
}
if(isXValid){
t = t + speedY;
b = b - speedY;
l = l - speedX;
r = r + speedX;
}else{
t = t - speedY;
b = b + speedY;
l = l + speedX;
r = r - speedX;
}
validPos();
layout(l, t, r, b);
}
/**
* @title getSpeedX
* @author [email protected]
* @description TODO 獲得X方向滑動速度
* @param x
* @return
* @date 2013-11-05 4:09:41 PM
*/
private int getSpeedX(int x){
if(mLastX == 0){
return 0;
}
return Math.abs(x - mLastX);
}
/**
* @title getSpeedY
* @author [email protected]
* @description TODO 獲得Y方向滑動速度
* @param y
* @return
* @date 2013-11-05 4:10:07 PM
*/
private int getSpeedY(int y){
if(mLastY == 0){
return 0;
}
return Math.abs(y - mLastY);
}
/**
* @title setImageResource
* @author [email protected]
* @description TODO 要顯示的圖片資源
* @param id
* @date 2013-11-05 4:10:28 PM
*/
public void setImageResource(int id){
if(mRes != null){
mDrawable = mRes.getDrawable(id);
}
}
/**
* @title validPos
* @author [email protected]
* @description TODO 使得View一直顯示在螢幕之內
* @date 2013-11-04 8:19:51 PM
*/
private void validPos(){
if(l < 0){
l = 0;
r = width;
}else if(r > mScrrenWidth){
r = mScrrenWidth;
l = r - width;
}
if(t < 0){
t = 0;
b = height;
}else if(b > mScrrenHeight){
b = mScrrenHeight;
t = b - height;
}
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if(mDrawable == null) return;
mDrawable.setBounds(0, 0, getWidth(), getHeight());
mDrawable.draw(canvas);
}
/**
* @title touch
* @author [email protected]
* @description TODO 傳遞進來的touch事件處理
* @param event
* @date 2013-11-05 4:11:20 PM
*/
public void touch(MotionEvent event) {
// TODO Auto-generated method stub
touchPX = (int)event.getX();
touchPY = (int)event.getY();
switch(event.getActionMasked()){
case MotionEvent.ACTION_DOWN:
if(isInView()){
isDraging = true;
}
break;
case MotionEvent.ACTION_UP:
isDraging = false;
if(isInView()){
reset();
}
break;
case MotionEvent.ACTION_MOVE:
onDraging();
break;
}
}
/**
* @title isInView
* @author [email protected]
* @description TODO 判斷點選位置是否在此View之上
* @return
* @date 2013-11-04 8:17:30 PM
*/
private boolean isInView(){
if(touchPX > l && touchPX < r && touchPY > t && touchPY < b){
return true;
}
return false;
}
/**
* @title reset
* @author [email protected]
* @description TODO 恢復圖形正常大小和寬高比
* @date 2013-11-04 8:16:35 PM
*/
private void reset(){
l = touchPX - width/2;
t = touchPY - height/2;
r = l + width;
b = t + height;
validPos();
layout(l, t, r, b);
}
}
具體用法見 效果實現的Demo