Android 自己实现 NavigationView [Design Support Library(1)]

<?xml version="1.0" encoding="utf-8"?>

<item

android:id=“@+id/nav_home”

android:icon=“@drawable/ic_dashboard”

android:title=“Home”/>

<item

android:id=“@+id/nav_messages”

android:icon=“@drawable/ic_event”

android:title=“Messages”/>

<item

android:id=“@+id/nav_friends”

android:icon=“@drawable/ic_headset”

android:title=“Friends”/>

<item

android:id=“@+id/nav_discussion”

android:icon=“@drawable/ic_forum”

android:title=“Discussion”/>

<item

android:icon=“@drawable/ic_dashboard”

android:title=“Sub item 1”/>

<item

android:icon=“@drawable/ic_forum”

android:title=“Sub item 2”/>

别放错文件夹哈~

布局文件写完了,基本就好了,是不是很爽~看似复杂的效果,写写布局文件就ok。

ps:默认的颜色很多是从当前的主题中提取的,比如icon的stateColor,当然你也可以通过以下属性修改部分样式:

app:itemIconTint=“”

app:itemBackground=“”

app:itemTextColor=“”

(二)Activity

最后是Activity:

package com.imooc.testandroid;

import android.os.Bundle;

import android.support.design.widget.NavigationView;

import android.support.v4.widget.DrawerLayout;

import android.support.v7.app.ActionBar;

import android.support.v7.app.ActionBarActivity;

import android.support.v7.widget.Toolbar;

import android.view.MenuItem;

public class NavigationViewActivity extends ActionBarActivity

{

private DrawerLayout mDrawerLayout;

private NavigationView mNavigationView;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_navigation_view);

mDrawerLayout = (DrawerLayout) findViewById(R.id.id_drawer_layout);

mNavigationView = (NavigationView) findViewById(R.id.id_nv_menu);

Toolbar toolbar = (Toolbar) findViewById(R.id.id_toolbar);

setSupportActionBar(toolbar);

final ActionBar ab = getSupportActionBar();

ab.setHomeAsUpIndicator(R.drawable.ic_menu);

ab.setDisplayHomeAsUpEnabled(true);

setupDrawerContent(mNavigationView);

}

private void setupDrawerContent(NavigationView navigationView)

{

navigationView.setNavigationItemSelectedListener(

new NavigationView.OnNavigationItemSelectedListener()

{

@Override

public boolean onNavigationItemSelected(MenuItem menuItem)

{

menuItem.setChecked(true);

mDrawerLayout.closeDrawers();

return true;

}

});

}

@Override

public boolean onCreateOptionsMenu(Menu menu)

{

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.menu_navigation_view, menu);

return true;

}

@Override

public boolean onOptionsItemSelected(MenuItem item)

{

if(item.getItemId() == android.R.id.home)

{

mDrawerLayout.openDrawer(GravityCompat.START);

return true ;

}

return super.onOptionsItemSelected(item);

}

}

我们在Activity里面可以通过navigationView去navigationView.setNavigationItemSelectedListener,当selected的时候,menuItem去setChecked(true)。

别忘了设置theme~

#FFF5F5F5

<activity

android:name=“.NavigationViewActivity”

android:label=“@string/title_activity_navigation_view”

android:theme=“@style/Theme.DesignDemo”>

ok,到此就搞定了~~

不过存在一个问题,此时你如果点击Sub items里面的Sub item,如果你期望当前选中应该是Sub item,你会发现不起作用。那怎么办呢?

(三)Sub Item支持Cheable

这里可以修改menu的配置文件:

<?xml version="1.0" encoding="utf-8"?>

<item

android:id=“@+id/nav_home”

android:checkable=“true”

android:icon=“@drawable/ic_dashboard”

android:title=“Home”/>

<item

android:id=“@+id/nav_messages”

android:checkable=“true”

android:icon=“@drawable/ic_event”

android:title=“Messages”/>

<item

android:id=“@+id/nav_friends”

android:checkable=“true”

android:icon=“@drawable/ic_headset”

android:title=“Friends”/>

<item

android:id=“@+id/nav_discussion”

android:checkable=“true”

android:icon=“@drawable/ic_forum”

android:title=“Discussion”/>

<item

android:checkable=“true”

android:icon=“@drawable/ic_dashboard”

android:title=“Sub item 1”/>

