Android基础13 常用UI(下)

1.菜单(Menu)

1.1 普通menu

图片1

  1. 重写Activity的onCreateOptionsMenu(Menu menu)方法,该方法用于创建选项菜单,在用户按下手机的“Menu”按钮时就会显示创建好的菜单,在onCreateOptionsMenu(Menu menu)方法内部可以调用Menu.add()方法实现菜单的添加。
  2. 重写Activity的onMenuItemSelected()方法,该方法用于处理菜单被选择事件
  3. 通过手机上提供的“MENU”按钮可以打开菜单,如果希望通过代码打开菜单,可以调用Activity的openOptionsMenu()方法。
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
public class MenuActivity extends Activity {
private static final String TAG = "MenuActivity";
private static final int MENU_ADD = Menu.FIRST;
private static final int MENU_UPDATE = Menu.FIRST + 1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
truetruemenu.add(Menu.NONE, MENU_ADD, Menu.NONE, "添加");
truetruemenu.add(Menu.NONE, MENU_UPDATE, Menu.NONE, "更新");
truetruereturn super.onCreateOptionsMenu(menu); }
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
truetrueswitch (item.getItemId()) {
true case MENU_ADD:
true Log.i(TAG, "add was selected");
true return true;
true case MENU_UPDATE:
true Log.i(TAG, "update was selected");
true return true;
true default:
return super.onMenuItemSelected(featureId, item);
} } }

1.2 SubMenu

  1. 添加子菜单
    调用menu对象的addSubMenu(final CharSequence title),该方法返回一个SubMenu对象
  2. 添加子菜单的菜单项
    调用SubMenu对象的add(CharSequence title) 方法
1
2
3
4
5
6
7
8
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 1, 1, "苹果");
menu.add(0, 2, 2, "香蕉");
SubMenu subMenu = menu.addSubMenu(1, 100, 100, "桃子");
subMenu.add(2, 101, 101, "大桃子");
subMenu.add(2, 102, 102, "小桃子");
return true;
}

1.3 Context Menu

类似于电脑上的右键,长按某个View之后弹出来的菜单。首先在main.xml里定义若干个按钮。首先要注册一下,在onCreate方法里,如下代码:

1
2
3
4
5
6
7
8
9
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b1 = (Button) findViewById(R.id.b1);
b2 = (Button) findViewById(R.id.b2);
registerForContextMenu(b1);
registerForContextMenu(b2);
}

然后覆盖onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
if(v==b1){
menu.setHeaderTitle("这是1");
menu.add(200, 200, 200, "Context Menu 1");
menu.add(200, 201, 201, "Context Menu 2");
}
else if(v==b2){
menu.setHeaderTitle("这是2");
menu.add(300, 300, 300, "C 1");
menu.add(300, 301, 301, "C 2");
}
super.onCreateContextMenu(menu, v, menuInfo);
}

1.4 动态Menu

图片2
动态菜单就是根据不同的界面有不同的菜单。下面的代码实现这样的功能:当主界面的某个TextView的值是“M“和“N”时,弹出不同的菜单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
String currentText = tv1.getText().toString();
if("M".equals(currentText)){
menu.clear();//先清掉菜单
MenuItem item = menu.add(0, 400, 401, "to N");//可以通过点击这个菜单项来改变tv1的值这样(变成N)就可以测试了
item.setIcon(android.R.drawable.alert_dark_frame);//android自带的图标
}
if("N".equals(currentText)){
menu.clear();//先清掉菜单
MenuItem item = menu.add(0, 401, 402, "to M");//可以通过点击这个菜单项来改变tv1的值这样(变成M)就可以测试了
item.setIcon(android.R.drawable.alert_light_frame);
}
menu.add(0, 402, 403, "Now is " + currentText);//现在共有两个菜单子项
return super.onPrepareOptionsMenu(menu);
}

1.5 用xml文件方式创建Menu

