国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android仿人人客戶端滑動菜單的側滑菜單效果

2019-10-22 18:11:41
字體:
來源:轉載
供稿:網友

人人客戶端有一個特效還是挺吸引人的,在主界面手指向右滑動,就可以將菜單展示出來,而主界面會被隱藏大部分,但是仍有左側的一小部分同菜單一起展示。

據說人人客戶端的這個特效是從facebook客戶端模仿來的,至于facebook是不是又從其它地方模仿來的就不得而知了。好,今天我們就一起來實現這個效果,總之我第一次看到這個特效是在人人客戶端看到的,我也就主觀性地認為我是在模仿人人客戶端的特效了。

雖然現在網上類似這種效果的實現也非常多,可是我發現實現方案大都非常復雜,并不容易理解。但其實這種效果并不難實現,因此我今天給大家帶來的也是史上最簡單的滑動菜單實現方案。

首先還是講一下實現原理。在一個Activity的布局中需要有兩部分,一個是菜單(menu)的布局,一個是內容(content)的布局。兩個布局橫向排列,菜單布局在左,內容布局在右。初始化的時候將菜單布局向左偏移,以至于能夠完全隱藏,這樣內容布局就會完全顯示在Activity中。然后通過監聽手指滑動事件,來改變菜單布局的左偏移距離,從而控制菜單布局的顯示和隱藏。

原理圖如下:

android,仿人人網,側滑特效,側滑菜單
 

將菜單布局的左偏移值改成0時。

效果圖如下:

android,仿人人網,側滑特效,側滑菜單

好,我們開始用代碼來實現。首先在Eclipse中新建一個Android項目,項目名就叫做RenRenSlideMenuDemo。然后寫一下布局文件,創建或打開layout目錄下的activity_main.xml文件,加入如下代碼:

<LinearLayout xmlns:android/212160.html">android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:orientation="horizontal"  tools:context=".MainActivity" >  <LinearLayout  android:id="@+id/menu"  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:background="@drawable/menu" >  </LinearLayout>  <LinearLayout  android:id="@+id/content"  android:layout_width="fill_parent"  android:layout_height="fill_parent"  android:background="@drawable/content" >  </LinearLayout> </LinearLayout>

這個布局文件的最外層布局是一個LinearLayout,排列方向是水平方向排列。這個LinearLayout下面嵌套了兩個子LinearLayout,分別就是菜單的布局和內容的布局。這里為了要讓布局盡量簡單,菜單布局和內容布局里面沒有加入任何控件,只是給這兩個布局各添加了一張背景圖片,這兩張背景圖片是我從人人客戶端上截下來的圖。這樣我們可以把注意力都集中在如何實現滑動菜單的效果上面,不用關心里面各種復雜的布局了。

創建或打開MainActivity,這個類仍然是程序的主Activity,也是這次demo唯一的Activity,在里面加入如下代碼:

