欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android實現(xiàn)自定義滑動式抽屜菜單效果

 更新時間:2020年04月08日 16:47:24   作者:我是喬同學(xué)  
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)自定義滑動式抽屜效果菜單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

在Andoird使用Android自帶的那些組件,像SlidingDrawer和DrawerLayout都是抽屜效果的菜單,但是在項目很多要實現(xiàn)的功能都收到Android這些自帶組件的限制,導(dǎo)致很難完成項目的需求,自定義的組件,各方面都在自己的控制之下,從而根據(jù)需求做出調(diào)整。想要實現(xiàn)好的效果,基本上都的基于Android的OnTouch事件自己實現(xiàn)響應(yīng)的功能。

首先,給大家先看一下整體的效果:

滑動的加速度效果都是有的,具體的體驗,只能安裝后才能查看。
接下來,看代碼:
代碼從MainActivity延伸出了2個類:MainController和MainView,MainController來處理控制層、MainView來操作展示層。
主要代碼:
MainActivity的代碼:

package com.example.wz;

import com.example.wz.controller.MainController;
import com.example.wz.util.MyLog;
import com.example.wz.view.MainView;

import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;

public class MainActivity extends Activity {

 public MyLog log = new MyLog(this, true);

 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 log.e("歡迎你加入測試項目.");
 link();
 }

 public MainController mainController;
 public MainView mainView;

 private void link() {
 this.mainController = new MainController(this);
 this.mainView = new MainView(this);

 this.mainController.thisView = this.mainView;
 this.mainView.thisController = this.mainController;

 this.mainView.initViews();
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
 super.onTouchEvent(event);
 return mainController.onTouchEvent(event);
 }
}

MainController的代碼:

package com.example.wz.controller;

import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;

import com.example.wz.MainActivity;
import com.example.wz.util.MyLog;
import com.example.wz.util.OpenLooper;
import com.example.wz.util.OpenLooper.LoopCallback;
import com.example.wz.view.MainView;

public class MainController {

 public MyLog log = new MyLog(this, true);

 public MainActivity mainActivity;
 public MainController thisController;
 public MainView thisView;

 public GestureDetector mGesture;

 public MainController(MainActivity mainActivity) {
 this.mainActivity = mainActivity;
 this.thisController = this;

 mGesture = new GestureDetector(mainActivity, new GestureListener());
 openLooper = new OpenLooper();
 openLooper.createOpenLooper();
 loopCallback = new ListLoopCallback(openLooper);
 openLooper.loopCallback = loopCallback;
 }

 public class TouchStatus {
 public int None = 4, Down = 1, Horizontal = 2, Vertical = 3, Up = 4;// LongPress = 5
 public int state = None;
 }

 public TouchStatus touchStatus = new TouchStatus();

 public class BodyStatus {
 public int Fixed = 0, Dragging = 1, Homing = 2, FlingHoming = 3, BoundaryHoming = 4;
 public int state = Fixed;
 }

 public BodyStatus bodyStatus = new BodyStatus();

 public class DrawStatus {
 public int Closed = 0, Open = 1, GoClosing = 2, GoOpening = 3;
 public int state = Closed;
 }

 public DrawStatus drawStatus = new DrawStatus();

 public class AreaStatus {
 public int A = 0, B = 1;
 public int state = A;
 }

 public AreaStatus areaStatus = new AreaStatus();

 public float touch_pre_x;
 public float touch_pre_y;

 public float currentTranslateX;

