转载请注明出处:http://blog.csdn.net/allen315410/article/details/39611355


在实际项目开发中,定制一个菜单,能让用户得到更好的用户体验,诚然菜单的样式各种各样,但是有一种菜单——滑动菜单,是被众多应用广泛使用的。关于这种滑动菜单的实现,我在前面的博文中也介绍了如何自定义去实现,请参考Android自定义控件——侧滑菜单,这篇博文描述的是如何从无到有创建一个侧滑菜单的控件,里面的代码不多,但是处理的逻辑和各种效果比较复杂,如果稍有不慎,这种自定义控件就要BUG不断,难以在项目中使用,而且实现的效果比较单一。

好在有开源力量的存在,在开源世界里,一切常用的实用的东西,都会有大牛帮我们做好了。所以,这种侧滑菜单不难被找到,下面就来介绍一下这个开源的侧滑菜单SlidingMenu。


一、SlidingMenu相关介绍

1,获取SlidingMenu

SlidingMenu在GitHub中可以被找到,下面是GitHub源码的地址,大家可以点进去,下载这个源码。另外,SlidingMenu这个开源组件也是基于另外一个开源组件之上的,这个开源组件是ActionBarSherlock,也需要下载下来。

SlidingMenu项目:https://github.com/jfeinstein10/SlidingMenu

ActionBarSherlock项目:https://github.com/JakeWharton/ActionBarSherlock

PS:关于SlidingMenu的作者Jeremy Feinstein和ActionBarSherlock的作者JakeWharton,都是大牛,前者还是JazzyViewPager的作者,后者更是Android-ViewPagerIndicator、NineOldAndroids、DiskLruCache等等的作者,大家可以注册一下GitHub的账号,选择Follow一下这些大牛,站在巨人的肩膀上进步。


2,导入到项目中

首先解压这个ActionBarSherlock的压缩包,找到actionbarsherlock这个包,这个工程是类库,下面打开eclipse,Import->Android->Android Project from Existing Code,导入这个actionbarsherlock。

然后解压这个SlidingMenu的压缩包,找到library,同样的方法Import->Android->Android Project from Existing Code,导入SlidingMenu的library,然后右键这个library,Properties->Android->add,选择上面导入的actionbarsherlock。

接着新建一个Android项目,在这个项目里引用SlidingMenu,同样,右键工程目录->Properties->Android->add,添加上面导入的SlidingMenu的类库library,这样,这个SlidingMenu就算是导入到了工程中了。注意,当导入这个包的时候有可能会报下面的错误:


引起这个错误的原因是ActionBarSherlock和SlidingMenu以及我们的工程里面的android-support-v4.jar这个包版本不一致,解决的办法是,将我们自己工程libs目录下的android-support-v4.jar复制黏贴到ActionBarSherlock和SlidingMenu的类库的libs目录下,选择同意覆盖,这样这个报错就消除了。


3,引用SlidingMenu

1.你可以通过new SlidingMenu(Context context)的方式把你的activity包含在一个slidingmenu里,然后调用SlidingMenu.attachToActivity(Activity activity, SlidingMenu.SLIDING_WINDOW | SlidingMenu.SLIDING_CONTENT)方法。SLIDING_WINDOW会在SlidingMenu的内容部分包含ActionBar,而SLIDING_CONTENT不会。你可以参加示例项目里的AttachExample。

2.你可以让你的activity继承SlidingActivity来在activity级别上嵌入SlidingMenu。

2.1 在你Activity的onCreate()方法里,像平常一样调用setContentView()方法,也要调用setBehindContentView()方法,它和setContentView()方法有同样的语法结构。setBehindContentView()方法会把view放置在SlidingMenu的后面。你也可以使用getSlidingMenu()方法,这样你就可以自定义你链接的slidingMenu了。

2.2 如果你想使用其它的库,例如ActionBarSherlock,你只需要改变SlidingActivity的继承关系,让它继承SherlockActivity就可以了,原来继承的是Activity。这一点尤为重要,若是在Activity中需要引用ActionBar时,必须修改当前Activity继承于SherlockActivity,不然会产生意想不到的错误。

3.你可以在Java代码里用编程来使用SlidingMenu,也可以在xml布局文件里使用。你可以把SlidingMenu当成一种其它的视图类型,并可以把它放在一些非常棒的地方,例如ListView的行里。


4,相关API介绍

1,下面是SlidingMenu在GitHub主页中的介绍,翻译过来大致的意思如下

Simple Example - 简单示例