public class MainActivity extends Activity implements OnTouchListener {   /**  * 滾動顯示和隱藏menu時,手指滑動需要達到的速度。  */  public static final int SNAP_VELOCITY = 200;   /**  * 屏幕寬度值。  */  private int screenWidth;   /**  * menu最多可以滑動到的左邊緣。值由menu布局的寬度來定,marginLeft到達此值之后,不能再減少。  */  private int leftEdge;   /**  * menu最多可以滑動到的右邊緣。值恒為0,即marginLeft到達0之后,不能增加。  */  private int rightEdge = 0;   /**  * menu完全顯示時,留給content的寬度值。  */  private int menuPadding = 80;   /**  * 主內容的布局。  */  private View content;   /**  * menu的布局。  */  private View menu;   /**  * menu布局的參數,通過此參數來更改leftMargin的值。  */  private LinearLayout.LayoutParams menuParams;   /**  * 記錄手指按下時的橫坐標。  */  private float xDown;   /**  * 記錄手指移動時的橫坐標。  */  private float xMove;   /**  * 記錄手機抬起時的橫坐標。  */  private float xUp;   /**  * menu當前是顯示還是隱藏。只有完全顯示或隱藏menu時才會更改此值,滑動過程中此值無效。  */  private boolean isMenuVisible;   /**  * 用于計算手指滑動的速度。  */  private VelocityTracker mVelocityTracker;   @Override  protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.activity_main);  initValues();  content.setOnTouchListener(this);  }   /**  * 初始化一些關鍵性數據。包括獲取屏幕的寬度,給content布局重新設置寬度,給menu布局重新設置寬度和偏移距離等。  */  private void initValues() {  WindowManager window = (WindowManager) getSystemService(Context.WINDOW_SERVICE);  screenWidth = window.getDefaultDisplay().getWidth();  content = findViewById(R.id.content);  menu = findViewById(R.id.menu);  menuParams = (LinearLayout.LayoutParams) menu.getLayoutParams();  // 將menu的寬度設置為屏幕寬度減去menuPadding  menuParams.width = screenWidth - menuPadding;  // 左邊緣的值賦值為menu寬度的負數  leftEdge = -menuParams.width;  // menu的leftMargin設置為左邊緣的值,這樣初始化時menu就變為不可見  menuParams.leftMargin = leftEdge;  // 將content的寬度設置為屏幕寬度  content.getLayoutParams().width = screenWidth;  }   @Override  public boolean onTouch(View v, MotionEvent event) {  createVelocityTracker(event);  switch (event.getAction()) {  case MotionEvent.ACTION_DOWN:  // 手指按下時,記錄按下時的橫坐標  xDown = event.getRawX();  break;  case MotionEvent.ACTION_MOVE:  // 手指移動時,對比按下時的橫坐標,計算出移動的距離,來調整menu的leftMargin值,從而顯示和隱藏menu  xMove = event.getRawX();  int distanceX = (int) (xMove - xDown);  if (isMenuVisible) {  menuParams.leftMargin = distanceX;  } else {  menuParams.leftMargin = leftEdge + distanceX;  }  if (menuParams.leftMargin < leftEdge) {  menuParams.leftMargin = leftEdge;  } else if (menuParams.leftMargin > rightEdge) {  menuParams.leftMargin = rightEdge;  }  menu.setLayoutParams(menuParams);  break;  case MotionEvent.ACTION_UP:  // 手指抬起時,進行判斷當前手勢的意圖,從而決定是滾動到menu界面,還是滾動到content界面  xUp = event.getRawX();  if (wantToShowMenu()) {  if (shouldScrollToMenu()) {  scrollToMenu();  } else {  scrollToContent();  }  } else if (wantToShowContent()) {  if (shouldScrollToContent()) {  scrollToContent();  } else {  scrollToMenu();  }  }  recycleVelocityTracker();  break;  }  return true;  }   /**  * 判斷當前手勢的意圖是不是想顯示content。如果手指移動的距離是負數,且當前menu是可見的,則認為當前手勢是想要顯示content。  *  * @return 當前手勢想顯示content返回true,否則返回false。  */  private boolean wantToShowContent() {  return xUp - xDown < 0 && isMenuVisible;  }   /**  * 判斷當前手勢的意圖是不是想顯示menu。如果手指移動的距離是正數,且當前menu是不可見的,則認為當前手勢是想要顯示menu。  *  * @return 當前手勢想顯示menu返回true,否則返回false。  */  private boolean wantToShowMenu() {  return xUp - xDown > 0 && !isMenuVisible;  }   /**  * 判斷是否應該滾動將menu展示出來。如果手指移動距離大于屏幕的1/2,或者手指移動速度大于SNAP_VELOCITY,  * 就認為應該滾動將menu展示出來。  *  * @return 如果應該滾動將menu展示出來返回true,否則返回false。  */  private boolean shouldScrollToMenu() {  return xUp - xDown > screenWidth / 2 || getScrollVelocity() > SNAP_VELOCITY;  }   /**  * 判斷是否應該滾動將content展示出來。如果手指移動距離加上menuPadding大于屏幕的1/2,  * 或者手指移動速度大于SNAP_VELOCITY, 就認為應該滾動將content展示出來。  *  * @return 如果應該滾動將content展示出來返回true,否則返回false。  */  private boolean shouldScrollToContent() {  return xDown - xUp + menuPadding > screenWidth / 2 || getScrollVelocity() > SNAP_VELOCITY;  }   /**  * 將屏幕滾動到menu界面,滾動速度設定為30.  */  private void scrollToMenu() {  new ScrollTask().execute(30);  }   /**  * 將屏幕滾動到content界面,滾動速度設定為-30.  */  private void scrollToContent() {  new ScrollTask().execute(-30);  }   /**  * 創建VelocityTracker對象,并將觸摸content界面的滑動事件加入到VelocityTracker當中。  *  * @param event  * content界面的滑動事件  */  private void createVelocityTracker(MotionEvent event) {  if (mVelocityTracker == null) {  mVelocityTracker = VelocityTracker.obtain();  }  mVelocityTracker.addMovement(event);  }   /**  * 獲取手指在content界面滑動的速度。  *  * @return 滑動速度,以每秒鐘移動了多少像素值為單位。  */  private int getScrollVelocity() {  mVelocityTracker.computeCurrentVelocity(1000);  int velocity = (int) mVelocityTracker.getXVelocity();  return Math.abs(velocity);  }   /**  * 回收VelocityTracker對象。  */  private void recycleVelocityTracker() {  mVelocityTracker.recycle();  mVelocityTracker = null;  }   class ScrollTask extends AsyncTask<Integer, Integer, Integer> {   @Override  protected Integer doInBackground(Integer... speed) {  int leftMargin = menuParams.leftMargin;  // 根據傳入的速度來滾動界面,當滾動到達左邊界或右邊界時,跳出循環。  while (true) {  leftMargin = leftMargin + speed[0];  if (leftMargin > rightEdge) {  leftMargin = rightEdge;  break;  }  if (leftMargin < leftEdge) {  leftMargin = leftEdge;  break;  }  publishProgress(leftMargin);  // 為了要有滾動效果產生,每次循環使線程睡眠20毫秒,這樣肉眼才能夠看到滾動動畫。  sleep(20);  }  if (speed[0] > 0) {  isMenuVisible = true;  } else {  isMenuVisible = false;  }  return leftMargin;  }   @Override  protected void onProgressUpdate(Integer... leftMargin) {  menuParams.leftMargin = leftMargin[0];  menu.setLayoutParams(menuParams);  }   @Override  protected void onPostExecute(Integer leftMargin) {  menuParams.leftMargin = leftMargin;  menu.setLayoutParams(menuParams);  }  }   /**  * 使當前線程睡眠指定的毫秒數。  *  * @param millis  * 指定當前線程睡眠多久,以毫秒為單位  */  private void sleep(long millis) {  try {  Thread.sleep(millis);  } catch (InterruptedException e) {  e.printStackTrace();  }  } } 

全部的代碼都在這里了,我們可以看到,加上注釋總共才兩百多行的代碼就能實現滑動菜單的特效。下面我來對以上代碼解釋一下,首先初始化的時候調用initValues方法,在這里面將內容布局的寬度設定為屏幕的寬度,菜單布局的寬度設定為屏幕的寬度減去menuPadding值,這樣可以保證在菜單布局展示的時候,仍有一部分內容布局可以看到。如果不在初始化的時候重定義兩個布局寬度,就會按照layout文件里面聲明的一樣,兩個布局都是fill_parent,這樣就無法實現滑動菜單的效果了。然后將菜單布局的左偏移量設置為負的菜單布局的寬度,這樣菜單布局就會被完全隱藏,只有內容布局會顯示在界面上。

之后給內容布局注冊監聽事件,這樣當手指在內容布局上滑動的時候就會觸發onTouch事件。在onTouch事件里面,根據手指滑動的距離會改變菜單布局的左偏移量,從而控制菜單布局的顯示和隱藏。當手指離開屏幕的時候,會判斷應該滑動到菜單布局還是內容布局,判斷依據是根據手指滑動的距離或者滑動的速度,細節可以看代碼中的注釋。

最后還是給出AndroidManifest.xml的代碼,都是自動生成的,非常簡單:

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"  package="com.example.renrenslidemenudemo"  android:versionCode="1"  android:versionName="1.0" >  <uses-sdk  android:minSdkVersion="8"  android:targetSdkVersion="8" />  <application  android:allowBackup="true"  android:icon="@drawable/ic_launcher"  android:label="@string/app_name"  android:theme="@android:style/Theme.NoTitleBar" >  <activity  android:name="com.example.renrenslidemenudemo.MainActivity"  android:label="@string/app_name" >  <intent-filter>  <action android:name="android.intent.action.MAIN" />  <category android:name="android.intent.category.LAUNCHER" />  </intent-filter>  </activity>  </application> </manifest> 

好了,現在我們運行一下,看一下效果吧,首先是程序剛打開的時候,顯示的是內容布局。用手指在界面向右滑動,可以看到菜單布局出現。

android,仿人人網,側滑特效,側滑菜單                 android,仿人人網,側滑特效,側滑菜單
 

而當菜單布局完全展示的時候,效果如下圖:

android,仿人人網,側滑特效,側滑菜單
 

今天大家看到了史上最簡單的滑動菜單實現方案,確實是非常簡單。那么有朋友也許會問了,在一個Activity當中這樣實現滑動菜單是很簡單,可是如果我的應用程序有好多個Activity都需要滑動菜單,每個Activity里都這么實現一遍,也變得復雜了。沒錯,當前的這個解決方案只適用于單個Activity中,如果是想在多個Activity中都實現滑動菜單的效果,請參考我的另一篇文章 Android實現滑動菜單特效的完全解析。

有對雙向滑動菜單感興趣的朋友請轉閱 Android實現雙向滑動特效的實例代碼。

好了,今天的講解到此結束,有疑問的朋友可以在下面留言。

源碼下載,請點擊這里

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 洛南县| 无极县| 江口县| 娱乐| 大同县| 五台县| 西安市| 唐海县| 三亚市| 卓尼县| 天长市| 鲁山县| 公安县| 全南县| 青阳县| 张北县| 南华县| 牙克石市| 习水县| 淮滨县| 蒙阴县| 西乡县| 林口县| 新丰县| 彩票| 通辽市| 军事| 临西县| 松原市| 溧阳市| 舒城县| 漠河县| 黔西县| 栖霞市| 镇沅| 吉首市| 宜兰市| 锡林浩特市| 酒泉市| 运城市| 河曲县|