 public boolean onTouchEvent(MotionEvent event) {
 int action = event.getAction();

 float x = event.getX();
 float y = event.getY();

 if (action == MotionEvent.ACTION_DOWN) {
 this.touch_pre_x = x;
 this.touch_pre_y = y;

 if (touchStatus.state == touchStatus.None) {
 touchStatus.state = touchStatus.Down;
 log.e("Down ");
 if (x > thisView.maxTranslateX) {
  areaStatus.state = areaStatus.B;
 } else if (x <= thisView.maxTranslateX) {
  areaStatus.state = areaStatus.A;
 }
 }
 } else if (action == MotionEvent.ACTION_MOVE) {
 float Δy = (y - touch_pre_y);
 float Δx = (x - touch_pre_x);
 if (touchStatus.state == touchStatus.Down) {
 if (Δx * Δx + Δy * Δy > 400) {
  if (Δx * Δx > Δy * Δy) {
  touchStatus.state = touchStatus.Horizontal;
  } else {
  touchStatus.state = touchStatus.Vertical;
  }
  touch_pre_x = x;
  touch_pre_y = y;
  log.e("ACTION_MOVE ");
 }
 } else if (touchStatus.state == touchStatus.Horizontal) {
 currentTranslateX += Δx;
 this.touch_pre_x = x;
 this.touch_pre_y = y;
 if (currentTranslateX - thisView.maxTranslateX <= 0 && currentTranslateX >= 0) {
  setPosition();
 }
 log.e("Horizontal");
 bodyStatus.state = bodyStatus.Dragging;
 } else if (touchStatus.state == touchStatus.Vertical) {
 log.e("Vertical");
 bodyStatus.state = bodyStatus.Dragging;
 }
 } else if (action == MotionEvent.ACTION_UP) {
 log.e("ACTION_UP");
 if (bodyStatus.state == bodyStatus.Dragging) {
 if (touchStatus.state == touchStatus.Horizontal) {
  bodyStatus.state = bodyStatus.Homing;
  openLooper.start();
 } else if (touchStatus.state == touchStatus.Vertical) {
  if (drawStatus.state == drawStatus.Open && areaStatus.state == areaStatus.B) {
  bodyStatus.state = bodyStatus.Homing;
  drawStatus.state = drawStatus.GoClosing;
  openLooper.start();
  }
 }
 } else if (touchStatus.state == touchStatus.Down && areaStatus.state == areaStatus.B) {
 bodyStatus.state = bodyStatus.Homing;
 drawStatus.state = drawStatus.GoClosing;
 openLooper.start();
 }
 touchStatus.state = touchStatus.Up;
 }
 mGesture.onTouchEvent(event);
 return true;
 }

 class GestureListener extends SimpleOnGestureListener {

 @Override
 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
 if (velocityX * velocityX + velocityY * velocityY > 250000) {
 if (velocityX * velocityX > velocityY * velocityY) {
  log.e("velocityX--" + velocityX);
  if (drawStatus.state == drawStatus.Closed && velocityX < 0) {
  } else if (drawStatus.state == drawStatus.Open && velocityX > 0) {
  } else {
  dxSpeed = velocityX;
  bodyStatus.state = bodyStatus.FlingHoming;
  openLooper.start();
  }
 } else {
  log.e("velocityY");
 }
 }
 return true;
 }

 public void onLongPress(MotionEvent event) {
 }

 public boolean onDoubleTap(MotionEvent event) {
 return false;
 }

 public boolean onDoubleTapEvent(MotionEvent event) {
 return false;
 }

 public boolean onSingleTapUp(MotionEvent event) {
 return false;
 }