之前都是用代码的方法创建Menu,用xml配置文件也可以相当方便地制作菜单。
要res/目录下建一个文件夹,名为menu,下面建一个xml文件,名为menu_xml_file.xml,代码如下:

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/grout_main">
<item android:id="@+id/menu_1"
android:title="This 1"/>
<item android:id="@+id/menu_2"
android:title="This 2" />
</group>
</menu>

在Activity中覆盖onCreateOptionsMenu(Menu menu)方法,代码如下:

1
2
3
4
5
6
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu_xml_file, menu);
return true;
}

其他的都和在Activity中制作菜单一样。

2. 手势识别(GestureOverlayView)

图片3

  1. 建立手势库
    使用SDK自带例子GestureBuilder建立手势库(位置:android-sdk-windows\samples\android-8\GestureBuilder)。使用GestureBuilder之前,你需要恢复其到开发环境,然后进行编绎并部署到手机上。此时,就可以使用GestureBuilder建立手势库,生成的手势库文件在SCDard上,默认文件名称为:gestures
  2. 在应用中加载手势库文件,然后开发手势识别代码。
    把手势库文件gestures文件拷贝到项目的res/raw目录下。然后在布局文件中添加用于手势绘制的View:
1
2
3
4
5
<android.gesture.GestureOverlayView
truetrueandroid:id="@+id/gov"
truetrueandroid:layout_width="fill_parent"
truetrueandroid:layout_height="fill_parent"
truetrueandroid:gestureStrokeType="multiple"/>
  1. 为View添加手势监听事件:gestureOverlayView.addOnGesturePerformedListener();
  2. 得到手势库:mLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);
  3. 加载手势库:mLibrary.load();

大多数情况下,手势都是通过一笔完成。然而有一些特别的需求就需要通过多个笔画来实现,这时可以使用gestureStrokeType属性进行设置:android:gestureStrokeType=”multiple”

代码实现:

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
public class MainActivity extends Activity {
private GestureOverlayView gestureOverlayView;
private GestureLibrary mLibrary;
private boolean state;
private EditText addressText;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
addressText = (EditText)this.findViewById(R.id.address);
gestureOverlayView = (GestureOverlayView)this.findViewById(R.id.gestures);
//当用户完成一次Gesture绘制后,系统将自动调用Listener对象的onGesturePerformed()方法
gestureOverlayView.addOnGesturePerformedListener(new GestureListener());
mLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);
state = mLibrary.load();//加载手势库
}
private final class GestureListener implements GestureOverlayView.OnGesturePerformedListener{
truetrue@Override
truetruepublic void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
truetruetrueif(state){
truetruetruetrueList<Prediction> predictions = mLibrary.recognize(gesture);
truetruetruetrue//从手势库中查询匹配的内容,匹配的结果可能包括多个相似的结果,匹配度高的结果放在最前面
truetruetruetrueif(!predictions.isEmpty()){
truetruetruetruetruePrediction prediction = predictions.get(0);
truetruetruetruetrue//prediction的score属性代表了与手势的相似程度name代表手势对应的名称
truetruetruetruetrueif(prediction.score > 1){
truetruetruetruetruetrueaddressText.setText(prediction.name);
truetruetruetruetrue}
truetruetruetrue}
truetruetrue}
truetrue}
true}
}

3. 编码实现软件界面

Android除了可以使用xml实现软件界面,还可以通过编码方式实现软件的界面,而且在某种情况下只能采用编码方式实现软件的界面,例如:软件运行时需要根据运算结果决定显示某些内容。如果不是必须,建议使用xml,因为这样可以使应用遵守mvc设计模式,具有良好的软件分层结构。下面代码实现了如HelloWorld项目一样的软件界面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MainActivity extends Activity {
truepublic void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout linearLayout = new LinearLayout(this);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
TextView textView = new TextView(this);
textView.setText(R.string.hello);
textView.setId(34);
LinearLayout.LayoutParams textParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
linearLayout.addView(textView, textParams);
setContentView(linearLayout, layoutParams);
}
}