<item

android:checkable=“true”

android:icon=“@drawable/ic_forum”

android:title=“Sub item 2”/>

android:checkableBehavior="single"去掉,然后给每个item项添加android:checkable="true"

然后在代码中:

navigationView.setNavigationItemSelectedListener(

new NavigationView.OnNavigationItemSelectedListener()

{

private MenuItem mPreMenuItem;

@Override

public boolean onNavigationItemSelected(MenuItem menuItem)

{

if (mPreMenuItem != null) mPreMenuItem.setChecked(false);

menuItem.setChecked(true);

mDrawerLayout.closeDrawers();

mPreMenuItem = menuItem;

return true;

}

});

存一下preMenuItem,手动切换。

效果:

ok,哈其实这个还是参考链接2里面的一个评论说的~

到此用法就介绍完了有木有一点小激动 但是还有个问题,对于app,就像ActionBar最初的出现,一开始大家都欢欣鼓舞,后来发现app中多数情况下需要去定制,尼玛,是不是忽然觉得ActionBar太死板了,恶心死了(当然了现在有了ToolBar灵活度上好多了)~对于上述NavigationView可能也会存在定制上的问题,比如我希望选中的Item左边有个高亮的竖线之类的效果。那么,针对于各种需求,想要能解决各种问题,最好的方式就是说对于NavigationView的效果自己可以实现。最好,我们就来看看NavigationView自己实现有多难?

三、自己实现NavigationView效果

其实NavigationView的实现非常简单,一个ListView就可以了,甚至都不需要去自定义,简单写一个Adapter就行了~~

首先观察该图,有没有发现神奇之处,恩,你肯定发现不了,因为我们做的太像了。

其实这个图就是我通过ListView写的一个是不是和原版很像(哈~参考了源码的实现,当然像。)

接下来分析,如果说是ListView,那么Item的type肯定不止一种,那我们数一数种类:

  • 带图标和文本的

  • 仅仅是文本的 Sub Items

  • 分割线

你会说还有顶部那个,顶部是headview呀~~

这么分析完成,是不是瞬间觉得没有难度了~

(一)首先布局文件
<?xml version="1.0" encoding="utf-8"?>

<android.support.v4.widget.DrawerLayout

android:id=“@+id/id_drawer_layout”

xmlns:android=“http://schemas.android.com/apk/res/android”

xmlns:app=“http://schemas.android.com/apk/res-auto”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:fitsSystemWindows=“true”

<RelativeLayout

android:layout_width=“match_parent”

android:layout_height=“match_parent”>

<android.support.v7.widget.Toolbar

android:id=“@+id/id_toolbar”

android:layout_width=“match_parent”

android:layout_height=“?attr/actionBarSize”

android:background=“?attr/colorPrimary”

app:layout_scrollFlags=“scroll|enterAlways”

app:popupTheme=“@style/ThemeOverlay.AppCompat.Light”/>

<TextView

android:id=“@+id/id_tv_content”

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:layout_centerInParent=“true”

android:text=“HelloWorld”

android:textSize=“30sp”/>

<ListView

android:id=“@+id/id_lv_left_menu”

android:layout_width=“match_parent”

android:layout_height=“match_parent”

android:layout_gravity=“start”

android:paddingTop=“0dp”

android:background=“#ffffffff”

android:clipToPadding=“false”

android:divider=“@null”

android:listSelector=“?attr/selectableItemBackground”

/>

</android.support.v4.widget.DrawerLayout>

布局文件上:和上文对比,我们仅仅把NavigationView换成了ListView.

下面注意了,一大波代码来袭.

(二) Activity

package com.imooc.testandroid;

public class NavListViewActivity extends ActionBarActivity

{

private ListView mLvLeftMenu;

private DrawerLayout mDrawerLayout;

@Override

protected void onCreate(Bundle savedInstanceState)

{

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_nav_list_view);

mDrawerLayout = (DrawerLayout) findViewById(R.id.id_drawer_layout);

mLvLeftMenu = (ListView) findViewById(R.id.id_lv_left_menu);

Toolbar toolbar = (Toolbar) findViewById(R.id.id_toolbar);

setSupportActionBar(toolbar);

final ActionBar ab = getSupportActionBar();

ab.setHomeAsUpIndicator(R.drawable.ic_menu);

ab.setDisplayHomeAsUpEnabled(true);

setUpDrawer();

}

