ActionBar
ActionBar和Fragment、Loader等一样,都是在Android3.0及后续版本新加的技术。那么ActionBar是什么呢,它的位置在Android3.0之前就是标题栏的位置。只是ActionBar除了可以显示标题和图标外,还可以显示动作按钮和自定义视图,因此也可以将ActionBar称为扩展标题栏。
ActionBar入门
①创建menu文件夹自定义menu文件
②在onCreateOptionsMenu中使用该menu文件
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.second, menu);
}
ActionBar的显示和隐藏
getSupportActionBar().show()
getSupportActionBar().hide()
ActionBar的使用
实现层级式导航
第一步:MainActivity中添加一个按钮,点击跳转到SecondActivity |
---|
第二步:SecondActivity中编写 |
---|
//判断父Activity是否为空,不为空设置导航图标显示
if (NavUtils.getParentActivityName(SecondActivity.this) != null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);//设置向左导航显示
}
第三步:AndroidManifest.xml中配置 |
---|
<activity android:name=".SecondActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
Action Provider的使用
效果如下:生成“分享”图标并在右方显示上次操作方式
1.使用系统自带的ShareActionProvider(注意导包问题)
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/share"
android:title="share"
app:showAsAction="always"
app:actionProviderClass="android.support.v7.widget.ShareActionProvider" />
</menu>
注意:这里使用的ShareActionProvider是v7包下的,并且注意前缀不是(android:)
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main,menu);
MenuItem menuItem = menu.findItem(R.id.share);
//这里使用 menuItem.getActionProvider() 程序会挂掉
//ShareActionProvider provider = (ShareActionProvider) menuItem.getActionProvider();
ShareActionProvider provider = (ShareActionProvider) MenuItemCompat.getActionProvider(menuItem);
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
//设置过滤分享列表的Intent对象
provider.setShareIntent(intent);
return true;
}
注意:如果程序挂掉,看看是不是导入成了错的android.widget.ShareActionProvider
import android.support.v4.view.MenuItemCompat;
import android.support.v7.widget.ShareActionProvider;//这里导入的包一定要和item中定义的ShareActionProvider导入的v7包一致
2.使用自定义ShareActionProvider
实现效果如下:点击图标时,进入设置页面。
①编写自定义属性的xml文件(action_provider.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="@+id/imageButton"
android:scaleType="centerInside"
android:src="@drawable/hao"
android:layout_marginRight="10dp"
//自定义背景属性
android:background="@color/background"
android:layout_width="40dp"
android:layout_height="40dp" />
</LinearLayout>
②自定义MyActionProvider继承ActionProvider,两个方法必须实现:
带参数的构造方法,传入一个Context上下文对象
重写方法onCreateActionView,在其中对布局进行操作
public class MyActionProvider extends ActionProvider {
private Context mContext;
public MyActionProvider(Context context) {
super(context);
mContext = context;
}
@Override
public View onCreateActionView() {
//加载自定义View
View view = LayoutInflater.from(mContext).inflate(R.layout.action_provider, null);
//通过我们的View找到我们的自定义控件并为它设置监听器
ImageButton imageButton = view.findViewById(R.id.imageButton);
imageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//通过意图打开系统设置页面
Intent intent = new Intent(Settings.ACTION_SETTINGS);
mContext.startActivity(intent);
}
});
return view;
}
}
③编写menu下的item(myShare.xml)
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/myShare"
android:title="share"
app:showAsAction="always"
//这里的引入是自定义ActionProvider的具体位置,具体到包名
app:actionProviderClass="com.example.actionbardemo.MyActionProvider" />
</menu>
④在MainActivity中重写onCreateOptionsMenu()方法
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.myShare, menu);
return super.onCreateOptionsMenu(menu);
}
!!!敲重点!!! |
---|
1.使用getSupportActionBar时,继承的Activity要是AppCompatActivity。在API21之前我们使用标题栏基本都是在ActionBarActivity的Activity中处理的,而API21之后,谷歌遗弃了ActionBarActivity,推荐我们也可以说是强制我们使用AppCompatActivity。
解释①:Activity和AppCompatActivity的区别,AppCompatActivity默认带标题,但Activity不带;
解释②:如果需要用兼容版的fragment,则需要继承support v4提供的FragmentActivity。如果需要使用兼容版的actionbar,则继承support v7提供的ActionBarActivity(它是继承FragmentActivity的)。
2.AppCompatActivity和 requestWindowFeature(Window.FEATURE_NO_TITLE)一起使用会发生冲突,程序会直接挂掉。应该使用兼容包的方法supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
Toolbar
一、简介
Android3.0之后,Google引入了ActionBar,想要统一安卓应用的导航栏样式。但是由于ActionBar难以定制,很大程度上限制了开发人员。较为常见的实现是使用普通的ViewGroup来封装自己的APP Bar,或者使用JakeWharton大神的ActionBarSherlock库。
自2014年Google I/O上Material Design横空出世后,市场上的应用又逐步趋向了样式的风格统一,support library中很快就出来了ToolBar控件,一个定制化的ViewGroup,来完善ActionBar的使用。
ToolBar是ActionBar的替代品,对于像我这样的菜鸟级Android开发者来说,对怎样使用ToolBar还是感到比较困惑,那今天就来学一下如何使用吧。
二、Toolbar的使用(android.support.v7.widget.Toolbar)
先说一下大致实现的效果图
2.1编写布局文件(activity_main.xml)或在Activity中编写
2.1.1 xml编写
<!--novigationIcon表示最左边的图标,logo表示第二个图标,title表示大标题,subtitle表示小标题-->
<android.support.v7.widget.Toolbar
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
app:navigationIcon="@mipmap/wechat"
app:logo="@mipmap/ic_launcher"
app:title="Toolbar"
app:subtitle="subtitle"/>
设置成系统自带的样式:
解释①android:minHeight="?attr/actionBarSize":设置标题栏最小高度为ActionBar的高度。
解释②android:background="?attr/colorPrimary":设置背景颜色
对于这些colorPrimary,colorPrimaryDark(statusBarColor默认使用该颜色)不理解的同学,这里有张图,方便大家理解Android Studio下的color.xml中设置的都是些什么。
2.1.2 Activity中编写
public class MainActivity extends AppCompatActivity {
private Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolBar);
toolbar.setNavigationIcon(R.mipmap.wechat);
toolbar.setLogo(R.mipmap.ic_launcher);
toolbar.setTitle("TitleInJava");
toolbar.setSubtitle("subtitle");
//这里特别注意,setSupportActionBar(toolbar)一定要放在setOnMenuItemClickListener之前
//不然无法响应点击事件
setSupportActionBar(toolbar);
toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {
int menuItemId = menuItem.getItemId();
switch (menuItemId) {
case R.id.search:
Toast.makeText(MainActivity.this, "search", Toast.LENGTH_SHORT).show();
break;
// ...
}
return true;
}
});
}
}
2.2 编写标题栏的item(两个图标和溢出菜单)------main.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/search"
android:icon="@drawable/search"
android:title="search"
app:showAsAction="ifRoom" />
<item
android:id="@+id/notify"
android:icon="@drawable/notify"
android:title="notify"
app:showAsAction="ifRoom" />
<item
android:id="@+id/sheZhi"
android:title="@string/sheZhi"
android:icon="@mipmap/ic_launcher"
app:showAsAction="never" />
<item
android:id="@+id/guanYu"
android:title="@string/guanYu"
android:icon="@mipmap/ic_launcher"
app:showAsAction="never" />
</menu>
1、always:使菜单项一直显示在ToolBar上。
2、ifRoom:如果有足够的空间,这个值会使菜单项显示在ToolBar上。
3、never:使菜单项永远都不出现在ToolBar上,在溢出菜单的子项中显示。
4、withText:使菜单项和它的图标,菜单文本一起显示。
2.3 在MainActivity的onCreateOptionsMenu中调用
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
基本配置都已完成,运行…结果你会发现
为什么呢?其实我们前面已经说过,AppCompatActivity是默认有标题栏的(ActionBar),你要使用Toolbar,就得替代掉原先的ActionBar。因此开始第四步…
2.4 在Theme中隐藏现有的ActionBar
方法一:在style.xml中添加以下两句
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
但是为了防止主题原因导入设置的隐藏ActionBar无效,建议再加入以下两句预防(当然也可以不添加,笔者就没有添加)
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
方法二:直接设置主题,让他本身就不带ActionBar,也就是主题样式的后缀是“.NoActionBar”。
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
方法三(推荐使用,最方便):在java代码中设置,由于我们默认继承的Acivity是AppCompatActivity,使用supportRequestWindowFeature(Window.FEATURE_NO_TITLE)。这里要注意,一定要在setContentView(R.layout.activity_main)之前设置。
再次运行。程序运行起来了,但是两个图标和溢出菜单呢???网上搜索很多,感觉都没有解释到点上。自己总结了一下,ToolBar实际上是一个ViewGroup,支持在其内部放入子View,我们只是让一个视图去覆盖ActionBar,但是他没能发挥ActionBar的作用,所以Google提供了替代ActionBar功能的方法setSupportActionBar(toolbar).
2.5 在MainActivity的onCreate方法中做替代工作
setSupportActionBar(toolbar);
大功告成!可是点击溢出菜单时,弹出的菜单覆盖住了标题,一点都不美观。
2.6 设置溢出菜单
<style name="popupTheme" parent="Theme.AppCompat.Light">
<item name="overlapAnchor">false</item>
</style>
使用该主题,在activity_main中最后添加一句app:popupTheme="@style/popupTheme"
当点击overlapAnchor时,它会自动把前缀(android:)也带上。一定要去掉,不然你会发现效果出不来。
为了让溢出菜单更加美观,我们再设置一下背景和字体颜色,颜色在color.xml里,自己定义
<item name="android:background">@color/background</item>
<item name="android:textColor">@color/textColor</item>
让溢出菜单能够带上图标,比较麻烦,要对JAVA反射机制了解,这里不讲述,可以自己上网查找。直接贴出最终效果
扩展:设置状态栏文本居中
在自定义的Toolbar中添加TextView,然后再设置TextView居中显示。这里贴出代码
<android.support.v7.widget.Toolbar
android:id="@+id/toolBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="15sp"
android:text="MyTextView"/>
</android.support.v7.widget.Toolbar>
注意:这里如果在Toolbar中定义了TextView,那么title和subtitle的设置就会失效。