4. 网页视图(WebView)

因为android软件开发分工目前还没有细化,程序员往往需要负责软件界面的开发,虽然软件的界面图片已经由美工设计好了,但如果使用layout技术把软件做成如图片所示的界面确实很困难,而且也比较耗时。Android通过WebView实现了JS代码与Java代码互相通信的功能,使的android软件的界面开发也可以采用HTML网页技术,这样,广大网页美工可以参与进android软件的界面开发工作,从而让程序员从中解脱出来。

XML配置

1
2
3
4
<WebView
android:id="@+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />

在项目的assets目录放入index.html文件

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
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
true<head>
truetrue<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
truetrue<title>Insert title here</title>
truetrue<script type="text/javascript">
function show(jsondata){
var jsonobjs = eval(jsondata);
var table = document.getElementById("personTable");
for(var y=0; y<jsonobjs.length; y++){
var tr = table.insertRow(table.rows.length);
var td1 = tr.insertCell(0);
var td2 = tr.insertCell(1);
td2.align = "center";
var td3 = tr.insertCell(2);
td3.align = "center";
truetruetruetrue td1.innerHTML = jsonobjs[y].name;
truetruetruetrue td2.innerHTML = jsonobjs[y].amount;
td3.innerHTML = "<a href='javascript:contact.call(\""+ jsonobjs[y].phone+ "\")'>"+ jsonobjs[y].phone+ "</a>";
truetruetruetruetrue}
truetruetrue}
truetrue</script>
true</head>
true<body onload="javascript:contact.showcontacts()">
true <table border="0" width="100%" id="personTable" cellspacing="0">
truetruetrue<tr>
truetruetruetrue<td width="30%">姓名</td>
truetruetruetrue<td width="30%" align="center">存款</td>
truetruetruetrue<td align="center">电话</td>
truetruetrue</tr>
truetrue</table>
true</body>
</html>

代码实现:

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
public class HtmlActivity extends Activity {
private WebView webView;
private Handler handler = new Handler();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webView = (WebView)this.findViewById(R.id.webView);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setSaveFormData(false);
webView.getSettings().setSavePassword(false);
webView.getSettings().setSupportZoom(false);
webView.addJavascriptInterface(new NcistJavaScript(), “ncist”);
truetrue//addJavascriptInterface方法中要绑定的Java对象
webView.setWebChromeClient(new NcistWebClient());
webView.loadUrl("file:///android_asset/index.html");
}

private final class NcistJavaScript{
public void personlist(){
webview.loadUrl("javascript:contactlist('"+ getPersonJson() + "')");
truetrue}
public void call(final String phone){
true startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:"+ phone)));
}
truetruepublic static String getPersonJson() {//生成json字符串
true try {
truetrueJSONObject jsonObject = new JSONObject();
truetruejsonObject.put("id", 56);
truetruejsonObject.put("name", "老张");
truetruejsonObject.put("phone", "5556");
truetrueJSONObject jsonObject2 = new JSONObject();
truetruejsonObject2.put("id", 89);
truetruejsonObject2.put("name", "老方");
truetruejsonObject2.put("phone", "5558");
truetrueJSONArray jsonArray = new JSONArray();
truetruejsonArray.put(jsonObject);
truetruejsonArray.put(jsonObject2);
truetruereturn jsonArray.toString();
true } catch (JSONException e) {
truetruee.printStackTrace();
true }
true return "";
true}
}
private final class NcistWebClient extends WebChromeClient{
@Override
truepublic boolean onJsAlert(WebView view, String url, String message, JsResult result) {
new AlertDialog.Builder(HtmlActivity.this)
true.setTitle("提示信息")
true.setMessage(message)
true.setPositiveButton("确定", new DialogInterface.OnClickListener(){
true public void onClick(DialogInterface dialoginterface, int i){}
true}).show();
truereturn true;
true} }}

 

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×