创建菜单
一、创建方式
1、xml
(1)制作Menu.xml,并且把菜单选项都设置好
(2)Inflater压进来,显示
game_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/new_game"
android:icon="@drawable/ic_new_game"
android:title="@string/new_game"
android:showAsAction="ifRoom"/>
<item android:id="@+id/help"
android:icon="@drawable/ic_help"
android:title="@string/help" />
</menu>
android:id——A resource ID that's unique to the item, which allows the application can recognize the item when the user selects it.
android:icon——A reference to a drawable to use as the item's icon.
android:title——A reference to a string to use as the item's title.
android:showAsAction——Specifies when and how this item should appear as an action item in the action bar.
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.game_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
case R.id.new_game:
newGame();
return true;
case R.id.help:
showHelp();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
2、Menu.add()
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//add(int i, int i1, int i2, java.lang.CharSequence charSequence);
menu.add(1, 1, 1, "add");
menu.add(1, 2, 2, "delete");
return super.onCreateOptionsMenu(menu);
}
Menu可以多级嵌套
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/file"
android:title="@string/file" >
<!-- "file" submenu -->
<menu>
<item android:id="@+id/create_new"
android:title="@string/create_new" />
<item android:id="@+id/open"
android:title="@string/open" />
</menu>
</item>
</menu>
二、菜单类别
1、OptionMenu:按Menu键弹出的菜单
2、ContextMenu:右键菜单:需要注册
Register the View to which the context menu should be associated by calling registerForContextMenu() and pass it the View.
If your activity uses a ListView or GridView and you want each item to provide the same context menu,
register all items for a context menu by passing the ListView or GridView to registerForContextMenu().
Implement the onCreateContextMenu() method in your Activity or Fragment
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
Implement onContextItemSelected().
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
switch (item.getItemId()) {
case R.id.edit:
editNote(info.id);
return true;
case R.id.delete:
deleteNote(info.id);
return true;
default:
return super.onContextItemSelected(item);
}
}
3、SubMenu(归在OptionMenu和ContextMenu中)
创建Dialog
Builder设计模式
当一个对象太复杂,而且不一定每一个都是构建时必须的
所以使用Builder去拼装,需要哪些拼装哪些
拼装好以后调用create,返回需要的对象
Builder斜体,表示的是一个抽象类
Director与Builder之间是一个聚合的关系
说明:
setCancelable(),能否取消
官方推荐复写onCreateDialog方法,能通过id创建不同的dialog
查看Dialog源码
很像Activity,有WIndowManager
能看到样式的定义,也能看到为什么Dialog默认居中
查看Dialog子类AlertDialog的源码
create是AlertDialog内部类Builder的方法
看一下AlertDialog的构造器
AlertController是一个控制对象,是后面与set相关的各个对象属性的控制器
回头看Create方法
P是一系列的参数,将设定的属性都应用到AlertDialog上
看一下show方法
show也调用了create方法,所以AlertDialog不调用create直接show也是可以的
看其父类Dialog的show方法
可以看到Dialog中也有一个DecorView,也有WindowManager
最后设置完成后,发送一个消息sendShowMessage()
提醒
一、Toast
二、Notification
基本Notification操作步骤
1、通过getSystemServices得到NotificationManager对象
2、构造一个Notification实例
3、Notification设置最新事件信息
4、启动提醒
public class MainActivity extends Activity {
private NotificationManager mNotificationManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// ......
// 设置NotificationManager实例
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
// ......
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// public Notification(int icon, java.lang.CharSequence tickerText, long when)
// 这个构造器中传入的都是顶部提示条不拉下的时候显示的内容(图标和文字)
Notification notification = new Notification(R.drawable.icon,
"you have a new message", System.currentTimeMillis() + 1000);
// Pending是等待的意思,PendingIntent的作用就是点击后要进行的操作
// PendingIntent没有构造函数,通过getActivity,getService等获得并传入相关Intent
// PendingIntent不是Intent
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this,
0x123, new Intent(MainActivity.this, LoginActicity.class), 0);
notification.setLatestEventInfo(MainActivity.this, "Notification Title",
"Notification Content", pendingIntent);
// 还可以定义一些震动、声音、呼吸灯等
// 定义震动
long[] vib = {0, 200, 400, 600, 1000};
notification.vibrate = vib;
mNotificationManager.notify(123, notification);
}
});
}
@Override
protected void onStop() {
// 可以通过id清掉指定通知,也可以通过cancelAll清掉所有
mNotificationManager.cancel(123);
super.onStop();
}
}
用户还可以自定义自己的布局样式
// public Notification(int icon, java.lang.CharSequence tickerText, long when)
// 这个构造器中传入的都是顶部提示条不拉下的时候显示的内容(图标和文字)
Notification notification = new Notification(R.drawable.icon,
"you have a new message", System.currentTimeMillis() + 1000);
// Pending是等待的意思,PendingIntent的作用就是点击后要进行的操作
// PendingIntent没有构造函数,通过getActivity,getService等获得并传入相关Intent
// PendingIntent不是Intent
PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this,
0x123, new Intent(MainActivity.this, LoginActicity.class), 0);
// notification.setLatestEventInfo(MainActivity.this, "Notification Title",
// "Notification Content", pendingIntent);
// 主要不要与setLatestEventInfo共存,不然会冲突(都是设置页面布局的)
// contentView设置RemoteView布局,contentIntent设置点击后的操作PendingIntent
notification.contentView = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
notification.contentIntent = pendingIntent;
mNotificationManager.notify(123, notification);
PendingIntent是Singleton模式
样式
使用?调用样式表示如果找不到定义的样式可以使用默认样式
使用@调用样式表示确定要使用指定的样式
values下面不看文件名,而以标签名确定,所以把所有values放一个文件也没问题
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="textRed">
<item name="android:textColor">@color/color_red</item>
</style>
<style name="textGreen">
<item name="android:textColor">@color/color_green</item>
</style>
<style name="textBlue">
<item name="android:textColor">@color/color_blue</item>
</style>
<color name="color_red">#ff0000</color>
<color name="color_green">#00ff00</color>
<color name="color_blue">#0000ff</color>
</resources>
之前建立水平进度条时发现是这样引用的
看到是一个attr的属性,进入源码values/attrs.xml中可以看到
这些attr是被包含在declare-styleable标签中的,后面跟着的format是类型
style可以应用到View上,也可以应用到Activity或者Application上
style也可以继承
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="customTheme" parent="@android:style/TextAppearance">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">fill_parent</item>
</style>
<style name="customTheme.textRed">
<item name="android:textColor">@color/color_red</item>
</style>
<style name="customTheme.textGreen">
<item name="android:textColor">@color/color_green</item>
</style>
<style name="customTheme.textBlue">
<item name="android:textColor">@color/color_blue</item>
</style>
<color name="color_red">#ff0000</color>
<color name="color_green">#00ff00</color>
<color name="color_blue">#0000ff</color>
</resources>
首先customTheme继承了系统的样式,而textRed等继承了customTheme的样式
开发中应该多使用style,这样换肤的时候更加方便。
values文件夹可以加后缀,语言、版本等等,可以参考这里
自定义组件
分类
1、Customized Component
继承View,增加更多的属性和事件,纵向扩展
2、Compound Component
继承ViewGroup,把多个简单控件通过布局拼装一个复合控件,横向扩展
定义组件步骤
1、选择继承类,View或View的子类
2、类的初始化:新增属性和新增属性的初值设定
3、重载方法
(1)onDraw(), onMeasure()
(2)onKeyEvent():监听器+重载函数
public class MyButton extends Button {
// 定义一个接口对象,传入的接口实现对象赋到此处
private OnIconClickListener mOnIconClickListener;
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
// 定义一个监听接口
interface OnIconClickListener{
// 定义一个方法
public void onClick(String iconObject);
}
public void setOnIconClickListener(OnIconClickListener onIconClickListener){
mOnIconClickListener = onIconClickListener;
}
// 设定一个protected方法,供子类调用并在onKeyDown中调用这个方法
protected void onIconClick(String iconObject){
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (mOnIconClickListener != null){
mOnIconClickListener.onClick("Hello");
onIconClick("Hello");
}
return super.onKeyDown(keyCode, event);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.RED);
canvas.drawRect(5, 5, 25, 25, paint);
}
}
使用方式
1、layout中<包名+类名>
2、<View class="包名+类名" /> 可以容易在动态代码写控件中使用
如果是内部类<View class="包名+类名$内部类类名" />
原则:
1、如果只是本项目用,可以用inner class
2、如果打算商业发布,需要用单独的类文件
3、如果打算商业发布,不要用xml layout文件,而用动态代码生成