DrawerLayout的使用越来越广泛,也许有的朋友说我可以做一个侧滑面板,使用ViewDragHelper来写.当然,自己写的自定义控件扩展性更好,但是DrawerLayout也能满足一般的侧滑需求了,效果如图:
首先:布局的写法:
<?xml version="1.0" encoding="utf-8"?>
<!--加上openDrawer这个属性可以预览效果-->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start"
>
<!--主页面带ToolBar的页面-->
<include layout="@layout/app_bar_main"
android:layout_height="match_parent"
android:layout_width="match_parent"
/>
<!--左边的导航条-->
<android.support.design.widget.NavigationView
android:id="@+id/navigationview"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="left"
app:headerLayout="@layout/nav_header_layout"
app:menu="@menu/nav_bottom_menu"
/>
</android.support.v4.widget.DrawerLayout>
注意:这里有一个坑, 侧边的导航条NavigationView是写在主页面的下面的(即布局是在主页面的上方的), 这样里面的条目才能获取到焦点,有点击事件
那我们就开始写主页面的布局吧:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"/>
</android.support.design.widget.AppBarLayout>
<!--
下方为一个帧布局,用于存放Fragment-->
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/fl_container"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
></FrameLayout>
</android.support.design.widget.CoordinatorLayout>
CoordinatorLayout 下包裹一个Toolbar 和一个FrameLayout ,没什么特别的
而Activity整体的布局是: 在AndroidManifesth中配置的:
<!--没有Actionbar的样式-->
<style name="AppTheme.NoActionBar">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
</style>
左边导航条的属性, 关键是android:layout_gravity="left" 和两个 headerLayout 和menu属性的书写:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="130dp"
android:background="@drawable/shape_nav_top"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:src="@mipmap/ic_launcher"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Gank"
android:textColor="#ffffff"
android:paddingTop="10dp"
android:paddingLeft="5dp"
/>
</LinearLayout>
而这里 头部的 背景使用的是shape 图, 颜色渐变:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
>
<gradient android:startColor="#ff0000"
android:endColor="#00ff00"
android:type="linear"
android:angle="0"
/>
</shape>
res下新建一个menu文件夹, 下面写group和item 的布局:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item android:icon="@drawable/ic_today_black_18dp"
android:checked="true"
android:title="今天"
android:id="@+id/nav_item_today"/>
<item android:icon="@drawable/ic_android_black_18dp"
android:title="@string/nav_txt2"
android:id="@+id/nav_item_android"/>
<item android:icon="@drawable/ic_apps_black_18dp"
android:title="@string/nav_txt3" android:id="@+id/nav_item_apple"/>
</group>
<item android:title="@string/below_title">
<menu>
<item android:title="@string/below_txt3"
android:icon="@drawable/ic_person_black_18dp"
android:id="@+id/nav_abount"/>
<item android:icon="@drawable/ic_dot"
android:title="@string/below_txt4"
android:id="@+id/nav_fankui"/>
</menu>
</item>
</menu>
这里每一个条目 左边的图片都是灰色的,如果要显示原来的颜色,则需要在代码中写:
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view);
navigationView.setItemIconTintList(null);
还有下面两个常用的API:
1.app:itemBackground="@color/colorAccent"设置每一个item的背景颜色
2.app:itemTextColor=""设置item的背景颜色
OK,如果我想在NavigationView的item之间添加上一条分隔线呢?很简单,只需要在menu中将相应的item放到一个group中,并给该group取一个id即可,代码如下:
接下来 我们看看如何处理NavigationView中的点击事件的监听
头部事件的监听:
首先,获得头部文件View headerView = navigationView.getHeaderView(0); 然后通过调用headerView中的findViewById方法来查找到头部的控件,设置点击事件即可,设计图像或者文字的点击事件
item的点击事件
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(MenuItem item) {
//在这里处理item的点击事件
return true;
}
});
最后贴上我在MainActivity中的代码:
处理了ToolBar和Fragment切换的逻辑, 有兴趣的朋友可以看看
package com.hanzheng.drawerlayout;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.widget.FrameLayout;
import android.widget.Toast;
import com.hanzheng.drawerlayout.fragment.AndroidFragment;
import com.hanzheng.drawerlayout.fragment.BaseFragment;
import com.hanzheng.drawerlayout.fragment.ToadayFragment;
import java.util.ArrayList;
import java.util.List;
import butterknife.ButterKnife;
import butterknife.InjectView;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
@InjectView(R.id.navigationview)
NavigationView mNavigationview;
@InjectView(R.id.toolbar)
Toolbar mToolbar;
@InjectView(R.id.fl_container)
FrameLayout mFlContainer;
@InjectView(R.id.drawer_layout)
DrawerLayout mDrawerLayout;
private List<BaseFragment> fragments = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
//这句话将ToolBar设置为ActionBar,并且文字显示为App名字
setSupportActionBar(mToolbar);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this,mDrawerLayout,mToolbar,R.string.open,R.string.close);
toggle.syncState();
//设置抽屉布局的监听器
mDrawerLayout.addDrawerListener(toggle); //打开或者关闭三条横线变成箭头
/** Navigationview的item的点击事件 */
mNavigationview.setNavigationItemSelectedListener(this);
fragments.add(new ToadayFragment());
fragments.add(new AndroidFragment());
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
//默认选中今天条目,则先初始化TodayFragment
ft.replace(R.id.fl_container,fragments.get(0)).commit();
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
//一定要再写个Fragment的事物,不能抽取为类的成员变量
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.hide(fragments.get(0));
ft.hide(fragments.get(1));
BaseFragment baseFragment =null;
switch (item.getItemId()) {
case R.id.nav_item_today:
//选中today条目
baseFragment = fragments.get(0);
Toast.makeText(MainActivity.this,"点击了第一个条目吗",Toast.LENGTH_SHORT).show();
break;
case R.id.nav_item_android:
baseFragment = fragments.get(1);
Toast.makeText(MainActivity.this,"点击了第二个条目吗",Toast.LENGTH_SHORT).show();
break;
}
if(!baseFragment.isAdded()) {
ft.add(R.id.fl_container,baseFragment);
}
ft.show(baseFragment).commit();
//关闭抽屉
mDrawerLayout.closeDrawer(GravityCompat.START);
return true; //消费事件
}
/**
* 重写返回键, 当抽屉是打开的时候关闭抽屉,否则则不作处理,让系统处理
*/
@Override
public void onBackPressed() {
if(mDrawerLayout.isDrawerOpen(GravityCompat.START)) {
mDrawerLayout.closeDrawer(GravityCompat.START);
}else {
super.onBackPressed();
}
}
}