 @Override
 public boolean onSingleTapConfirmed(MotionEvent event) {
 return false;
 }

 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
 return false;
 }
 }

 public void setPosition() {
 thisView.v1.setTranslationX(currentTranslateX - thisView.maxTranslateX);
 thisView.v2.setTranslationX(Math.abs(currentTranslateX));
 }

 float transleteSpeed = 3f;
 OpenLooper openLooper = null;
 LoopCallback loopCallback = null;

 public class ListLoopCallback extends LoopCallback {
 public ListLoopCallback(OpenLooper openLooper) {
 openLooper.super();
 }

 @Override
 public void loop(double ellapsedMillis) {
 if (bodyStatus.state == bodyStatus.Homing) {
 hommingView((float) ellapsedMillis);
 } else if (bodyStatus.state == bodyStatus.FlingHoming) {
 flingHomingView((float) ellapsedMillis);
 }
 }
 }

 public float ratio = 0.0008f;

 public void flingHomingView(float ellapsedMillis) {
 float distance = (float) ellapsedMillis * transleteSpeed;
 boolean isStop = false;
 if (drawStatus.state == drawStatus.Closed) {
 drawStatus.state = drawStatus.GoOpening;
 } else if (drawStatus.state == drawStatus.Open) {
 drawStatus.state = drawStatus.GoClosing;
 }
 if (drawStatus.state == drawStatus.GoClosing) {
 this.currentTranslateX -= distance;
 if (this.currentTranslateX <= 0) {
 this.currentTranslateX = 0;
 drawStatus.state = drawStatus.Closed;
 isStop = true;
 log.e("-------------1");
 }
 } else if (drawStatus.state == drawStatus.GoOpening) {
 this.currentTranslateX += distance;
 if (this.currentTranslateX >= thisView.maxTranslateX) {
 this.currentTranslateX = thisView.maxTranslateX;
 drawStatus.state = drawStatus.Open;
 isStop = true;
 log.e("-------------2");
 }
 }
 setPosition();
 if (isStop) {
 openLooper.stop();
 }
 }

 public float dxSpeed;

 public void dampenSpeed(long deltaMillis) {

 if (this.dxSpeed != 0.0f) {
 this.dxSpeed *= (1.0f - 0.002f * deltaMillis);
 if (Math.abs(this.dxSpeed) < 50f)
 this.dxSpeed = 0.0f;
 }
 }

 public void hommingView(float ellapsedMillis) {
 float distance = (float) ellapsedMillis * transleteSpeed;
 boolean isStop = false;
 if (drawStatus.state == drawStatus.Closed && this.currentTranslateX < thisView.maxTranslateX / 5) {
 this.currentTranslateX -= distance;
 if (this.currentTranslateX <= 0) {
 this.currentTranslateX = 0;
 drawStatus.state = drawStatus.Closed;
 isStop = true;
 }
 } else if (drawStatus.state == drawStatus.Closed && this.currentTranslateX >= thisView.maxTranslateX / 5) {
 this.currentTranslateX += distance;
 if (this.currentTranslateX >= thisView.maxTranslateX) {
 this.currentTranslateX = thisView.maxTranslateX;
 drawStatus.state = drawStatus.Open;
 isStop = true;
 }
 } else if (drawStatus.state == drawStatus.Open && this.currentTranslateX < thisView.maxTranslateX / 5 * 4) {
 this.currentTranslateX -= distance;
 if (this.currentTranslateX <= 0) {
 this.currentTranslateX = 0;
 drawStatus.state = drawStatus.Closed;
 isStop = true;
 }
 } else if (drawStatus.state == drawStatus.Open && this.currentTranslateX >= thisView.maxTranslateX / 5 * 4) {
 this.currentTranslateX += distance;
 if (this.currentTranslateX >= thisView.maxTranslateX) {
 this.currentTranslateX = thisView.maxTranslateX;
 drawStatus.state = drawStatus.Open;
 isStop = true;
 }
 } else if (drawStatus.state == drawStatus.GoClosing) {
 this.currentTranslateX -= distance;
 if (this.currentTranslateX <= 0) {
 this.currentTranslateX = 0;
 drawStatus.state = drawStatus.Closed;
 isStop = true;
 }
 }
 setPosition();
 if (isStop) {
 openLooper.stop();
 log.e("looper stop...");
 }
 }

}

MainView的代碼:

package com.example.wz.view;

import android.graphics.Color;
import android.util.DisplayMetrics;
import android.view.ViewGroup.LayoutParams;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.wz.MainActivity;
import com.example.wz.R;
import com.example.wz.controller.MainController;
import com.example.wz.util.MyLog;

public class MainView {

 public MyLog log = new MyLog(this, true);

 public MainActivity mainActivity;
 public MainController thisController;
 public MainView thisView;

 public MainView(MainActivity mainActivity) {
 this.mainActivity = mainActivity;
 this.thisView = this;
 }

 public DisplayMetrics displayMetrics;

 public float screenWidth;
 public float screenHeight;
 public float density;

 public float maxTranslateX;

 public RelativeLayout maxView;
 public RelativeLayout v1;
 public RelativeLayout v2;

 public void initViews() {
 this.displayMetrics = new DisplayMetrics();
 this.mainActivity.getWindowManager().getDefaultDisplay().getMetrics(this.displayMetrics);
 this.screenHeight = this.displayMetrics.heightPixels;
 this.screenWidth = this.displayMetrics.widthPixels;
 this.density = this.displayMetrics.density;
 this.maxTranslateX = this.screenWidth * 0.8f;
 this.mainActivity.setContentView(R.layout.activity_main);
 this.maxView = (RelativeLayout) this.mainActivity.findViewById(R.id.maxView);
 v1 = new RelativeLayout(mainActivity);
 v1.setBackgroundColor(Color.RED);
 RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams((int) this.maxTranslateX, LayoutParams.MATCH_PARENT);
 this.maxView.addView(v1, params1);
 TextView t1 = new TextView(mainActivity);
 t1.setText("left menu bar");
 t1.setTextColor(Color.WHITE);
 v1.addView(t1);
 v1.setTranslationX(0 - this.maxTranslateX);
 v2 = new RelativeLayout(mainActivity);
 v2.setBackgroundColor(Color.parseColor("#0099cd"));
 RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams((int) this.screenWidth, LayoutParams.MATCH_PARENT);
 this.maxView.addView(v2, params2);
 v2.setTranslationX(0);
 TextView t2 = new TextView(mainActivity);
 t2.setText("body content");
 t2.setTextColor(Color.WHITE);
 v2.addView(t2);
 }
}