public class SlidingExample extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.attach);
// set the content view
setContentView(R.layout.content);
// configure the SlidingMenu
SlidingMenu menu = new SlidingMenu(this);
menu.setMode(SlidingMenu.LEFT);
menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
menu.setShadowWidthRes(R.dimen.shadow_width);
menu.setShadowDrawable(R.drawable.shadow);
menu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
menu.setFadeDegree(0.35f);
menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
menu.setMenu(R.layout.menu);
}

}

XML Usage - xml用法

如果你决定要把SlidingMenu当作一个view,那你可以在xml文件里定义它:

<com.jeremyfeinstein.slidingmenu.lib.SlidingMenu
xmlns:sliding="http://schemas.android.com/apk/res-auto"
android:id="@+id/slidingmenulayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
sliding:viewAbove="@layout/YOUR_ABOVE_VIEW"
sliding:viewBehind="@layout/YOUR_BEHIND_BEHIND"
sliding:touchModeAbove="margin|fullscreen"
sliding:behindOffset="@dimen/YOUR_OFFSET"
sliding:behindWidth="@dimen/YOUR_WIDTH"
sliding:behindScrollScale="@dimen/YOUR_SCALE"
sliding:shadowDrawable="@drawable/YOUR_SHADOW"
sliding:shadowWidth="@dimen/YOUR_SHADOW_WIDTH"
sliding:fadeEnabled="true|false"
sliding:fadeDegree="float"
sliding:selectorEnabled="true|false"
sliding:selectorDrawable="@drawable/YOUR_SELECTOR"/>

注意:你不能既使用behindOffset,又使用behindWidth。如果你这样做,程序会抛出异常。
viewAbove : 你想在SlidingMenu上面使用的布局的引用
viewBehind :你想在SlidingMenu下面使用的布局的引用
touchModeAbove :一个enum,当上面的视图显示时,它指定了屏幕的哪部分是可触摸的。margin意味着只有左边缘。fullscreen意味着整个屏幕。默认是margin。
behindOffset :当后面的视图显示时,你想让它上面的view显示的像素尺寸。默认是0。
behindWidth : 后面视图宽度的尺寸。默认是屏幕的宽度(相当于behindOffset=0)。
behindScrollScale :一个浮点值,代表了上面view滚动与下面view滚动的关系。如果被设置为0.5f,上面的view每滚动2px,后面的view滚动1px。如果被设置为1.0f,上面的view每滚动1px,后面的view也滚动1px。如果被设置为0.0f,后面的view不会滚动,也就是说它是静态的。这是一个有趣的东东。默认是0.25f。
shadowDrable :指向上面视图和后面视图落差阴影的drawable的引用。默认没有阴影。
shadowWidth :代表着阴影drawable宽度的尺寸。默认为0。
shadowEnable :当SlidingMenu以非fade模式打开,在关闭时是否以fade模式关闭。
fadeDegree :一个浮点值,代表着fade的“数量”。1.0f意味着当SlidingMenu关闭时,fade会一直存在。0.0f意味着不会有fade。
selectorEnable :一个布尔值,标识了在上面view的左边是否绘制一个选择项,用于展示后面view被选择的元素。
selectorDrawable : 用于选择项drawable的引用。注意:为了使得选择项被画出来,在被选择的view上,你必须调用SlidingMenu.setSelectView(View v)方法。在ListView上,列表项极有可能不工作,因为Android会回收它们。

Caveats - 附加说明
你的布局必须基于viewgroup,不幸的是,这种做法违背了<merge>的最优化。


2,SlidingMenu类的相关方法

menu.setMode(SlidingMenu.LEFT); //设置左滑菜单
menu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); //设置滑动的屏幕范围,该设置为全屏区域都可以滑动
menu.setShadowDrawable(R.drawable.shadow); //设置阴影图片
menu.setShadowWidthRes(R.dimen.shadow_width); //设置阴影图片的宽度
menu.setBehindOffsetRes(R.dimen.slidingmenu_offset); //SlidingMenu划出时主页面显示的剩余宽度
menu.setBehindWidth(400); //设置SlidingMenu菜单的宽度
menu.setFadeDegree(0.35f); //SlidingMenu滑动时的渐变程度
menu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT); //使SlidingMenu附加在Activity上
menu.setMenu(R.layout.menu_layout); //设置menu的布局文件
menu.toggle(); //动态判断自动关闭或开启SlidingMenu
menu.showMenu(); //显示SlidingMenu
menu.showContent(); //显示内容
menu.setOnOpenListener(onOpenListener); //监听slidingmenu打开