private void setUpDrawer()

{

LayoutInflater inflater = LayoutInflater.from(this);

mLvLeftMenu.addHeaderView(inflater.inflate(R.layout.header_just_username, mLvLeftMenu, false));

mLvLeftMenu.setAdapter(new MenuItemAdapter(this));

}

@Override

public boolean onCreateOptionsMenu(Menu menu)

{

// Inflate the menu; this adds items to the action bar if it is present.

getMenuInflater().inflate(R.menu.menu_nav_list_view, menu);

return true;

}

@Override

public boolean onOptionsItemSelected(MenuItem item)

{

// Handle action bar item clicks here. The action bar will

// automatically handle clicks on the Home/Up button, so long

// as you specify a parent activity in AndroidManifest.xml.

int id = item.getItemId();

//noinspection SimplifiableIfStatement

if (id == android.R.id.home)

{

mDrawerLayout.openDrawer(GravityCompat.START);

return true;

}

return super.onOptionsItemSelected(item);

}

}

直接看onCreate中的setUpDrawer(),可以看到我们首先去addHeadView,然后去setAdapter。

那么核心代码就是我们的Adapter了~~

(三)MenuItemAdapter

public class LvMenuItem

{

public LvMenuItem(int icon, String name)

{

this.icon = icon;

this.name = name;

if (icon == NO_ICON && TextUtils.isEmpty(name))

{

type = TYPE_SEPARATOR;

} else if (icon == NO_ICON)

{

type = TYPE_NO_ICON;

} else

{

type = TYPE_NORMAL;

}

if (type != TYPE_SEPARATOR && TextUtils.isEmpty(name))

{

throw new IllegalArgumentException(“you need set a name for a non-SEPARATOR item”);

}

L.e(type + “”);

}

public LvMenuItem(String name)

{

this(NO_ICON, name);

}

public LvMenuItem()

{

this(null);

}

private static final int NO_ICON = 0;

public static final int TYPE_NORMAL = 0;

public static final int TYPE_NO_ICON = 1;

public static final int TYPE_SEPARATOR = 2;

int type;

String name;

int icon;

}

public class MenuItemAdapter extends BaseAdapter

{

private final int mIconSize;

private LayoutInflater mInflater;

private Context mContext;

public MenuItemAdapter(Context context)

{

mInflater = LayoutInflater.from(context);

mContext = context;

mIconSize = context.getResources().getDimensionPixelSize(R.dimen.drawer_icon_size);//24dp

}

private List mItems = new ArrayList(

Arrays.asList(

new LvMenuItem(R.drawable.ic_dashboard, “Home”),

new LvMenuItem(R.drawable.ic_event, “Messages”),

new LvMenuItem(R.drawable.ic_headset, “Friends”),

new LvMenuItem(R.drawable.ic_forum, “Discussion”),

new LvMenuItem(),

new LvMenuItem(“Sub Items”),

new LvMenuItem(R.drawable.ic_dashboard, “Sub Item 1”),

new LvMenuItem(R.drawable.ic_forum, “Sub Item 2”)

));

@Override

public int getCount()

{

return mItems.size();

}

@Override

public Object getItem(int position)

{

return mItems.get(position);

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

结尾

最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

高级UI,自定义View

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

3197767515)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

结尾

最后小编想说:不论以后选择什么方向发展,目前重要的是把Android方面的技术学好,毕竟其实对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

想要拿高薪实现技术提升薪水得到质的飞跃。最快捷的方式,就是有人可以带着你一起分析,这样学习起来最为高效,所以为了大家能够顺利进阶中高级、架构师,我特地为大家准备了一套高手学习的源码和框架视频等精品Android架构师教程,保证你学了以后保证薪资上升一个台阶。

当你有了学习线路,学习哪些内容,也知道以后的路怎么走了,理论看多了总要实践的。

[外链图片转存中…(img-yz4IUjvu-1713197767516)]

高级UI,自定义View

UI这块知识是现今使用者最多的。当年火爆一时的Android入门培训,学会这小块知识就能随便找到不错的工作了。

不过很显然现在远远不够了,拒绝无休止的CV,亲自去项目实战,读源码,研究原理吧!

[外链图片转存中…(img-L2HISlk8-1713197767516)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 18
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值