Android滑動解鎖控件

fpy7 9年前發布 | 15K 次閱讀 Java Android

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.mosjoy.ad.R;

public class SliderRelativeLayout extends RelativeLayout {

private static String TAG = "SliderRelativeLayout";
private TextView tv_slider_icon = null; // 初始控件,用來判斷是否為拖動?
private Bitmap dragBitmap = null; //拖拽圖片
private Context mContext = null; // 初始化圖片拖拽時的Bitmap對象
private Handler mainHandler = null; //與主Activity通信的Handler對象
private ImageView mPhoneImageView;
private ImageView mUnlockImageView;
private ImageView mMessageImageView;
private ImageView mCameraImageView;
private boolean mStopBoolean = false;
private Canvas mCanvas;
public SliderRelativeLayout(Context context) {
    super(context);
    mContext = context;
    initDragBitmap();
}

public SliderRelativeLayout(Context context, AttributeSet attrs) {
    super(context, attrs, 0);
    mContext = context;
    initDragBitmap();
}

public SliderRelativeLayout(Context context, AttributeSet attrs,
        int defStyle) {
    super(context, attrs, defStyle);
    mContext = context;
    initDragBitmap();
}

// 初始化圖片拖拽時的Bitmap對象
private void initDragBitmap() {
    if (dragBitmap == null)
        dragBitmap = BitmapFactory.decodeResource(mContext.getResources(),
                R.drawable.getup_slider_ico_normal);
}

@Override
protected void onFinishInflate() {
    super.onFinishInflate();
    // 該控件主要判斷是否處于滑動點擊區域。滑動時 處于INVISIBLE(不可見)狀態,滑動時處于VISIBLE(可見)狀態
    tv_slider_icon = (TextView) findViewById(R.id.slider_icon);
    mPhoneImageView = (ImageView) findViewById(R.id.iv_phone);
    mUnlockImageView = (ImageView) findViewById(R.id.iv_unlock);
    mCameraImageView = (ImageView) findViewById(R.id.iv_camera);
    mMessageImageView = (ImageView) findViewById(R.id.iv_message);
}
private int mLastMoveX = 1000;  //當前bitmap應該繪制的地方 , 初始值為足夠大,可以認為看不見
private int mLastMoveY = 1000;  //當前bitmap應該繪制的地方 , 初始值為足夠大,可以認為看不見
public boolean onTouchEvent(MotionEvent event) {
    int x = (int) event.getX();
    int y = (int) event.getY();
    switch (event.getAction()) {
    case MotionEvent.ACTION_DOWN:
        mLastMoveX = (int) event.getX();
        mLastMoveY = (int) event.getY();
        //處理Action_Down事件:  判斷是否點擊了滑動區域
        return handleActionDownEvenet(event);
    case MotionEvent.ACTION_MOVE:
        mLastMoveX = x; //保存了X軸方向
        mLastMoveY = y;
        invalidate(); //重新繪制   
        return true;
    case MotionEvent.ACTION_UP:
        //處理Action_Up事件:  判斷是否解鎖成功,成功則結束我們的Activity ;否則 ,緩慢回退該圖片。
        handleActionUpEvent(event);
        return true;
    }
    return super.onTouchEvent(event);
}

// 繪制拖動時的圖片
@Override
protected void onDraw (Canvas canvas) {
    super.onDraw(canvas);      
    // 圖片更隨手勢移動
    if (!mStopBoolean) {
        invalidateDragImg(canvas);
    }
    mCanvas = canvas;
}

// 圖片更隨手勢移動
private void invalidateDragImg(Canvas canvas) {
    //Log.e(TAG, "handleActionUpEvenet : invalidateDragImg" );
    //以合適的坐標值繪制該圖片
    int drawXCor = mLastMoveX - dragBitmap.getWidth()/2;
    int drawYCor = mLastMoveY - dragBitmap.getHeight()/2;
    canvas.drawBitmap(dragBitmap,  drawXCor < 0 ? 5 : drawXCor , drawYCor , null);

// isHitUnlock(canvas); }

// 手勢落下是,是否點中了圖片,即是否需要開始移動
private boolean handleActionDownEvenet(MotionEvent event) {
    Rect rect = new Rect();
    tv_slider_icon.getHitRect(rect);
    boolean isHit = rect.contains((int) event.getX(), (int) event.getY());
    //開始拖拽 ,隱藏該圖片
    if(isHit && !mStopBoolean){ 
        tv_slider_icon.setVisibility(View.INVISIBLE);
        mPhoneImageView.setVisibility(View.VISIBLE);
        mUnlockImageView.setVisibility(View.VISIBLE);
        mMessageImageView.setVisibility(View.VISIBLE);
        mCameraImageView.setVisibility(View.VISIBLE);
    }
    return isHit;
}

//判斷是否到達解鎖點
private boolean isHitUnlock() {
    Rect phoneRect = new Rect();
    mPhoneImageView.getHitRect(phoneRect);
    Rect unlockRect = new Rect();
    mUnlockImageView.getHitRect(unlockRect);
    Rect messageRect = new Rect();
    mMessageImageView.getHitRect(messageRect);
    Rect cameraRect = new Rect();
    mCameraImageView.getHitRect(cameraRect);
    //解鎖到電話界面
    if(phoneRect.contains(mLastMoveX,mLastMoveY)){
        mStopBoolean = true;
        adStopTwoSecond();
       //結束我們的主Activity界面
        Message msg = new Message();
        msg.what = MainLockActivity.MSG_PHONE_LOCK_SUCESS;
        mainHandler.sendMessageDelayed(msg, 2*1000);

// mainHandler.obtainMessage(MainLockActivity.MSG_PHONE_LOCK_SUCESS).sendToTarget(); return true; }else if(unlockRect.contains(mLastMoveX,mLastMoveY)){ mStopBoolean = true; adStopTwoSecond(); //結束我們的主Activity界面 Message msg = new Message(); msg.what = MainLockActivity.MSG_LOCK_SUCESS; mainHandler.sendMessageDelayed(msg, 21000); return true; }else if(messageRect.contains(mLastMoveX,mLastMoveY)){ mStopBoolean = true; adStopTwoSecond(); //結束我們的主Activity界面 Message msg = new Message(); msg.what = MainLockActivity.MSG_MESSAGE_LOCK_SUCESS; mainHandler.sendMessageDelayed(msg, 21000); // mainHandler.obtainMessage(MainLockActivity.MSG_MESSAGE_LOCK_SUCESS).sendToTarget(); return true; }else if(cameraRect.contains(mLastMoveX,mLastMoveY)){ mStopBoolean = true; adStopTwoSecond(); //結束我們的主Activity界面 Message msg = new Message(); msg.what = MainLockActivity.MSG_CAMERA_LOOK_SUCESS; mainHandler.sendMessageDelayed(msg, 2*1000); // mainHandler.obtainMessage(MainLockActivity.MSG_CAMERA_LOOK_SUCESS).sendToTarget(); return true; } return false; }

//回退動畫時間間隔值
private static int BACK_DURATION = 20 ;   // 20ms
//水平方向前進速率
private static float VE_HORIZONTAL = 0.7f ;  //0.1dip/ms
//判斷松開手指時,是否達到末尾即可以開鎖了 , 是,則開鎖,否則,通過一定的算法使其回退。
private void handleActionUpEvent(MotionEvent event){       
    int x = (int) event.getX() ;   
    int y = (int)event.getY();
    //解鎖到電話界面
    if(isHitUnlock()){
    }else {
        mStopBoolean = false;
        //沒有成功解鎖,以一定的算法使其回退
        //每隔20ms , 速率為0.6dip/ms ,  使當前的圖片往后回退一段距離,直到到達最左端  
        mLastMoveX = x ;  //記錄手勢松開時,當前的坐標位置。
        int distance = x - tv_slider_icon.getRight() ;
        //只有移動了足夠距離才回退
        Log.e(TAG, "handleActionUpEvent : mLastMoveX -->" + mLastMoveX + " distance -->" + distance );
        if(distance >= 0)
            mHandler.postDelayed(BackDragImgTask, BACK_DURATION);
        else{  //復原初始場景
            resetViewState();
        }
    }
}

//暫停兩秒
private void adStopTwoSecond() {
    mPhoneImageView.setVisibility(View.INVISIBLE);
    mUnlockImageView.setVisibility(View.INVISIBLE);
    mCameraImageView.setVisibility(View.INVISIBLE);
    mMessageImageView.setVisibility(View.INVISIBLE);

// mCanvas.drawBitmap(dragBitmap, 2000, 2000, null); invalidate(); // try { // Thread.sleep(2*1000); // } catch (InterruptedException e) { // e.printStackTrace(); // } }

//重置初始的狀態,顯示tv_slider_icon圖像,使bitmap不可見
private void resetViewState(){
    mLastMoveX = 1000;
    mLastMoveY = 1000;
    tv_slider_icon.setVisibility(View.VISIBLE);
    mPhoneImageView.setVisibility(View.INVISIBLE);
    mUnlockImageView.setVisibility(View.INVISIBLE);
    mCameraImageView.setVisibility(View.INVISIBLE);
    mMessageImageView.setVisibility(View.INVISIBLE);
    invalidate();        //重繪最后一次
}

//通過延時控制當前繪制bitmap的位置坐標
private Runnable BackDragImgTask = new Runnable(){
    public void run(){
        //一下次Bitmap應該到達的坐標值
        mLastMoveX = mLastMoveX - (int)(BACK_DURATION * VE_HORIZONTAL);
        invalidate();//重繪      
        //是否需要下一次動畫 ? 到達了初始位置,不在需要繪制
        boolean shouldEnd = Math.abs(mLastMoveX - tv_slider_icon.getRight()) <= 8 ;         
        if(!shouldEnd)
            mHandler.postDelayed(BackDragImgTask, BACK_DURATION);
        else { //復原初始場景
            resetViewState();  
        }              
    }
};

private Handler mHandler =new Handler (){
    public void handleMessage(Message msg){
    }
};
//震動一下下咯
private void virbate(){
    Vibrator vibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
    vibrator.vibrate(200);
}
public void setMainHandler(Handler handler){
    mainHandler = handler;//activity所在的Handler對象
}

}</pre>

 本文由用戶 fpy7 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!