Android – 如何制作像facebook,spotify和Google +的幻灯片菜单

我想添加一个幻灯片菜单到我的应用程序,如Facebook应用程序。 我在互联网上阅读了很多有关图书馆的东西,但都没有为我工作。 什么是最好的东西/图书馆,我可以用这个,也可以有人可以解释我如何使用它?

编辑这是我的布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="@drawable/zwemfest" >" <com.devspark.sidenavigation.SideNavigationView android:id="@+id/side_navigation_view" android:layout_width="match_parent" android:layout_height="match_parent" > <Button android:id="@+id/button1" android:layout_width="183dp" android:layout_height="113dp" android:layout_weight="0.91" android:text="Button" /> </com.devspark.sidenavigation.SideNavigationView> </RelativeLayout> 

但是我没有看到任何button或背景图像。 你知道怎么回事?

那么目前我正在做一个项目,并遇到滑动菜单,我GOOGLE了,但失望的看到,没有人已经给出了一些指示或提示如何开始做一个滑动菜单,每个人已经链接到一些Github的项目/图书馆使用,因此,我决定自己做,最后我有我自己的滑动菜单准备…

我花了两天的时间

1.制作滑动animation

2.使其适用于所有屏幕分辨率

一旦你对animation有了一些想法,它真的很容易和简单,我已经阅读了一些地方,它不是重新发明轮子 (指的是滑动菜单的github源代码的人),但我相信你至less应该一旦尝试做出自己的想法,那么你就会明白它是如何工作和运作的:P

所以这是我的滑动菜单将如何工作的图片

1.Find.xml //later in the code it will be refer as findLayout

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <RelativeLayout android:id="@+id/find_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:id="@+id/header" android:layout_width="match_parent" android:layout_height="60dp" android:padding="2dp" android:background="@drawable/main_header"> <Button android:id="@+id/filter" android:layout_width="40dp" android:layout_height="30dp" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:background="@drawable/filter_button" /> <TextView android:id="@+id/city" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/filter" android:layout_marginLeft="20dp" android:layout_marginTop="3dp" android:text="Islamabad" android:textSize="22sp" android:textStyle="bold" android:textColor="@android:color/primary_text_dark"/> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/city" android:layout_alignLeft="@+id/city"> <TextView android:id="@+id/interested_in" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:text="Men and Women" android:textSize="12sp" android:textColor="@android:color/primary_text_dark"/> <ImageView android:id="@+id/separator" android:layout_width="2dp" android:layout_height="18dp" android:layout_toRightOf="@+id/interested_in" android:layout_marginLeft="4dp" android:src="@drawable/separator_1" android:layout_centerVertical="true" /> <TextView android:id="@+id/age" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="4dp" android:layout_toRightOf="@+id/separator" android:layout_centerVertical="true" android:text="18-24 years" android:textSize="12sp" android:textColor="@android:color/primary_text_dark"/> <ImageView android:id="@+id/separator_1" android:layout_width="2dp" android:layout_height="18dp" android:layout_toRightOf="@+id/age" android:layout_marginLeft="4dp" android:src="@drawable/separator_1" android:layout_centerVertical="true" /> <TextView android:id="@+id/distance" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="4dp" android:layout_toRightOf="@+id/separator_1" android:layout_centerVertical="true" android:text=">30km" android:textSize="12sp" android:textColor="@android:color/primary_text_dark"/> </RelativeLayout> </RelativeLayout> <GridView android:id="@+id/users_grid" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@+id/header" android:numColumns="4"> </GridView> </RelativeLayout> <include layout="@layout/filter"/> //here i included the filter.xml, which is on top of find.xml layout and is initially invisible </RelativeLayout> 

在这里输入图像描述

