推荐资源站:https://zhimalier.com/
原创文章,转载请注明 ( 来自:http://blog.csdn.net/leejizhou/article/details/52013343 李济洲的博客 )
滑动导航菜单一直都是移动App中比较流行的UI设计,随着Material Design的盛行Android也越来越多采用这种设计,当然这种滑动菜单样式也是各种各样五花八门,这篇文章就来总结下如何利用Android Api去快速构建各种类型的滑动导航菜单效果。
1.先看第一种样式,这也是QQ客户端V6版本的滑动菜单样式
快速实现这个UI效果需要利用V4包的SlidingPaneLayout控件,这是一个帮助开发者实现水平的多层滑动的Layout,继承自ViewGroup。
代码还是很简单的,最外层是SlidingPaneLayout这个容器控件,里面放了两个子布局,第一个用来放置导航菜单布局,第二个放置主视图布局。
Java代码
SlidingPaneLayout 一些主要方法
- setParallaxDistance(int parallaxBy) 设置滑动视差
- setCoveredFadeColor(int color) 导航菜单视图的滑动颜色渐变
- setSliderFadeColor(int color) 主视图的滑动颜色渐变
- setPanelSlideListener(SlidingPaneLayout.PanelSlideListener listener) 滑动监听
- openPane() 打开导航菜单
- closePane() 关闭导航菜单
- https://developer.android.com/reference/android/support/v4/widget/SlidingPaneLayout.html
/**
* SlidingPaneLayout Sample
*/
public class SlidingPaneLayoutActivity extends AppCompatActivity {
private SlidingPaneLayout mSlidingPane;
private LinearLayout ll_menu,ll_main;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_slidingpane);
mSlidingPane= (SlidingPaneLayout) findViewById(R.id.SlidingPane);
ll_menu=(LinearLayout)findViewById(R.id.ll_menu);
ll_main=(LinearLayout)findViewById(R.id.ll_main);
setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
//设置滑动视差 可选
mSlidingPane.setParallaxDistance(200);
//菜单滑动的颜色渐变设置 可选
//mSlidingPane.setCoveredFadeColor(getResources().getColor(R.color.colorAccent));
//主视图滑动的颜色渐变设置 可选
mSlidingPane.setSliderFadeColor(0);
//滑动监听 可选
mSlidingPane.setPanelSlideListener(new SlidingPaneLayout.PanelSlideListener() {
@Override
public void onPanelSlide(View panel, float slideOffset) {
// slideOffset这个参数 是跟随滑动0-1变化的 通过这个数值变化我们可以做出一些不一样的滑动效果
//ll_menu.setScaleY(slideOffset / 2 + 0.5F);
//ll_menu.setScaleX(slideOffset/ 2 + 0.5F);
//ll_main.setScaleY(1 - slideOffset / 5);
}
@Override
public void onPanelOpened(View panel) {
Log.i("mylog","slide --- open");
}
@Override
public void onPanelClosed(View panel) {
Log.i("mylog","slide --- close");
}
});
}
}
OK,这样就实现了滑动导航的效果,注意在滑动监听中的这个方法里面,跟据slideOffset参数0~1的变化可以去改变视图大小就会做出更多种类的效果,这里我们设置滑动过程中改变主视图的大小,代码如下
public void onPanelSlide(View panel, float slideOffset) {
Log.i("mylog","slide --- "+slideOffset);
// slideOffset这个参数 是跟随滑动0-1变化的 通过这个数值变化我们可以做出一些不一样的滑动效果
ll_menu.setScaleY(slideOffset / 2 + 0.5F);
ll_menu.setScaleX(slideOffset/ 2 + 0.5F);
ll_main.setScaleY(1 - slideOffset / 5);
}
运行效果(下左图)
2.下面介绍第二种滑动导航菜单的效果,主视图不动,然后在边缘划出菜单。(上右图)
快速实现这个效果需要利用V4包的DrawerLayout 这个布局容器,可见V4包下面有多少好东西,另外其实SlidingPaneLayout和这个DrawerLayout都是利用V4的ViewDragHelper去实现的,这是一个帮助类,这里就不多做介绍了,对它感兴趣的可以深入了解下。
需要注意的是主视图的布局代码要放在侧滑菜单布局的前面,侧滑菜单布局的代码中android:layout_gravity=”start” 从左侧滑动,反之end右侧滑动。
Java代码
DrawerLayout 的一些主要方法
addDrawerListener(DrawerLayout.DrawerListener listener) 添加滑动监听
openDrawer(int gravity) 开启导航菜单 参数:GravityCompat.START GravityCompat.END 要跟XML设置相同
closeDrawer(int gravity) 关闭导航菜单
isDrawerOpen(int drawerGravity) 菜单是否开启
https://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html
/**
* DrawerLayout Sample
*/
public class DrawerLayoutActivity extends AppCompatActivity {
private DrawerLayout drawerLayout;
private Toolbar toolbar;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drawerlayout);
setSupportActionBar(toolbar=(Toolbar) findViewById(R.id.toolbar));
drawerLayout=(DrawerLayout)findViewById(R.id.dl_left);
//ActionBarDrawerToggle是DrawerLayout.DrawerListener的实现,可以方便的将drawlayout和actionbar结合起来
ActionBarDrawerToggle actionBarDrawerToggle=
new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.open,R.string.close){
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
}
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
}
};
actionBarDrawerToggle.syncState();
drawerLayout.addDrawerListener(actionBarDrawerToggle);
}
}
DrawerLayout跟ActionBarDrawerToggle配合快速就可以快速构建出具有动画交互的滑动导航菜单效果,是不是很简单。
总结“当下”如何按照Android的设计标准去设计滑动导航菜单,我为什么说的“当下”呢?因为这个设计标准是会变的。
在material design之前,官方对滑动导航菜单的设计标准是这样的。
*图片来自http://www.androiduipatterns.com/2014/10/navigation-drawer-where-does-it-belong.html
滑动导航菜单需要在Actionbar(Toolbar)下面,这在Android 4.X时代是比较常见的设计,也是当时的Android Design标准设计。
随着时间的推移,到了android 5.0时代,google带来了material design,新的设计风格变化比较大, 当然滑动导航菜单的设计标准也跟着改变了,下面是最新官方的滑动导航菜单设计文档。
在新的标准化设计当中,滑动导航菜单一跃来到了所有界面的顶端,这跟之前的设计是截然不同的。
新的滑动导航菜单结构介绍完,再看一下官方设计标准的排版样式
图片看着可能有些小,官网地址:https://material.google.com/patterns/navigation-drawer.html#navigation-drawer-specs
当你看到这个精确到像素级的设计标准的时候,相信你也要气的关网页了吧,还好Android给我提供了一个叫NavigationView这个布局容器,我们可以很快的实现标准设计的滑动导航菜单栏,这也是NavigationView的最主要的用途,当出现新技术的时候,我们不仅仅需要会使用,还要去了解为什么使用它。
当然NavigationView如何使用已经遍地都是了,为了文章的完整性我还是放一些主要的实现代码吧。
NavigationView是和DrawLayout配合使用的,把上一章介绍的DrawLayout使用示例中的菜单布局换成NavigationView就OK了。
下面是实现步骤
1 因为NavigationView在Design库中,需要添加依赖
compile 'com.android.support:design:24.0.0'
2 在DrawLayout中添加NavigationView
因为属于DrawLayout的导航菜单布局,所以NavigationView要加上android:layout_gravity=”start”代表从左面滑动,反之是“end”。 其中的app:headerLayout=”@layout/nv_header” 需要传入一个导航菜单的头部布局,它的作用如图绿框部分。
app:menu=”@menu/main_drawer”用于设置导航菜单中的菜单部分,如图绿框中。
3 最后是java中代码实现
/**
* NavigationView Sample
*/
public class NavigationViewActivity extends AppCompatActivity {
private DrawerLayout drawerLayout;
private Toolbar toolbar;
private NavigationView navigationView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navigationview);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
//透明状态栏
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
setSupportActionBar(toolbar=(Toolbar)findViewById(R.id.toolbar));
drawerLayout=(DrawerLayout)findViewById(R.id.drawerlayout);
navigationView = (NavigationView) findViewById(R.id.navigationView);
ActionBarDrawerToggle actionBarDrawerToggle=
new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.open,R.string.close);
actionBarDrawerToggle.syncState();
drawerLayout.addDrawerListener(actionBarDrawerToggle);
// navigationView menu点击监听
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem menuItem) {
selectDrawerItem(menuItem);
return true;
}
});
}
public void selectDrawerItem(MenuItem menuItem){
switch (menuItem.getItemId()) {
// ...
default:
Toast.makeText(NavigationViewActivity.this,"menu click",Toast.LENGTH_SHORT).show();
break;
}
menuItem.setChecked(true);
drawerLayout.closeDrawers();
}
}
其中下面代码和布局代码中的android:fitsSystemWindows=”true”起到一个半透明状态栏的作用,半透明状态栏(非叫沉浸)效果有各种实现方式,google也没能给一个好的实现方式,后续可能会考虑写一个全面的了解透明状态效果的文章,这里就不多做介绍了。
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); //透明状态栏
}
源代码下载地址:https://github.com/lijizhou/SlidingLayoutSample