关于关闭menu有两个监听,简单的来说,对于menu close事件,一个是when,一个是after
menu.OnClosedListener(OnClosedListener); //监听slidingmenu关闭时事件
menu.OnClosedListener(OnClosedListener); //监听slidingmenu关闭后事件


左右都可以划出SlidingMenu菜单只需要设置
menu.setMode(SlidingMenu.LEFT_RIGHT); //属性,然后设置右侧菜单的布局文件
menu.setSecondaryShadowDrawable(R.drawable.shadowright); //右侧菜单的阴影图片


================================================华丽丽的分割线========================================================


二、在项目中引用SlidingMenu

1,创建项目,导入library

首先来看看效果图吧,上图:

可以看到效果了,没错,这个Demo用的是SIidingMenu的左右都可以滑出的效果,是不是觉得还可以啊?下面,我们一步步的来,去完成这个简单的SlidingMemuDemo的工程,这个工程非常简单,但是只要实现了这个Demo之后,以后做项目的时候,可以在这个Demo上面扩展,添加不同的界面UI罢了。

首先,按照上面介绍的步骤,先将下载好的SlidingMenu包解压,找到library,在Eclipse上Import这个library。然后新建这个SlidingMenuDemo,右键选择Properties->Android->Add,添加这个library到工程下。注意:我们在这个工程里面将不会涉及使用ActionBar,所以不需要导入ActionBarSherlock的类库了。


2,菜单的布局XML

接下来,我们先定义好左右菜单的UI,由于这是一个Demo,所以我这个UI做的比较简单,就是写死的一个线性布局,而且左右菜单的布局都是一样的,就偷懒不想写过多的代码,既然只是一个Demo,那大家就不要把美观放在第一位了,着重关注这个功能实现就好了。因为左右菜单的布局都是一样的,所以在这里只贴出左边菜单的布局的XML,以供参考。在实际开发中,菜单可以多种多样的,可以放ListView、GridView等等,根据具体需要来定夺。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/menu_left_frag"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent" >

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/menu_bg"
android:orientation="vertical" >

<TextView
android:id="@+id/tab_news"
style="@style/tab_style"
android:drawableLeft="@drawable/tab_news"
android:text="新闻" />

<TextView
android:id="@+id/tab_read"
style="@style/tab_style"
android:drawableLeft="@drawable/tab_read"
android:text="订阅" />

<TextView
android:id="@+id/tab_local"
style="@style/tab_style"
android:drawableLeft="@drawable/tab_local"
android:text="本地" />

<TextView
android:id="@+id/tab_ties"
style="@style/tab_style"
android:drawableLeft="@drawable/tab_ties"
android:text="跟帖" />

<TextView
android:id="@+id/tab_pics"
style="@style/tab_style"
android:drawableLeft="@drawable/tab_pics"
android:text="图片" />

<TextView
android:id="@+id/tab_focus"
style="@style/tab_style"
android:drawableLeft="@drawable/tab_focus"
android:text="话题" />

<TextView
android:id="@+id/tab_vote"
style="@style/tab_style"
android:drawableLeft="@drawable/tab_vote"
android:text="投票" />

<TextView
android:id="@+id/tab_ugc"
style="@style/tab_style"
android:drawableLeft="@drawable/tab_ugc"
android:text="聚合阅读" />
</LinearLayout>
</ScrollView>

</FrameLayout>
布局中使用的样式:

<style name="tab_style">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:background">@drawable/tab_background</item>
<item name="android:drawablePadding">20dip</item>
<item name="android:gravity">center_vertical</item>
<item name="android:padding">10dip</item>
<item name="android:textColor">@android:color/white</item>
<item name="android:textSize">18dp</item>
<item name="android:clickable">true</item>
</style>
由于在使用SlidingMenu时,要继承SlidingFragmentActivity,查看SlidingFragmentActivity的继承体系

public class SlidingFragmentActivity extends FragmentActivity implements SlidingActivityBase

会发现SlidingFragmentActivity是继承了FragmentActivity,那么就决定着,接下来的UI界面都是使用Fragment来实现的,包括左右菜单,主页UI都是Fragment。先来看看这个左右菜单的实现,比较简单,直接上主要代码:

package com.example.slidingmenudemo;