2.Filter.xml //later in code refer as FilterLayout

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/filter_layout" android:visibility="invisible" android:layout_width="260dp" android:layout_height="match_parent" android:background="@drawable/grey_bg" > <ImageView android:id="@+id/profile_pic" android:layout_width="match_parent" android:layout_height="220dp" android:src="@drawable/pic"/> <RelativeLayout android:id="@+id/header" android:layout_width="match_parent" android:layout_height="55dp" android:paddingLeft="10dp" android:paddingTop="5dp" android:layout_below="@+id/profile_pic" android:background="@drawable/light_blue_header"> <TextView android:id="@+id/name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:text="Raja Babar" android:textSize="18sp" android:textStyle="bold" android:textColor="@android:color/primary_text_dark"/> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/name" android:layout_alignLeft="@+id/name"> <TextView android:id="@+id/gender" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:text="Male" android:textSize="12sp" android:textColor="@android:color/primary_text_dark" /> <ImageView android:id="@+id/seperator" android:layout_width="2dp" android:layout_height="20dp" android:layout_toRightOf="@+id/gender" android:layout_marginLeft="5dp" android:src="@drawable/separator_1" android:layout_centerVertical="true" /> <TextView android:id="@+id/age" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/seperator" android:layout_marginLeft="5dp" android:layout_centerVertical="true" android:text="22 years" android:textSize="12sp" android:textColor="@android:color/primary_text_dark" /> </RelativeLayout> </RelativeLayout> <ScrollView android:layout_width="250dp" android:layout_height="wrap_content" android:layout_below="@+id/header" android:layout_marginTop="15dp" android:layout_centerHorizontal="true"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/filter_options" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/filter_options" android:textSize="18sp" android:textStyle="bold" android:textColor="@android:color/primary_text_light"/> <RelativeLayout android:id="@+id/interested_in_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="15dp" android:paddingRight="40dp" android:layout_below="@+id/filter_options" android:background="@drawable/interested_in_field"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:text="@string/gender" android:textSize="18sp" android:textStyle="bold" android:textColor="@android:color/primary_text_light"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:text="@string/women_men" android:textSize="18sp" android:textColor="#33b9cd" /> </RelativeLayout> <RelativeLayout android:id="@+id/age_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="15dp" android:paddingRight="40dp" android:layout_below="@+id/interested_in_layout" android:background="@drawable/age_field_1"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:text="@string/age" android:textSize="18sp" android:textStyle="bold" android:textColor="@android:color/primary_text_light"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:text="18-24 years" android:textSize="18sp" android:textColor="#33b9cd"/> </RelativeLayout> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="15dp" android:paddingRight="40dp" android:layout_below="@+id/age_layout" android:background="@drawable/distance_field"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:text="@string/distance" android:textSize="18sp" android:textStyle="bold" android:textColor="@android:color/primary_text_light"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:text=">30km" android:textSize="18sp" android:textColor="#33b9cd"/> </RelativeLayout> </RelativeLayout> </ScrollView> </RelativeLayout> 

在这里输入图像描述

find.xml中,我最初包含了不可见的filter.xml

