最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android仿人人客戶端滑動(dòng)菜單的側(cè)滑菜單效果

 更新時(shí)間:2018年05月10日 14:22:53   作者:guolin  
這篇文章主要介紹了Android仿人人客戶端滑動(dòng)菜單的側(cè)滑特效實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,分享給大家供大家參考

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

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

雖然現(xiàn)在網(wǎng)上類似這種效果的實(shí)現(xiàn)也非常多,可是我發(fā)現(xiàn)實(shí)現(xiàn)方案大都非常復(fù)雜,并不容易理解。但其實(shí)這種效果并不難實(shí)現(xiàn),因此我今天給大家?guī)淼囊彩鞘飞献詈唵蔚幕瑒?dòng)菜單實(shí)現(xiàn)方案。

首先還是講一下實(shí)現(xiàn)原理。在一個(gè)Activity的布局中需要有兩部分,一個(gè)是菜單(menu)的布局,一個(gè)是內(nèi)容(content)的布局。兩個(gè)布局橫向排列,菜單布局在左,內(nèi)容布局在右。初始化的時(shí)候?qū)⒉藛尾季窒蜃笃疲灾劣谀軌蛲耆[藏,這樣內(nèi)容布局就會完全顯示在Activity中。然后通過監(jiān)聽手指滑動(dòng)事件,來改變菜單布局的左偏移距離,從而控制菜單布局的顯示和隱藏。

原理圖如下:



將菜單布局的左偏移值改成0時(shí)。

效果圖如下:


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

<LinearLayout xmlns: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>

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

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

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

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

之后給內(nèi)容布局注冊監(jiān)聽事件,這樣當(dāng)手指在內(nèi)容布局上滑動(dòng)的時(shí)候就會觸發(fā)onTouch事件。在onTouch事件里面,根據(jù)手指滑動(dòng)的距離會改變菜單布局的左偏移量,從而控制菜單布局的顯示和隱藏。當(dāng)手指離開屏幕的時(shí)候,會判斷應(yīng)該滑動(dòng)到菜單布局還是內(nèi)容布局,判斷依據(jù)是根據(jù)手指滑動(dòng)的距離或者滑動(dòng)的速度,細(xì)節(jié)可以看代碼中的注釋。

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

<?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> 

好了,現(xiàn)在我們運(yùn)行一下,看一下效果吧,首先是程序剛打開的時(shí)候,顯示的是內(nèi)容布局。用手指在界面向右滑動(dòng),可以看到菜單布局出現(xiàn)。

                 

而當(dāng)菜單布局完全展示的時(shí)候,效果如下圖:



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

有對雙向滑動(dòng)菜單感興趣的朋友請轉(zhuǎn)閱 Android實(shí)現(xiàn)雙向滑動(dòng)特效的實(shí)例代碼

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

源碼下載,請點(diǎn)擊這里

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

相關(guān)文章

  • Android基于OpenCV實(shí)現(xiàn)圖像修復(fù)

    Android基于OpenCV實(shí)現(xiàn)圖像修復(fù)

    實(shí)際應(yīng)用中,圖像常常容易受損,如存在污漬的鏡頭、舊照片的劃痕、人為的涂畫(比如馬賽克),亦或是圖像本身的損壞。修復(fù)圖像就成為一個(gè)常見的需求了,本文講述Android基于OpenCV實(shí)現(xiàn)圖像修復(fù)的步驟,有此需求的朋友可以參考下
    2021-06-06
  • Android手機(jī)通過藍(lán)牙連接佳博打印機(jī)的實(shí)例代碼

    Android手機(jī)通過藍(lán)牙連接佳博打印機(jī)的實(shí)例代碼

    這篇文章主要介紹了Android手機(jī)通過藍(lán)牙連接佳博打印機(jī)的實(shí)例代碼,非常不錯(cuò)具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-11-11
  • android adb實(shí)用命令小結(jié)

    android adb實(shí)用命令小結(jié)

    adb對于Android程序員來說在日常的工作中使用頻率很高,現(xiàn)將自己工作中常用的adb命令總結(jié)一下備忘,方便查詢,也供大家參考
    2017-04-04
  • Android CameraX打開攝像頭預(yù)覽教程

    Android CameraX打開攝像頭預(yù)覽教程

    大家好,本篇文章主要講的是Android CameraX打開攝像頭預(yù)覽教程,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2021-12-12
  • android 設(shè)置wallpaper的操作方法

    android 設(shè)置wallpaper的操作方法

    下面小編就為大家?guī)硪黄猘ndroid 設(shè)置wallpaper的操作方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • Android垂直切換的圓角Banner與垂直指示器相關(guān)介紹與應(yīng)用詳解

    Android垂直切換的圓角Banner與垂直指示器相關(guān)介紹與應(yīng)用詳解

    這篇文章主要介紹了Android垂直切換的圓角Banner與垂直指示器相關(guān)介紹與應(yīng)用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-10-10
  • 解決AndroidStudio無法運(yùn)行java中的mian方法問題

    解決AndroidStudio無法運(yùn)行java中的mian方法問題

    這篇文章主要介紹了解決AndroidStudio無法運(yùn)行java中的mian方法問題,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Android中Intent與Bundle的使用詳解

    Android中Intent與Bundle的使用詳解

    這篇文章主要給大家總結(jié)介紹了關(guān)于Android中傳值Intent與Bundle的關(guān)系,文中通過示例代碼以及圖文介紹的非常詳細(xì),對各位Android開發(fā)者們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧<BR>
    2022-11-11
  • Android  listView 繪制表格實(shí)例詳解

    Android listView 繪制表格實(shí)例詳解

    這篇文章主要介紹了Android listView 繪制表格實(shí)例詳解的相關(guān)資料,這里附有實(shí)例代碼及實(shí)現(xiàn)效果圖,利用listView 繪制表格提供實(shí)現(xiàn)思路,需要的朋友可以參考下
    2017-01-01
  • Android錄音并且輸出為Mp4文件的方法教程

    Android錄音并且輸出為Mp4文件的方法教程

    這篇文章主要給大家介紹了關(guān)于Android錄音并且輸出為Mp4文件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-08-08

最新評論

盈江县| 东安县| 洛隆县| 巴彦淖尔市| 库尔勒市| 宜丰县| 阿尔山市| 临沧市| 高雄县| 永城市| 哈密市| 蓝山县| 绥江县| 泰安市| 汉阴县| 班戈县| 年辖:市辖区| 清水河县| 长宁县| 龙岩市| 新和县| 洪雅县| 桐城市| 台安县| 蒙山县| 乡城县| 淮北市| 黔西县| 大同县| 黔江区| 浦东新区| 黄大仙区| 当阳市| 新乡县| 蓬溪县| 黔南| 朝阳县| 盐池县| 左权县| 义马市| 鹤山市|