封面画师:KNYT 封面ID:73718817
Android应用的资源
定义资源文件时注意标签首字母小写!
定义资源文件时注意标签首字母小写!
定义资源文件时注意标签首字母小写!
字符串资源
字符串资源的使用
- 定义字符串资源文件
<string>
- 使用字符串资源 (在XML文件中、在Java文件中)
在Java文件中使用字符串资源我们也称其为:动态设置。
AS在创建项目时,默认给我们创建了字符串资源文件。文件位置:res/values/string.xml
在XML文件中使用字符串资源:
首先在string.xml文件中新建资源:
注意:标签<string></string>
中首字母是小写!!!
1
| <string name="motto">当你有使命,它会让你更专注</string>
|
activity_main.xml:
1 2 3 4 5 6 7 8 9 10 11
| <RelativeLayout android:paddingStart="16dp" android:paddingTop="16dp" android:paddingEnd="16dp" android:paddingBottom="16dp"> <TextView android:id="@+id/mooto" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/motto" /> </RelativeLayout>
|
在Java文件中使用字符串资源:
在使用前我们需要把上一步XML文件中设置的引用清空,即:删除@string/motto
MainActivity.java:
1 2 3 4 5 6 7 8 9
| public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = findViewById(R.id.mooto); textView.setText(getResources().getString(R.string.motto)); } }
|
颜色资源
颜色值:
Android中,颜色值是由 透明度 加 红绿蓝三原色的值 来表示的。
格式: # + 透明度 + RGB
透明度由0到F的十六进制数表示,也可以使用00到FF的两位十六进制表示,其中0或00表示完全透明,F或FF表示完全不透明。透明度在书写时也可以省略,默认表示完全不透明。
RGB由0到F的十六进制数表示,也可以使用00到FF的两位十六进制表示。
在实际操作中我们一般使用拾色器获取颜色代码。
定义颜色资源文件
- 定义颜色资源文件
<color>
- 使用颜色资源(在XML文件中、在Java文件中)
AS在创建项目时,默认给我们创建了字符串资源文件。文件位置:res/values/colors.xml
在XML文件中使用颜色资源:
首先在colors.xml文件中新建资源:
注意:标签<color></color>
中首字母是小写!!!
1 2
| <color name="bg">#660000FF</color> <color name="title">#FF6600</color>
|
activity_main.xml:
1 2 3 4 5 6 7 8
| <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" android:background="@color/bg" android:textColor="@color/title" android:textSize="25dp"/>
|
在Java文件中使用颜色资源:
在使用前我们需要把上一步XML文件中设置的引用清空,即:删除@color/bg
和@color/title
MainActivity.java:
1 2 3 4 5 6 7 8 9 10
| public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = findViewById(R.id.title); textView.setTextColor(getColor(R.color.title)); textView.setBackgroundColor(getColor(R.color.bg)); } }
|
在设置文字颜色时,需要我们修改build.gradle文件:将最小sdk版本更改至23。
尺寸资源
常用尺寸单位:dp、sp
dp:设备独立像素。根据设备屏幕大小自适应。常用于边距、组件大小的设置。
sp:可伸缩像素。设置字体大小的单位。根据用户手机字体大小首选项进行缩放。
尺寸资源的使用
- 定义尺寸资源文件
<dimen>
- 使用尺寸资源 (在XML文件中、在Java文件中)
AS在创建项目时,不会默认给我们创建了字符串资源文件。
需要我们手动创建,文件位置为:res/values/dimens.xml
在XML文件中使用尺寸资源:
首先在dimens.xml文件中新建资源:
注意:标签<dimen></dimen>
中首字母是小写!!!
1 2 3 4
| <resources> <dimen name="title">26sp</dimen> <dimen name="padding">30dp</dimen> </resources>
|
activity_main.xml:
1 2 3 4 5 6 7
| <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" android:textSize="@dimen/title" android:padding="@dimen/padding"/>
|
在Java文件中使用尺寸资源:
在使用前我们需要把上一步XML文件中设置的引用清空,即:删除@dimen/title
在Java文件中,我们只进行设置字体大小,边距建议在XML文件中进行设置,简单方便。
MainActivity.java:
1 2 3 4 5 6 7 8 9
| public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = findViewById(R.id.title); textView.setTextSize(getResources().getDimension(R.dimen.title)); } }
|
布局资源
布局资源位置:res/layout/**.xml
我们经常设置布局的XML文件就是布局资源文件,如:activity_main.xml
我们在Java文件中使用布局资源,通常是用:
1
| setContentView(R.layout.activity_main);
|
在XML文件中使用布局资源文件:
假设我们已经在layout目录下创建了一个布局资源文件image.xml,这时候我们想要在activity_main.xml中使用image.xml文件,那么可以使用:
1
| <include layout="@layout/image" ></include>
|
数组资源
数组定义:数组是具有一组相同类型的一组数据的集合。
在Android中不推荐在Java程序中使用数组,而是建议使用数组资源文件。
使用数组
- 定义数组资源文件
- 使用尺寸资源 (在XML文件中、在Java文件中)
AS在创建项目时,不会默认给我们创建了数组资源文件。
需要我们手动创建,文件位置为:res/values/array.xml。
<resources>
标签内子元素有:
子元素名 |
作用 |
<array> |
定义普通类型数组。颜色、字符串、尺寸资源 |
<integer-array> |
定义整型数组。可以是十进制、十六进制等 |
<string-array> |
定义字符串数组。 |
在XML文件中使用尺寸资源:
使用场景:为下拉列表框或列表视图指定要显示的数据。
首先在array.xml文件中新建资源:
注意:标签<string-array></string-array>
中首字母是小写!!!
1 2 3 4 5 6 7
| <resources> <string-array name="listitem"> <item>活着就是为了改变世界,难道还有其他原因吗?</item> <item>尝试很重要</item> <item>求知若饥,虚心若愚</item> </string-array> </resources>
|
activity_main.xml:
1 2 3 4 5
| <ListView android:layout_width="wrap_content" android:layout_height="wrap_content" android:entries="@array/listitem" android:id="@+id/listView"/>
|
在Java文件中使用尺寸资源:
在使用前我们需要把上一步XML文件中设置的引用清空,即:删除@array/listitem
**只有通过Adapter 才可以把列表中的数据映射到ListView 中。**所以,我们在此需要使用适配器,我们选择ArrayAdapter
。
MainActivity.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String[] arr = getResources().getStringArray(R.array.listitem); ListView listView = findViewById(R.id.listView);
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,arr); listView.setAdapter(adapter); } }
|
Drawable资源
我们不仅可以使用图片作为资源,还可以使用多种XML作为资源。只要这个XML文件可以被系统编译成Drawable子类的对象,那么这个XML文件就可以作为Drawable资源。
Drawable资源被保存在res/drawable目录下。AS在创建项目时,会自动给我们创建drawable文件夹。
为了适应不同分辨率,我们一般会在res目录下手动创建以下目录:drawable-hdpi、drawable-mdpi、drawable-xhdpi、drawable-xxhdpi、drawable-xxxhdpi。
Drawable资源一般分成两大类:图片资源和StateListDrawable资源。
图片资源
后缀名可以为:.png
、.jpg
、.gif
、.9.png
.9.png
9-Patch图片文件的后缀名,这种图片不可以通过PS或画图工具来制作。
我们可以通过 在AS中右击目标png图片,选择create 9-patch file… 即可,具体绘制步骤可参考界面提示。
9-Patch图片特性:
9-Patch图片与普通图片不同,使用9-Patch图片作为屏幕或按钮的背景时,当屏幕的尺寸或按钮的大小改变时,图片可自动缩放,达到不失真的效果。
Android中不允许图片资源的文件中出现大写字母,且不能以数字开头。
Android中不允许图片资源的文件中出现大写字母,且不能以数字开头。
Android中不允许图片资源的文件中出现大写字母,且不能以数字开头。
使用方法与普通图片一样。
StateListDrawable资源
StateListDrawable资源:定义在XML文件中的Drawable对象,根据状态呈现不同的图像。
<selector>
子标签<item>
属性及其含义:
属性名 |
含义 |
android:state_pressed |
是否处于按下状态 |
android:state_focused |
是否处于聚焦状态 |
android:state_selected |
是否处于选中状态 |
android:state_checkable |
是否处于可勾选状态 |
android:state_checked |
是否处于勾选状态 |
android:state_enabled |
是否处于可用状态 |
android:window_focused |
当前程序窗口是否有焦点 |
注意:StateList中第一个匹配当前状态的item会被使用。因此,如果第一个item没有任何状态特性的话,那么它将每次都被使用,这也是为什么默认的值必须总是在最后。
实例:根据编辑框的焦点状态改变字体颜色
在res/drawable目录下,创建StateListDrawable资源文件edittext_focused.xml:
1 2 3 4 5 6
| <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_focused="true" android:color ="#f60" /> <item android:state_focused="false" android:color="#0a0"/> </selector>
|
activity_main.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <EditText android:id="@+id/editText" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@drawable/edittext_focused" android:text="活着就是为了改变世界" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:text="当你有使命,它会让你更专注" android:textColor="@drawable/edittext_focused" android:layout_below="@+id/editText" android:layout_alignParentLeft="true" android:layout_alignParentStart="true"/>
|
mipmap资源
AS在创建项目时,会自动给我们创建mipmap文件夹。这个文件夹就是用来存放mipmap资源文件的。
mipmap资源通常是APP的启动图标,我们把图标文件放在mipmap目录下,不仅可以提高系统渲染图片的速度,还可以图片的质量。
与drawable目录一样,mipmap目录也拥有相同的目录结构。比如mipmap目录下也有mipmap-hdpi、mipmap-mdpi,mipmap-xhdpi等目录。
mipmap资源的使用
在XML文件中使用:
我们在这使用系统默认的图标。
1 2 3 4 5
| <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@mipmap/ic_launcher" android:id="@+id/imageView"/>
|
在Java文件中使用:(一般不推荐这种方式)
在使用前我们需要把上一步XML文件中设置的引用清空,即:删除@mipmap/ic_launcher
1 2 3 4 5 6
| protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ImageView imageView = findViewById(R.id.imageView); imageView.setImageResource(R.mipmap.ic_launcher); }
|
mipmap和drawable的区别
mipmap:存放应用程序图标
drawable:可以存放图像文件、9-Patch、Shape、StateListDrawable等。
主题资源
作用:设置窗口整体样式,改变窗口外观。
在AS中我们可以切换系统自带的主题资源,在主题资源中还可以找到不显示ActionBar的主题资源。
除了使用系统自带的主题资源,我们还可以自定义主题资源。
AS在创建项目时,默认给我们创建了主题资源文件。文件位置:res/values/styles.xml
自定义主题资源文件
准备:我们需要准备一张主题背景图片,命名为image,放置于res/drawable-v24目录下。
编写主题资源文件,在res/values/styles.xml中进行编写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <resources> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="bgTheme" parent="@style/AppTheme"> <item name="android:windowNoTitle">false</item> <item name="android:windowBackground">@drawable/background</item> </style> </resources>
|
编写好主题资源后,就可以使用主题资源。
使用主题资源有两个方式:
- 在Androidmanifest.xml文件中配置;
- 在Java文件中使用主题资源。
在Androidmanifest.xml文件中配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/bgTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
|
若想要给所有的Activity设置主题资源,那么就在<application>
中的android:theme
进行设置;若指向给某个Activity设置主题资源,那么就在<activity>
中的android:theme
进行设置。
在Java文件中使用主题资源:
MainActivity.java:
这里的类继承的是Activity
1 2 3 4 5 6 7 8 9
| public class MainActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTheme(R.style.bgTheme); setContentView(R.layout.activity_main); } }
|
在Java文件中使用主题资源:在Activity的onCreate()
方法中,设置使用的主题资源时,一定要在方法setContentView()
之间设置,否则不起作用。
样式资源
我们可以在res/values/styles.xml中编写我们直接的样式资源。
既然样式资源和主题资源都是在styles.xml中进行编写,那他们有什么区别呢?
- 主题:设置整个APP或窗口样式
- 样式:设置组件的样式
样式资源的使用
在styles.xml文件中编写我们自定义的样式:
1 2 3 4 5 6 7 8 9
| <style name="title"> <item name="android:textSize">30sp</item> <item name="android:textColor">#06F</item> </style>
<style name="context" parent="title"> <item name="android:textSize">18sp</item> </style>
|
其他属性我们可以自行摸索理解。
样式资源文件我们一般在XML文件中使用。
activity_main.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <RelativeLayout> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="乔布斯" style="@style/title" android:id="@+id/textView"/> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="活着就是为了改变世界,难道还有其他原因吗?" android:layout_below="@+id/textView" style="@style/context"/> </RelativeLayout>
|
菜单资源
AS在创建项目时,不会默认给我们创建了菜单资源目录及文件。
需要我们手动创建,文件位置为:res/menu/**.xml
菜单资源的使用
在res/menu目录下创建menu.xml编写我们的菜单资源文件:
1 2 3 4 5 6 7
| <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="message" android:title="消息"></item> <item android:id="homepage" android:title="首页"></item> <item android:id="help" android:title="帮助"></item> <item android:id="feedback" android:title="我要反馈"></item> </menu>
|
创建选项菜单
选项菜单:点击手机上的物理按键(菜单键)或手机APP右上角的三个小圆点弹出的菜单。
创建步骤:
- 添加选项菜单;
- 指定菜单项被选中时应做出的处理。
创建右上角圆点菜单,并对选中项做出处理
在res目录下创建:menu/setting_menu.xml:
1 2 3 4
| <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/settings" android:title="设 置"></item> <item android:id="@+id/regard" android:title="关 于"></item> </menu>
|
编写处理界面:
activity_main.xml:
1 2 3 4
| <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="设置界面"/>
|
acitivity_regard.xml:
1 2 3 4
| <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="关于界面"/>
|
activity_main.xml使用默认即可。
在MainActivity中添加菜单选项,并对所选项做出处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = new MenuInflater(this); menuInflater.inflate(R.menu.setting_menu,menu); return super.onCreateOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { switch (item.getItemId()){ case R.id.settings: Intent intent = new Intent(MainActivity.this, Settings.class); startActivity(intent); break; case R.id.regard: Intent intent1 = new Intent(MainActivity.this, Regard.class); startActivity(intent1); break; } return super.onOptionsItemSelected(item); } }
|
创建上下文菜单
上下文菜单:就是我们在界面上长按某一组件时弹出的菜单。
创建步骤:
- 为主键注册上下文菜单;
- 添加上下文菜单;
- 指定菜单项被选择时所应作出的处理。
选中文字并长按,弹出上下文菜单,并对说选项做出处理
**在res目录下创建:menu/menu.xml,**自定义上下文菜单内容
1 2 3 4 5 6
| <menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/mune_copy" android:title="复制"></item> <item android:id="@+id/mune_collect" android:title="收藏"></item> <item android:id="@+id/mune_translate" android:title="翻译"></item> <item android:id="@+id/mune_report" android:title="举报"></item> </menu>
|
设置activity_main.xml布局资源文件内容:
1 2 3 4 5
| <TextView android:id="@+id/introduce" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="安卓是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的操作系统。主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。Android操作系统最初由Andy Rubin开发,主要支持手机。2005年8月由Google收购注资。2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,发布了Android的源代码。" />
|
在MainActivity中添加菜单选项,并对所选项做出处理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| public class MainActivity extends AppCompatActivity { TextView introduce; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); introduce = findViewById(R.id.introduce); registerForContextMenu(introduce); } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { MenuInflater menuInflater = new MenuInflater(this); menuInflater.inflate(R.menu.menu,menu); super.onCreateContextMenu(menu, v, menuInfo); } @Override public boolean onContextItemSelected(@NonNull MenuItem item) { switch (item.getItemId()){ case R.id.mune_copy: Toast.makeText(MainActivity.this, "已复制", Toast.LENGTH_SHORT).show(); break; case R.id.mune_collect: Toast.makeText(MainActivity.this, "已收藏", Toast.LENGTH_SHORT).show(); break; } return true; } }
|
Action Bar 的使用
初识Action Bar
Action Bar可以含有:APP图标、Activity标题、选项菜单、溢出菜单、向上按钮、Tab导航等。
可供参考链接: 参考链接1
显示和隐藏Action Bar
从Android 3.0(API 11)开始Activity就默认包含了Action Bar组件。
显示Action Bar:
那么只需要在build.gradle文件中将android:minSdkVersion
设置成11或以上版本就可以了。
隐藏Action Bar:
若想要给所有的Activity都不显示Action Bar,那么就将<application>
中的android:theme
设置成后缀为.NoActionBar
的主题;若指向给某个Activity不显示Action Bar,那么就将<activity>
中的android:theme
设置成后缀为.NoActionBar
的主题。
如: android:theme="@style/Theme.AppCompat.Light.NoActionBar"
通过按钮来显示或隐藏Action Bar
在activity_main.xml中编写两个按钮组件,用于控制Action Bar的显示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <LinearLayout android:orientation="horizontal" android:gravity="center_horizontal"> <Button android:id="@+id/button_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="显示Action Bar" android:textAllCaps="false"/> <Button android:id="@+id/button_hide" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="隐藏Action Bar" android:textAllCaps="false"/> </LinearLayout>
|
MainActivity.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ActionBar actionBar = getSupportActionBar(); Button button_show = findViewById(R.id.button_show); Button button_hide = findViewById(R.id.button_hide);
button_show.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { actionBar.show(); } });
button_hide.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { actionBar.hide(); } }); }
|
添加Action Item
在Action Bar上可以看到很多小图标,这些小图标就叫做:Action Item。由于Action Bar上的空间是有限的,有些放不下的小图标可以放到溢出菜单。
Action Bar空间划分示例:
添加Action Item的步骤:
- 定义菜单资源文件;
- 在onCreateOptionsMenu()方法中加载菜单资源文件。
在Action Bar中添加Action Item
准备:需要准备两个图标文件,分别表示搜索和消息,并分别命名为search和bell,将它们放置在drawable目录下。
**在res目录下创建:menu/menu.xml,**自定义Action Item:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <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="always"/> <item android:id="@+id/bell" android:icon="@drawable/bell" android:title="消息" app:showAsAction="ifRoom"/> <item android:id="@+id/settings" android:title="设置" app:showAsAction="ifRoom"/> <item android:id="@+id/about" android:title="关于" app:showAsAction="never"/> </menu>
|
在MainActivity.java 中解析菜单文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.menu,menu); return super.onCreateOptionsMenu(menu); } }
|
showAsAction属性详解:
属性详解:
- always:无论是否溢出,总会显示在Action Bar上。如果同时设置了icon和title,默认只会显示icon。
- ifRoom:可以显示在Item中。但是如果超出了菜单项的空间会隐藏在溢出菜单中,只显示title。菜单项的空间根据屏幕的宽窄而定。
- never:永远不会显示。只会在溢出菜单中显示,而且只显示title,所以在定义item的时候,需要设置title。
- collapseActionView:声明了collapseActionView的Action View会被折叠到一个按钮中,当用户点击这个按钮时,这个Action View才会展开。否则,这个Action View在默认的情况下是可见的,并且即便在不使用的时候,也要占据操作栏的有效空间。一般要配合ifRoom一起使用才会有效果。
- withText:使Action Item显示title。Action Item会尽可能的显示这个标题,但它会受到菜单项空间的限制而使文本标题有可能显示不全。
官方建议我们在设置<item>
时设置title属性,我们在长按icon的情况下title就会出现,另外官方还建议showAsAction最好设置为ifRoom,因为如果设置为always可能会在比较窄的屏幕上带来布局的问题。
showAsAction属性值withText解析:
在showAsAction属性详解中我们已经知道可以通过设置withText作为属性值来显示title。因此我们是否可以通过设置app:showAsAction="always|withText"
来同时显示title和icon。
我们发现这样也不一定生效,因为withText对actionBar的title来说只是一个hint,在条件允许的情况下actionBar会显示title,但是当设置了icon并由于空间限制也不会显示title。
而且系统默认在竖屏时是只显示icon,不论是否设置了withText属性在竖屏时都只显示icon而不显示title。withText属性要在横屏时才体现的出来,将设备横屏显示就既显示图标又显示文字了。
添加Action View
在一些APP界面的Action Bar上,经常可以看到有用来进行搜索操作的输入框或者可以进行搜索的组件,这些就是Action View。但也并不是说只有搜索框或搜索组件才是Action View,Action View是用于替换Action Button并显示在Action Bar上面的一种可视组件。
添加Action View
方法:
- 通过
app:actionViewClass
属性,依赖实现类。
- 通过
app:actionLayout
属性,依赖布局文件。
准备:需要准备两个图标文件,分别表示通讯录和添加,将其命名为message和add,置于drawable目录下。
Action View布局文件:
img_add.xml:
1 2 3 4 5 6 7 8 9 10
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:src="@drawable/add"/> </LinearLayout>
|
img_message.xml:
1 2 3 4 5 6 7 8 9 10
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent">
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="12dp" android:src="@drawable/message"/> </LinearLayout>
|
**在res目录下创建:menu/menu.xml,**自定义Action View:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/search" android:title="搜索" app:showAsAction="always" app:actionViewClass="android.widget.SearchView" /> <item android:id="@+id/img1" android:title="通讯录" app:actionLayout="@layout/img_message" app:showAsAction="always"/> <item android:id="@+id/img2" android:title="添加" app:actionLayout="@layout/img_add" app:showAsAction="always"/> </menu>
|
在MainActivity.java 中解析菜单文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getSupportActionBar().setDisplayShowTitleEnabled(false); }
@Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater menuInflater = getMenuInflater(); menuInflater.inflate(R.menu.menu,menu); return super.onCreateOptionsMenu(menu); } }
|
Action Bar 与Tab
在最新版的Android中,已经不推荐使用这种方法来实现顶部的Tab切换,推荐使用TabLayout。
内容太多,在此给出4片文章作为参考,也可根据自己需要自行搜索:
TabLayout-标签布局-
Android TabLayout
Tablayout使用全解,一篇就够了
TabLayout使用详解
前三篇为属性讲解和基本使用,最后一篇为小实战。
实现层级式导航
在APP的一些界面中,我们可以看到左上角有一个返回箭头,当我们点击这个箭头时,我们就会回到上一界面,这个箭头启用了层级式导航才实现了这样的功能。
实现方法:
- 设置导航图标显示:使用
setDisplayHomeAsUpEnabled()
- 配置父Activity:在AndroidManifest.xml中配置
实现层级式导航
准备:需要一张图片。命名为image,放置于drawable目录下。
自定义图片展示界面:activity_pic.xml
1 2 3 4 5 6 7 8 9
| <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/image" tools:context=".PicActivity">
</RelativeLayout>
|
定义程序主入口界面:activity_main.xml:
1 2 3 4 5 6 7 8 9
| <RelativeLayout > <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="查看图片" android:layout_centerHorizontal="true" android:layout_marginTop="20dp"/> </RelativeLayout>
|
实现在主界面点击按钮跳转至图片展示界面:MainActivity.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, PicActivity.class); startActivity(intent); } }); } }
|
判断父Activity是否为空,设置跳转箭头,实现层级式导航:
PicActivity.java:
1 2 3 4 5 6 7 8 9 10 11 12
| public class PicActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_pic); if (NavUtils.getParentActivityIntent(PicActivity.this) != null){ getSupportActionBar().setDisplayHomeAsUpEnabled(true); } } }
|
最后在AndroidManifest.xml中声明图片展示界面的父Activity:
1 2 3 4 5 6 7
| <activity android:name=".PicActivity" android:label="图片"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".MainActivity"/> </activity>
|
消息、通知与广播
通过Toast显示消息提示框
消息提示框特点:
- 没有控制按钮
- 不会获得焦点
- 过一会自动消失
显示消息提示框的步骤:
- 创建Toast对象
- 使用构造方法:
new Toast(context)
makeText()
方法:指定显示的内容、持续的时间
- 设置消息提示的方式
- 调用
show()
方法
一定不能忘记调用show()
方法,否则消息提示框不会显示并且程序也不会产生任何异常信息。
使用示例:
1
| Toast.makeText(MainActivity.this, "******", Toast.LENGTH_SHORT).show();
|
makeText第一个参数为上下文对象,第二个参数为消息内容,第三个参数为持续时间。
持续时间: LENGTH_SHORT
(2s) LENGTH_LONG
(3.5s)
使用AlertDialog实现对话框
对话框组成部分:
其中,图标区和标题区不是必须的。
应用AlertDialog类实现4种不同类型的对话框
准备:我们需要3张图标资源,分别表示iPhone、接收短信和骰子,并命名为iphone、like和dice,将他们放置于drawable目录下。
编写布局资源文件activity_main.xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingTop="16dp" android:paddingEnd="16dp" android:paddingStart="16dp" android:paddingBottom="16dp" android:orientation="vertical" tools:context=".MainActivity"> <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#38cfd1" android:textColor="#FFFFFF" android:textSize="16sp" android:layout_marginBottom="20dp" android:text="显示带取消、确定按钮的对话框"/> <Button android:id="@+id/button2" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#3961b7" android:textColor="#FFFFFF" android:textSize="16sp" android:layout_marginBottom="20dp" android:text="显示带列表的对话框"/> <Button android:id="@+id/button3" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#43b243" android:textColor="#FFFFFF" android:textSize="16sp" android:layout_marginBottom="20dp" android:text="显示带单选列表项的对话框"/> <Button android:id="@+id/button4" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#f9671c" android:textColor="#FFFFFF" android:textSize="16sp" android:text="显示带多选列表项的对话框"/> </LinearLayout>
|
编写MainActivity.java,使用AlertDialog实现对话框:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
| public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button1 = findViewById(R.id.button1); button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create(); alertDialog.setIcon(R.drawable.iphone); alertDialog.setTitle("乔布斯:"); alertDialog.setMessage("活着就是为了改变世界,难道还有其他原因吗?"); alertDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "否", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "您单击了否按钮", Toast.LENGTH_SHORT).show(); } }); alertDialog.setButton(DialogInterface.BUTTON_POSITIVE, "是", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "您单击了是按钮", Toast.LENGTH_SHORT).show(); } });
alertDialog.show(); } }); Button button2 = findViewById(R.id.button2); button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final String[] items = new String[]{"当你有使命,它会让你更专注", "要么出众,要么出局", "活着就是为了改变世界", "求知若饥,虚心若愚"}; AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setIcon(R.drawable.like); builder.setTitle("请选择你喜欢的名言"); builder.setItems(items, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "你选择了【" + items[which] + "】", Toast.LENGTH_SHORT).show(); } }); builder.create().show(); } }); Button button3 = findViewById(R.id.button3); button3.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final String[] items = new String[]{"扎克伯格", "乔布斯", "拉里·埃里森", "安迪·鲁宾", "马云"}; AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setIcon(R.drawable.dice); builder.setTitle("你更喜欢谁?"); builder.setSingleChoiceItems(items, 0, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Toast.makeText(MainActivity.this, "你选择了【" + items[which] + "】", Toast.LENGTH_SHORT).show(); } }); builder.setPositiveButton("确定", null); builder.create().show(); } }); Button button4 = findViewById(R.id.button4); button4.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final boolean[] checkedItems = new boolean[]{false, true, false, true, false}; final String[] items = new String[]{"LOL", "DOTA", "WOWS", "Warcraft", "StarCraft"}; AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setIcon(R.drawable.dice); builder.setTitle("请选择你喜爱的游戏"); builder.setMultiChoiceItems(items, checkedItems, new DialogInterface.OnMultiChoiceClickListener() { @Override public void onClick(DialogInterface dialog, int which, boolean isChecked) { checkedItems[which] = isChecked; } }); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String result = ""; for (int i = 0; i < checkedItems.length; i++) { if (checkedItems[i]){ result+=items[i]+"、"; } } if (!"".equals(result)){ Toast.makeText(MainActivity.this, "你选择了【"+result+"】", Toast.LENGTH_SHORT).show(); } } }); builder.create().show(); } }); } }
|
总结:
使用Notification显示通知
这里的通知是指在顶部状态栏上的通知。
使用Notification显示通知的步骤:
- 获取系统的NotificationManager服务。使用
getSystemService()
方法。
- 创建Notification对象。使用
new Notification.Builder(this)
- 为Notification对象设置属性。 使用
setContentTitle()
、setContentText()
…
- 发送Notification通知。使用NotificationManager类的
notify()
方法。
参考链接:Android Notification(通知)(含兼容问题)
实现点击状态栏通知跳转界面
案例概述:运行程序后,在程序主入口界面状态栏出现通知,点击通知后,跳转至图片显示界面。
准备:需要一张表示图片的图标文件(pic.png)和一张图片(image1.png),将它们放置于res/drawable目录下。
- 创建Activity——DetailActivity.java及其布局资源文件。
activity_main.xml使用默认布局资源。
编写点击通知后跳转的界面activity_detail.xml:
1 2 3 4 5 6 7 8
| <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/image1" tools:context=".DetailActivity"> </RelativeLayout>
|
- 在MainActivity.java中设置状态栏通知。
DetailActivity.java使用默认Activity。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class MainActivity extends AppCompatActivity { final int NOTIFY_ID = 0x123; public static final String NOTIFICATION_CHANNEL_ID = "10001"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); Notification.Builder builder = new Notification.Builder(MainActivity.this); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance); builder.setChannelId(NOTIFICATION_CHANNEL_ID); notificationManager.createNotificationChannel(notificationChannel); } builder.setAutoCancel(true) .setSmallIcon(R.drawable.pic) .setContentTitle("请接收你的图片") .setContentText("点击查看详情") .setWhen(System.currentTimeMillis()) .setDefaults(Notification.DEFAULT_SOUND|Notification.DEFAULT_VIBRATE); Intent intent = new Intent(MainActivity.this, DetailActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this,0,intent,0); builder.setContentIntent(pendingIntent); notificationManager.notify(NOTIFY_ID,builder.build()); } }
|
问题思考
编写好MainActivity运行后,状态栏不会显示通知,并弹出消息提示框,显示:Failed to post notification on channel “null”
参考链接:Failed to post notification on channel “null”
原因:Since Android Oreo, you need a Channel to send your notifications.
解决方法:
1 2 3 4 5 6 7 8 9
| if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { int importance = NotificationManager.IMPORTANCE_HIGH; NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance); builder.setChannelId(NOTIFICATION_CHANNEL_ID); notificationManager.createNotificationChannel(notificationChannel); }
|
其中,notificationManager是实例的NotificationManager对象,builder是实例的Notification.Builder对象。
使用BroadcastReceiver
BroadcastReceiver:广播接收器。
在安卓中,广播没有自己的表现形式,但我们可以通过通知、对话框、消息提示框来展示出来。
使用BroadcastReceiver接收广播
案例介绍:点击按钮,发送广播,然后接收广播并弹出消息提示框显示广播。
程序主入口:activity_main.xml:
1 2 3 4 5 6 7 8
| <RelativeLayout > <Button android:id="@+id/broadcast" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送一条广播" android:layout_centerHorizontal="true" /> </RelativeLayout>
|
编写广播接收器,新建MyReceiver.java 类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class MyReceiver extends BroadcastReceiver { private static final String ACTION_1 = "扎克伯格"; private static final String ACTION_2 = "马云"; @Override public void onReceive(Context context, Intent intent) { if (intent.getAction().equals(ACTION_1)){ Toast.makeText(context, "MyReceiver收到:扎克伯格的广播..."+intent.getStringExtra("msg"), Toast.LENGTH_SHORT).show(); }else if (intent.getAction().equals(ACTION_2)){ Toast.makeText(context, "MyReceiver收到:马云的广播..."+intent.getStringExtra("msg"), Toast.LENGTH_SHORT).show(); } } }
|
在MainActivity.java中发送广播:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public class MainActivity extends AppCompatActivity { private MyReceiver receiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button button = findViewById(R.id.broadcast); IntentFilter filter = new IntentFilter(); filter.addAction("扎克伯格"); filter.addAction("马云"); receiver = new MyReceiver(); registerReceiver(receiver,filter); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setAction("扎克伯格"); intent.putExtra("msg","比尔盖茨"); sendBroadcast(intent); } }); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(receiver); } }
|
我们在这个案例中使用的是动态注册广播,因为我们使用的是Android 10,在Android 8及以上的版本中静态注册广播的方式无效,因此选用动态注册广播。
至于静态注册在此不再说明,只需要在AndroidManifest.xml文件中配置即可,可自行搜索了解。
使用AlarmManager设置闹钟
通过案例来介绍:
应用AlarmManager类实现一个定时启动的闹钟
案例介绍:先设置一个闹钟,当到达设置的时间后,会弹出对话框显示。
准备:需要一张表示闹钟的图标资源文件,命名为alarm,放置于res/drawable目录下。
编写布局资源文件activity_main.xml,放置时间选择器和按钮组件:
1 2 3 4 5 6 7 8 9 10 11 12 13
| <RelativeLayout> <TimePicker android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <Button android:id="@+id/set" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:text="设置闹钟"/> </RelativeLayout>
|
编写AlarmActivity.java,创建闹钟提示内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class AlarmActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AlertDialog alert = new AlertDialog.Builder(this).create(); setContentView(R.layout.activity_alarm); alert.setIcon(R.drawable.alarm); alert.setTitle("每日一句:"); alert.setMessage("要么出众,要么出局"); alert.setButton(DialogInterface.BUTTON_POSITIVE, "确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); alert.show(); } }
|
编写MainActivity.java设置闹钟:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public class MainActivity extends AppCompatActivity {
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final TimePicker timePicker = findViewById(R.id.time); timePicker.setIs24HourView(true); Button button = findViewById(R.id.set); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MainActivity.this, AlarmActivity.class); PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 0,intent,0); AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY,timePicker.getCurrentHour()); calendar.set(Calendar.MINUTE,timePicker.getCurrentMinute()); calendar.set(Calendar.SECOND,0);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),pendingIntent); Toast.makeText(MainActivity.this, "闹钟设置成功", Toast.LENGTH_SHORT).show(); } }); } }
|
闹钟类型
ELAPSED_REALTIME
:设置在指定的延时后提醒,不会唤醒系统
ELAPSED_REALTIME_WAKEUP
:设置在指定的延时后提醒,会唤醒系统
RTC
:使用真实的时间提醒,到达指定的时间提醒,不会唤醒系统
RTC_WAKEUP
:使用真实的时间提醒,到达指定的时间提醒,会唤醒系统
使用AlarmManager类的实例对象中的set()
方法设置闹钟。
Android资源、活动条与信息通知完