日志管理類MyLog:

package com.example.wz.util;

import android.util.Log;

public class MyLog {

 public static boolean isGlobalTurnOn = true;

 public boolean isTurnOn = true;
 public String tag = null;

 public MyLog(String tag, boolean isTurnOn) {
 this.tag = tag;
 this.isTurnOn = isTurnOn;
 }

 public MyLog(Object clazz, boolean isTurnOn) {
 this.tag = clazz.getClass().getSimpleName();
 this.isTurnOn = isTurnOn;
 }

 public void v(String message) {
 this.v(this.tag, message);
 }

 public void d(String message) {
 this.d(this.tag, message);
 }

 public void i(String message) {
 this.i(this.tag, message);
 }

 public void w(String message) {
 this.w(this.tag, message);
 }

 public void e(String message) {
 this.e(this.tag, message);
 }

 public void v(String tag, String message) {
 if (isTurnOn && isGlobalTurnOn) {
 Log.v(tag, message);
 }
 }

 public void d(String tag, String message) {
 if (isTurnOn && isGlobalTurnOn) {
 Log.d(tag, message);
 }
 }

 public void i(String tag, String message) {
 if (isTurnOn && isGlobalTurnOn) {
 Log.i(tag, message);
 }
 }

 public void w(String tag, String message) {
 if (isTurnOn && isGlobalTurnOn) {
 Log.w(tag, message);
 }
 }

 public void e(String tag, String message) {
 if (isTurnOn && isGlobalTurnOn) {
 Log.e(tag, message);
 }
 }

}

實現(xiàn)動畫效果的核心類OpenLooper:

package com.example.wz.util;

import android.annotation.TargetApi;
import android.os.Build;
import android.os.Handler;
import android.os.SystemClock;
import android.view.Choreographer;

public class OpenLooper {

 public LegacyAndroidSpringLooper legacyAndroidSpringLooper = null;
 public ChoreographerAndroidSpringLooper choreographerAndroidSpringLooper = null;
 public LoopCallback loopCallback = null;

 public void createOpenLooper() {
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
 choreographerAndroidSpringLooper = new ChoreographerAndroidSpringLooper();
 } else {
 legacyAndroidSpringLooper = new LegacyAndroidSpringLooper();
 }
 }

 public void start() {
 if (choreographerAndroidSpringLooper != null) {
 choreographerAndroidSpringLooper.start();
 } else if (legacyAndroidSpringLooper != null) {
 legacyAndroidSpringLooper.start();
 }
 }

 public void stop() {
 if (choreographerAndroidSpringLooper != null) {
 choreographerAndroidSpringLooper.stop();
 } else if (legacyAndroidSpringLooper != null) {
 legacyAndroidSpringLooper.stop();
 }
 }

 public class LoopCallback {

 public void loop(double ellapsedMillis) {

 }
 }

 public void loop(double ellapsedMillis) {
 if (this.loopCallback != null) {
 this.loopCallback.loop(ellapsedMillis);
 }
 }

 public class LegacyAndroidSpringLooper {

 public Handler mHandler;
 public Runnable mLooperRunnable;
 public boolean mStarted;
 public long mLastTime;

 public LegacyAndroidSpringLooper() {
 initialize(new Handler());
 }

 public void initialize(Handler handler) {
 mHandler = handler;
 mLooperRunnable = new Runnable() {
 @Override
 public void run() {
  if (!mStarted) {
  return;
  }
  long currentTime = SystemClock.uptimeMillis();
  loop(currentTime - mLastTime);
  mHandler.post(mLooperRunnable);
 }
 };
 }

 public void start() {
 if (mStarted) {
 return;
 }
 mStarted = true;
 mLastTime = SystemClock.uptimeMillis();
 mHandler.removeCallbacks(mLooperRunnable);
 mHandler.post(mLooperRunnable);
 }

 public void stop() {
 mStarted = false;
 mHandler.removeCallbacks(mLooperRunnable);
 }
 }

 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
 public class ChoreographerAndroidSpringLooper {

 public Choreographer mChoreographer;
 public Choreographer.FrameCallback mFrameCallback;
 public boolean mStarted;
 public long mLastTime;

 public ChoreographerAndroidSpringLooper() {
 initialize(Choreographer.getInstance());
 }

 public void initialize(Choreographer choreographer) {
 mChoreographer = choreographer;
 mFrameCallback = new Choreographer.FrameCallback() {
 @Override
 public void doFrame(long frameTimeNanos) {
  if (!mStarted) {
  return;
  }
  long currentTime = SystemClock.uptimeMillis();
  loop(currentTime - mLastTime);
  mLastTime = currentTime;
  mChoreographer.postFrameCallback(mFrameCallback);
 }
 };
 }

 public void start() {
 if (mStarted) {
 return;
 }
 mStarted = true;
 mLastTime = SystemClock.uptimeMillis();
 mChoreographer.removeFrameCallback(mFrameCallback);
 mChoreographer.postFrameCallback(mFrameCallback);
 }

 public void stop() {
 mStarted = false;
 mChoreographer.removeFrameCallback(mFrameCallback);
 }
 }
}