现在FilterAnimation.java

 package matchat.helpers; import com.s3.matchat.R; import android.content.Context; import android.util.DisplayMetrics; import android.view.View; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; import android.widget.RelativeLayout; public class FilterAnimation implements AnimationListener { Context context; RelativeLayout filterLayout, otherLayout; private Animation filterSlideIn, filterSlideOut, otherSlideIn, otherSlideOut; private static int otherLayoutWidth, otherLayoutHeight; private boolean isOtherSlideOut = false; private int deviceWidth; private int margin; public FilterAnimation(Context context) { this.context = context; DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics(); deviceWidth = displayMetrics.widthPixels; // as my animation is x-axis related so i gets the device width and will use that width,so that this sliding menu will work fine in all screen resolutions } public void initializeFilterAnimations(RelativeLayout filterLayout) { this.filterLayout = filterLayout; filterSlideIn = AnimationUtils.loadAnimation(context, R.anim.filter_slide_in); filterSlideOut = AnimationUtils.loadAnimation(context, R.anim.filter_slide_out); } public void initializeOtherAnimations(RelativeLayout otherLayout) { this.otherLayout = otherLayout; otherLayoutWidth = otherLayout.getWidth(); otherLayoutHeight = otherLayout.getHeight(); otherSlideIn = AnimationUtils.loadAnimation(context, R.anim.other_slide_in); otherSlideIn.setAnimationListener(this); otherSlideOut = AnimationUtils.loadAnimation(context, R.anim.other_slide_out); otherSlideOut.setAnimationListener(this); } public void toggleSliding() { if(isOtherSlideOut) //check if findLayout is already slided out so get so animate it back to initial position { filterLayout.startAnimation(filterSlideOut); filterLayout.setVisibility(View.INVISIBLE); otherLayout.startAnimation(otherSlideIn); } else //slide findLayout Out and filterLayout In { otherLayout.startAnimation(otherSlideOut); filterLayout.setVisibility(View.VISIBLE); filterLayout.startAnimation(filterSlideIn); } } @Override public void onAnimationEnd(Animation animation) { if(isOtherSlideOut) //Now here we will actually move our view to the new position,because animations just move the pixels not the view { RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(otherLayoutWidth, otherLayoutHeight); otherLayout.setLayoutParams(params); isOtherSlideOut = false; } else { margin = (deviceWidth * 80) / 100; //here im coverting device percentage width into pixels, in my other_slide_in.xml or other_slide_out.xml you can see that i have set the android:toXDelta="80%",so it means the layout will move to 80% of the device screen,to work across all screens i have converted percentage width into pixels and then used it RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(otherLayoutWidth, otherLayoutHeight); params.leftMargin = margin; params.rightMargin = -margin; //same margin from right side (negavite) so that our layout won't get shrink otherLayout.setLayoutParams(params); isOtherSlideOut = true; dimOtherLayout(); } } @Override public void onAnimationRepeat(Animation animation) { } @Override public void onAnimationStart(Animation animation) { } private void dimOtherLayout() { AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.5f); alphaAnimation.setFillAfter(true); otherLayout.startAnimation(alphaAnimation); } } 

现在Find.java

 package main.matchat.activities; import matchat.helpers.FilterAnimation; import com.s3.matchat.R; import android.app.Activity; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.View; import android.view.ViewTreeObserver; import android.view.View.OnClickListener; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.widget.Button; import android.widget.RelativeLayout; public class Find extends Activity implements OnClickListener { RelativeLayout filterLayout, findLayout; Button btFilter; FilterAnimation filterAnimation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.find); filterLayout = (RelativeLayout)findViewById(R.id.filter_layout); findLayout = (RelativeLayout)findViewById(R.id.find_layout); btFilter = (Button)findViewById(R.id.filter); btFilter.setOnClickListener(this); filterAnimation = new FilterAnimation(this); initializeAnimations(); } private void initializeAnimations() { //Setting GlobolLayoutListener,when layout is completely set this function will get called and we can have our layout onbject with correct width & height,else if you simply try to get width/height of your layout in onCreate it will return 0 final ViewTreeObserver filterObserver = filterLayout.getViewTreeObserver(); filterObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { filterLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); int deviceWidth = displayMetrics.widthPixels; int filterLayoutWidth = (deviceWidth * 80) / 100; //here im coverting device percentage width into pixels, in my other_slide_in.xml or other_slide_out.xml you can see that i have set the android:toXDelta="80%",so it means the layout will move to 80% of the device screen,to work across all screens i have converted percentage width into pixels and then used it RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(filterLayoutWidth, RelativeLayout.LayoutParams.MATCH_PARENT); filterLayout.setLayoutParams(params);//here im setting the layout params for my filter.xml because its has width 260 dp,so work it across all screen i first make layout adjustments so that it work across all screens resolution filterAnimation.initializeFilterAnimations(filterLayout); } }); final ViewTreeObserver findObserver = findLayout.getViewTreeObserver(); findObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { findLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); filterAnimation.initializeOtherAnimations(findLayout); } }); } @Override public void onClick(View v) { int id = v.getId(); switch(id) { case R.id.filter: filterAnimation.toggleSliding(); break; } } } 

这里是animationres / anim

1.filter_slide_in.xml

 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:fromXDelta="-100%" android:toXDelta="0%" android:duration="1000" android:fillEnabled="true" /> </set> 

2.filter_slide_out.xml

 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:fromXDelta="0%" android:toXDelta="-100%" android:duration="1000"/> </set> 

3.other_slide_in.xml

 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator" > <translate android:fromXDelta="0%" android:toXDelta="-80%" android:duration="1000" android:fillEnabled="true"/> </set> 

4.other_slide_out.xml

 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/decelerate_interpolator"> <translate android:fromXDelta="0%" android:toXDelta="80%" android:duration="1000" android:fillEnabled="true"/> </set> 

在这里你可以find一个完整的工作和function滑动菜单,你可以定制它来满足你的要求,如果任何人仍然有一些设置问题,随时问,我很乐意帮助你🙂

https://github.com/johnkil/SideNavigation

这些日子我一直在使用这个库,它工作得很好。 事实上,它的使用非常简单。

您只需在菜单文件夹下声明一个side_navigation.xml:

 <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/side_navigation_menu_chart" android:icon="@drawable/icon_kitsch_gray" android:title="@string/navigation_chart"/> <item android:id="@+id/side_navigation_menu_info" android:icon="@drawable/ic_menu_info_details" android:title="@string/navigation_info"/> <item android:id="@+id/side_navigation_menu_gallery" android:icon="@drawable/ic_menu_gallery" android:title="@string/navigation_photos"/> <item android:id="@+id/side_navigation_menu_signin" android:icon="@drawable/ic_menu_login" android:title="@string/navigation_signin"/> <item android:id="@+id/side_navigation_menu_settings" android:icon="@drawable/ic_menu_preferences" android:title="@string/navigation_settings"/> </menu> 

然后,在您的活动布局中,添加导航视图:

 <com.devspark.sidenavigation.SideNavigationView android:id="@+id/side_navigation_view" android:layout_width="match_parent" android:layout_height="match_parent" /> 

而且,在你的活动中,你可以链接他们两个:

 SideNavigationView sideNavigationView = (SideNavigationView)findViewById(R.id.side_navigation_view); sideNavigationView.setMenuItems(R.menu.side_navigation); 

编辑:

要触发侧面导航面板,当用户按下ActionBar中的主页图标时,是一个很好的select。 例如:

 @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: sideNavigationView.toggleMenu(); return true; default: return super.onOptionsItemSelected(item); } } 