import com.example.slidingmenudemo.fragment.BaseFragment;
import com.example.slidingmenudemo.fragment.FocusFragment;
import com.example.slidingmenudemo.fragment.LocalFragment;
import com.example.slidingmenudemo.fragment.PicsFragment;
import com.example.slidingmenudemo.fragment.ReadFragment;
import com.example.slidingmenudemo.fragment.TiesFragment;
import com.example.slidingmenudemo.fragment.UgcFragment;
import com.example.slidingmenudemo.fragment.VoteFragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;

public class LeftMenuFragment extends Fragment implements OnClickListener {

private MainActivity mAct;
private View view;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.menu_left_frag, null);
mAct = (MainActivity) getActivity();
view.findViewById(R.id.tab_news).setOnClickListener(this);
view.findViewById(R.id.tab_read).setOnClickListener(this);
view.findViewById(R.id.tab_local).setOnClickListener(this);
view.findViewById(R.id.tab_ties).setOnClickListener(this);
view.findViewById(R.id.tab_pics).setOnClickListener(this);
view.findViewById(R.id.tab_focus).setOnClickListener(this);
view.findViewById(R.id.tab_vote).setOnClickListener(this);
view.findViewById(R.id.tab_ugc).setOnClickListener(this);
return view;
}

@Override
public void onClick(View v) {
BaseFragment fragment = null;
switch (v.getId()) {
case R.id.tab_news:
fragment = new HomeFragment();
break;
case R.id.tab_read:
fragment = new ReadFragment();
break;
case R.id.tab_local:
fragment = new LocalFragment();
break;
case R.id.tab_ties:
fragment = new TiesFragment();
break;
case R.id.tab_pics:
fragment = new PicsFragment();
break;
case R.id.tab_focus:
fragment = new FocusFragment();
break;
case R.id.tab_vote:
fragment = new VoteFragment();
break;
case R.id.tab_ugc:
fragment = new UgcFragment();
break;
default:
break;
}
mAct.switchContent(fragment);
fragment = null;
}

}

3,内容Fragment的创建

由于右边菜单的主要代码跟左边菜单的代码很相似,限于篇幅,这里就不贴了,有兴趣的请点击下面的源码链接,下载源码。看源码里面可以发现,当点击菜单上某一个标签时,要将标签代表的内容放到主页上去显示,可以看出这个所谓的“内容”都是一个个的Fragment实现的,要让这些Fragment在FragmentActivity上不停的切换来达到主页内容变化的效果,下面是内容的代码段,很简单,只贴出一段了,不同的内容页不同的布局,在项目按照需求定夺,我这里是简单的处理。

1,Fragment布局XML

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

<include layout="@layout/frag_title" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="这是网易话题频道"
android:textColor="#FFFF0000"
android:textSize="22dp" />

</RelativeLayout>
2,include的标题XML

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rl_maincenter_title"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/top_bar_bg" >

<ImageButton
android:id="@+id/ib_menu_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:background="@drawable/left_menu_button" />

<TextView
android:id="@+id/tv_load_course"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:text="网易新闻"
android:textColor="@android:color/white"
android:textSize="18dp" />

<ImageButton
android:id="@+id/ib_menu_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:background="@drawable/right_menu_button" />

</RelativeLayout>
3,Fragment的抽象基类——BaseFragment
package com.example.slidingmenudemo.fragment;

import com.example.slidingmenudemo.MainActivity;
import com.example.slidingmenudemo.R;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.ImageButton;

public abstract class BaseFragment extends Fragment implements OnClickListener {
protected Context ct;
/** SlidingMenu对象 */
protected SlidingMenu sm;
public View rootView;
protected Activity MenuChangeHome;
/** 左菜单按钮 */
private ImageButton leftMenuBtn;
/** 右菜单按钮 */
private ImageButton rightMenuBtn;

@Override
public void onActivityCreated(Bundle savedInstanceState) {

super.onActivityCreated(savedInstanceState);
sm = ((MainActivity) getActivity()).getSlidingMenu();
initData(savedInstanceState);
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ct = getActivity();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = initView(inflater);
leftMenuBtn = (ImageButton) rootView.findViewById(R.id.ib_menu_left);
rightMenuBtn = (ImageButton) rootView.findViewById(R.id.ib_menu_right);
leftMenuBtn.setOnClickListener(this);
rightMenuBtn.setOnClickListener(this);
setListener();
return rootView;
}

public View getRootView() {
return rootView;
}

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()) {
case R.id.ib_menu_left: // 点击左边的按钮,左菜单收放
sm.toggle();
break;
case R.id.ib_menu_right: // 点击右边按钮,右菜单缩放
sm.showSecondaryMenu();
break;
default:
break;
}
}