源碼下載:抽屜效果

更多關(guān)于滑動功能的文章,請點擊專題: 《Android滑動功能》

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android全面屏適配方法詳解

    Android全面屏適配方法詳解

    Apple一直在引領(lǐng)設(shè)計的潮流,自從 iPhone X 發(fā)布之后,各種異形屏、劉海屏也都出來,下面這篇文章主要給大家分享介紹了關(guān)于Android全面屏與異形(劉海)屏的適配教程,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-11-11
  • Android使用ViewPager實現(xiàn)啟動引導(dǎo)頁

    Android使用ViewPager實現(xiàn)啟動引導(dǎo)頁

    這篇文章主要為大家詳細(xì)介紹了Android使用ViewPager實現(xiàn)第一次啟動引導(dǎo)頁,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • android開發(fā)實現(xiàn)列表控件滾動位置精確保存和恢復(fù)的方法(推薦)

    android開發(fā)實現(xiàn)列表控件滾動位置精確保存和恢復(fù)的方法(推薦)

    下面小編就為大家?guī)硪黄猘ndroid開發(fā)實現(xiàn)列表控件滾動位置精確保存和恢復(fù)的方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • Flutter適配深色模式的方法(DarkMode)

    Flutter適配深色模式的方法(DarkMode)

    這篇文章主要介紹了Flutter適配深色模式的方法(DarkMode),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 使用WEB工具快速提高Android開發(fā)效率

    使用WEB工具快速提高Android開發(fā)效率

    正所謂工欲善其事,必先利其器。學(xué)習(xí)并應(yīng)用優(yōu)秀的輪子,可以讓我們跑的更快,走的更遠(yuǎn)。這里所指的工具是廣義的,泛指能幫助我們開發(fā)的東西,或者能提高我們效率的東西,包括:開發(fā)工具,監(jiān)測工具,第三方代碼庫等
    2016-02-02
  • Android自定義滑動解鎖控件使用詳解

    Android自定義滑動解鎖控件使用詳解

    這篇文章主要為大家詳細(xì)介紹了Android自定義滑動解鎖控件的使用方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Android動畫工具類的封裝實戰(zhàn)記錄

    Android動畫工具類的封裝實戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于一次Android動畫工具類的封裝實戰(zhàn),文中通過示例代碼介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Android實現(xiàn)搖一搖功能

    Android實現(xiàn)搖一搖功能

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)搖一搖功能的相關(guān)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android Canvas和Bitmap結(jié)合繪圖詳解流程

    Android Canvas和Bitmap結(jié)合繪圖詳解流程

    在 Android Canvas 上繪圖非常難,在繪圖時需要理解許多不同的類和概念。這篇文章中,將介紹 Android 框架中可用的一些類,它們可以讓畫布使用時更輕松
    2021-11-11
  • Android小部件Widget開發(fā)過程中的坑和問題小結(jié)

    Android小部件Widget開發(fā)過程中的坑和問題小結(jié)

    這篇文章主要介紹了Android小部件Widget開發(fā)過程中的坑和問題小結(jié),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-09-09

最新評論