您也可以使用www.scringo.com 。 这是一个SDK,允许您添加这种types的侧边菜单几乎只是这段代码:

 Scringo scringo = new Scringo(); scringo.init(); 

以后可以从网站上进行很多configuration(菜单方向,颜色等),还可以在菜单中添加内置function,例如收件箱,查找/邀请朋友,雷达等。

使用正式版本。 Google在I / O 2013发布了导航抽屉模式,并更新了版本4支持库以包含此function。 🙂

http://developer.android.com/design/patterns/navigation-drawer.html

下面是我开发的一个简单的滑动菜单,在github中检查项目,实现起来很简单http://github.com/leonardosalles/shipp-sliding-menu

你可以阅读这3篇文章:

http://android.cyrilmottier.com/?p=658

http://android.cyrilmottier.com/?p=701

http://android.cyrilmottier.com/?p=717

得到一个想法:)

导航抽屉(Google+与YouTube)

幻灯片菜单技术实施

侧面导航现在包含在Android SDK中。 http://developer.android.com/design/patterns/navigation-drawer.html

在github快速search确实揭示了一个已经实现了UI模式的项目。

github上的android-fb-like-slideout-navigation还有一个video展示了工作中的库。

编辑:这是另一个图书馆项目: https : //github.com/darvds/RibbonMenu谢谢BuBBLs在评论!

更多图书馆项目:

Cyril Mottier也在他的博客中写了关于实现这种模式的文章。 这些post非常值得一读:

  1. Prix​​ing#1:Fly-in应用程序菜单的制作
  2. Prix​​ing#2的制作:轻扫飞入应用程序菜单
  3. Prix​​ing#3的制作:抛光滑动应用程序菜单

另请参阅Google Play上的Prixing应用,试用Cyril实施的侧面导航。

如果你想制作自己的滑动菜单,而不是使用其他库,为了更好地理解事情的工作方式,请阅读我的文章

在Android教程上创build自己的滑动菜单 – 第1部分

在Android教程上制作自己的滑动菜单 – 第2部分

在这里输入图像描述

要实现滑动效果,您可以移动菜单或内容视图,或两者都取决于您的愿望。

Te的想法是依靠2个方法offsetLeftAndRight()和layout()来更新视图的位置。 你还需要Scroller来促进animation

试试这个方法。 在xml中有两个相对的布局。

 CONTENT(initially gone) HEADER 

标题最初占据了所有的宽度,内容在标题的左边,但是当前被设置为可见性= GONE。

所以当单击标题或页眉布局上的任何button时发生点击

只需将您的内容布局的宽度设置为screen_width / 2(分数将取决于您的要求)。

 public void onCreate(){ RelativeLayout header=(RelativeLayout)findViewById(R.id.header); RelativeLayout content=(RelativeLayout)findViewById(R.id.content); Display display = getWindowManager().getDefaultDisplay(); int width = display.getWidth(); // deprecated int height = display.getHeight(); // deprecated //on some event content.setVisibility(View.VISIBLE); //margin(left,right,bottom,top) content.setMargin(width/3,0,0,0); //if already opened,close the door content.setVisibility(View.GONE); } 

如果你想要一些好的开放animation,在布局上使用翻译animation。
并且请确保在我的答案的顶部提到两个相对并排的初始configuration。