/**
* 初始化UI
*
* @param inflater
* @return
*/
protected abstract View initView(LayoutInflater inflater);

/**
* 初始化数据
*
* @param savedInstanceState
*/
protected abstract void initData(Bundle savedInstanceState);

/**
* 设置监听
*/
protected abstract void setListener();

}
4,其中的一个Fragment主要代码,其实里面什么也没有

public class FocusFragment extends BaseFragment {

@Override
protected View initView(LayoutInflater inflater) {
// TODO Auto-generated method stub
return inflater.inflate(R.layout.frag_focus, null);
}

@Override
protected void initData(Bundle savedInstanceState) {
// TODO Auto-generated method stub
}

@Override
protected void setListener() {
// TODO Auto-generated method stub
}
}

4,主要代码,MainActivity

最后,来重点看一下这个MainActivity里面的代码,在这里才是构建一个侧滑菜单效果的主要代码,源代码如下,可以参考注释来看:

package com.example.slidingmenudemo;

import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu;
import com.jeremyfeinstein.slidingmenu.lib.SlidingMenu.CanvasTransformer;
import com.jeremyfeinstein.slidingmenu.lib.app.SlidingFragmentActivity;

import android.graphics.Canvas;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.animation.Interpolator;

public class MainActivity extends SlidingFragmentActivity {

/** 侧滑菜单 */
private SlidingMenu sm;
/** 左边菜单 */
private LeftMenuFragment mLeftMenu;
/** 右边菜单 */
private RightMenuFragment mRightMenu;
/** 主界面 */
private HomeFragment mHomeFragment;
/** 动画类 */
private CanvasTransformer mTransformer;
/** 保存Fragment的状态 */
private Fragment mContent;

@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
initAnimation();
sm = getSlidingMenu();
setContentView(R.layout.content_frame);
setBehindContentView(R.layout.menu_left_frag);
sm.setSecondaryMenu(R.layout.menu_right_frag);
if (savedInstanceState == null) {
mLeftMenu = new LeftMenuFragment();
mRightMenu = new RightMenuFragment();
mHomeFragment = new HomeFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.menu_left_frag, mLeftMenu, "Left").commit();
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, mHomeFragment, "Home").commit();
getSupportFragmentManager().beginTransaction().replace(R.id.menu_right_frag, mRightMenu, "Right").commit();
}
sm.setSecondaryShadowDrawable(R.drawable.rightshadow); // 设置右边菜单的阴影
sm.setShadowDrawable(R.drawable.shadow); // 设置阴影图片
sm.setShadowWidthRes(R.dimen.shadow_width); // 设置阴影图片的宽度
sm.setBehindOffsetRes(R.dimen.slidingmenu_offset); // 显示主界面的宽度
sm.setFadeDegree(0f); // SlidingMenu滑动时的渐变程度
sm.setBehindScrollScale(0f);
sm.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); // 设置滑动的屏幕范围,该设置为全屏区域都可以滑动
sm.setMode(SlidingMenu.LEFT_RIGHT); // 设置菜单同时兼具左右滑动
sm.setBehindCanvasTransformer(mTransformer); // 设置动画
}

/**
* 初始化菜单滑动的效果动画
*/
private void initAnimation() {
mTransformer = new CanvasTransformer() {
@Override
public void transformCanvas(Canvas canvas, float percentOpen) {
canvas.scale(interp.getInterpolation(percentOpen), interp.getInterpolation(percentOpen), canvas.getWidth() / 2, canvas.getHeight() / 2);
// canvas.translate(0, canvas.getHeight() * (1 -
// interp.getInterpolation(percentOpen)));
}

};
}

private static Interpolator interp = new Interpolator() {
@Override
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t + 1.0f;
}
};

/**
* 切换到主界面
*
* @param fragment
*/
public void switchContent(Fragment fragment) {
mContent = fragment;
getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).commit();
getSlidingMenu().showContent();
}

/**
* 保存Fragment的状态
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
// TODO Auto-generated method stub
super.onSaveInstanceState(outState);
getSupportFragmentManager().putFragment(outState, "Home", mContent);
}

}

上面的代码里关于Fragment使用以及Fragment的API不是这篇博文的重点,如果看不明白就先学习一下Fragment。我们关注这个菜单的实现即可,我使用的方式是Activity继承SlidingFragmentActivity,这种方式是很常见的,也很好维护,只要理解Fragment使用即可。诚然,我的这个Demo里没有使用SlidingMenu的依赖库ActionBarSherlock,是因为这个Demo已经自己定义了左右菜单导航按钮,无需使用ActionBar。


5,SlidingMenu的动画

关于代码中的初始化动画,有必要解释一下。这个初始化动画可以不设置,默认就是左右水平方向的平移,这样比较死板,但是SlidingMenu的作者考虑到了我们的担忧,很“t贴心”的为我们写好了实现菜单滑动效果动画的接口,不得不说这外国大牛想的还真细腻。

sm.setBehindCanvasTransformer(mTransformer); // 设置动画

其中mTransformer是SlidingMenu类下的内部接口CanvasTransformer对象,源码如下:

/**
* The Interface CanvasTransformer.
*/
public interface CanvasTransformer {

/**
* Transform canvas.
*
* @param canvas the canvas
* @param percentOpen the percent open
*/
public void transformCanvas(Canvas canvas, float percentOpen);
}
实现这个接口,复写这个transformCanvas方法,使用该方法中提供的Canvas对象来实现相应的动画效果。当SlidingMenu触发了setBehindCanvasTransformer(mTransformer)时,这个方法会触发SlidingMenu下的自定义View对象的dispatchDraw(Canvas canvas)方法,即每次菜单界面重绘的时候,这个动画就会被调用。关于动画的写法,我提供两个吧,实际情况得根据项目需求来定夺。

SlidingMemu的缩放动画:

/**
* 初始化菜单滑动的效果动画
*/
private void initAnimation() {
mTransformer = new CanvasTransformer() {
@Override
public void transformCanvas(Canvas canvas, float percentOpen) {
canvas.scale(interp.getInterpolation(percentOpen), interp.getInterpolation(percentOpen), canvas.getWidth() / 2, canvas.getHeight() / 2);
}

};
}

private static Interpolator interp = new Interpolator() {
@Override
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t + 1.0f;
}
};

SlidingMenu的平移动画:

/**
* 初始化菜单滑动的效果动画
*/
private void initAnimation() {
mTransformer = new CanvasTransformer() {
@Override
public void transformCanvas(Canvas canvas, float percentOpen) {
canvas.translate(0, canvas.getHeight() * (1 - interp.getInterpolation(percentOpen)));
}

};
}

private static Interpolator interp = new Interpolator() {
@Override
public float getInterpolation(float t) {
t -= 1.0f;
return t * t * t + 1.0f;
}
};
SlidingMenu的拉伸动画:

private void initAnimation() {
mTransformer = new CanvasTransformer() {
@Override
public void transformCanvas(Canvas canvas, float percentOpen) {
canvas.scale(percentOpen, 1, 0, 0);
}

};
}

6,SlidingMenu的背景

最后一点,需要注意的是,在给SlidingMenu添加了动画效果后,运行时会看见菜单的背景处是一片“白色”或者“透明色”的,这样的用户体验非常的不好,那么怎么解决呢?这个很简单的,第一个考虑到是SlidingMenu本身没有设置背景,所以我们要手动的给SlidingMenu控件设置一下背景,打开SlidingMenu的类库library,在res/layout目录下找到slidingmenumain.xml的文件,打开看见这里就简单的定义了一个SlidingMenu,其它什么都没有,此时我们就可以在这个slidingmenumain.xml的节点下设置一下drawable属性即可。

library/res/layout/slidingmenumain.xml:

<?xml version="1.0" encoding="utf-8"?>
<com.jeremyfeinstein.slidingmenu.lib.SlidingMenu
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/slidingmenumain"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

源码请在这里下载



更多相关文章

  1. Android 属性动画(Property Animation)
  2. Android使用SVG矢量图打造酷炫动画效果
  3. Android DrawerLayout 高仿QQ5.2双向侧滑菜单
  4. Button点击缩放动画效果
  5. Android Tab导航菜单栏--FragmentTabHost+Fragment实现(基础篇)
  6. android(6) 扇形菜单实现
  7. 点击或长按的Android Listview用户交互设计上下文菜单
  8. android滑动菜单SlidingMenu
  9. Android显示GIF动画完整示例(二)

随机推荐

  1. Android 一个APK文件部署产生多个应用安
  2. 优酷菜单
  3. 半透明Activity方法
  4. android 设置activity不全屏
  5. TextView的走马灯效果
  6. 国产android新机开用5件事
  7. Android 判断SD卡是否存在及容量查询
  8. 自定义Android 标题栏TitleBar布局
  9. eclipse 配置android
  10. android EditText使用指南