Android UI组件

对话框通知(Dialog Notification)


 

当你的应用需要显示一个进度条或需要用户对信息进行确认时,可以使用对话框来完成。

对话框和菜单一样,都是由Activity统一管理的,我们只要重新实现onCreateDialog(int id)传近来的不同的对话id,初始化并返回相应的对话框。Activity会将所有你已经初始化的对话框保存,下次呼出对话框的时候不会重新初始化。因此当需要动态更新我们的对话框时,就需要重新实现onPrepareDialog(int id,Dialog dialog)方法。

下面代码将打开一个对话框:

new AlertDialog.Builder(this)
		.setTitle("zyj标题")
		.setCancelable(false) //设置不能通过“后退”按钮关闭对话框
		.setMessage("zyj浏览我的bolg?")
		.setPositiveButton("确认",new DialogInterface.OnClickListener(){
			        public void onClick(DialogInterface dialoginterface, int i){
		    	    Uri uri = Uri.parse("http://justsee.iteye.com/");//打开链接
		    	    Intent intent = new Intent(Intent.ACTION_VIEW, uri);
		    	    startActivity(intent);
		    	}
		})
		.setNegativeButton("取消", new DialogInterface.OnClickListener() {
	        	  	 public void onClick(DialogInterface dialog, int id) {
	               			 dialog.cancel();
	        	 	  }
	    	})
	   	 .show();//显示对话框

 上面代码采用的是一个链式调用,像setTitle()、setMessage()这些方法,他们的返回值都是当前对话框对象。

单选框(RadioButton)


在radio.xml中:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent">
  <RadioGroup android:id="@+id/radioGroup"
		xmlns:android="http://schemas.android.com/apk/res/android"
		android:layout_width="wrap_content" android:layout_height="wrap_content">
		<RadioButton android:id="@+id/small" android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:text="small" />
		<RadioButton android:id="@+id/middle"
			android:layout_width="wrap_content" android:layout_height="wrap_content"
			android:text="middle" />
		<RadioButton android:id="@+id/big" android:layout_width="wrap_content"
			android:layout_height="wrap_content" android:text="big" />
	</RadioGroup>
</LinearLayout>

 在RadioButtonActivity中:

......

// xml实现
  setContentView(R.layout.radio);
  RadioGroup radioGroup = (RadioGroup) findViewById(R.id.radioGroup);
  radioGroup.check(R.id.middle);// 设置成默认选项
  Log.i(TAG,
    "默认选中的是:"
      + ((RadioButton) this.findViewById(radioGroup
        .getCheckedRadioButtonId())).getText()
        .toString());
  radioGroup
    .setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
     public void onCheckedChanged(RadioGroup group, int checkedId) {
      RadioButton radioButton = (RadioButton) findViewById(checkedId);
      Log.i(TAG, String.valueOf(radioButton.getText()));
     }
    });

/*

使用到RadioGroup和RadioButton(单选框),RadioGroup用于对单选框进行分组,相同组内的单选框只有一个单选框能被选中。(例子代码请见下方备注栏)
 RadioGroup.check(R.id.dotNet);将id名为dotNet的单选框设置成选中状态。
(RadioButton) findViewById(radioGroup.getCheckedRadioButtonId());//获取被选中的单选框。
RadioButton.getText();//获取单选框的值
调用setOnCheckedChangeListener()方法,处理单选框被选择事件,把RadioGroup.OnCheckedChangeListener实例作为参数传入

*/

 在RadioButtonActivity中:

final String[] items = { "海", "陆", "空" };
  new AlertDialog.Builder(this).setTitle("选择军队")
    .setItems(items, new DialogInterface.OnClickListener() {
     public void onClick(DialogInterface dialog, int item) {
      Toast.makeText(getApplicationContext(), items[item],
        Toast.LENGTH_SHORT).show();
     }
    }).show();// 显示对话框 

 在RadioButtonActivity中:

final String[] itemsa = { "红", "黄", "灯" };
  new AlertDialog.Builder(this)
    .setTitle("选择灯颜色")
    // setSingleChoiceItems()的第二个参数是设置默认选项,选项索引从0开始,-1代表不选择任何选项。
    .setSingleChoiceItems(itemsa, 1,
      new DialogInterface.OnClickListener() {
       public void onClick(DialogInterface dialog, int item) {
        Toast.makeText(getApplicationContext(),itemsa[item], Toast.LENGTH_SHORT).show();dialog.cancel();
       }
      }).show();
 多选框(CheckBox)


checkbox.xml界面

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">
  <CheckBox android:id="@+id/checkboxjava"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="java" />
  <CheckBox android:id="@+id/checkboxdotNet"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="dotNet" />
  <CheckBox android:id="@+id/checkboxphp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="PHP" />
    <Button android:id="@+id/checkboxButton"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="获取值" />
</LinearLayout>

 

 

  CheckBoxActivity中

 

............................
public class CheckBoxActivity extends Activity {
	private static final String TAG = "CheckBoxActivity";
	private List<CheckBox> checkboxs = new ArrayList<CheckBox>();

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
/*		每个多选框都是独立的,可以通过迭代所有多选框,然后根据其状态是否被选中再获取其值。
		 CheckBox.setChecked(true);//设置成选中状态。
		 CheckBox.getText();//获取多选框的值
		 调用setOnCheckedChangeListener()方法,处理多选框被选择事件,把CompoundButton.OnCheckedChangeListener实例作为参数传入*/
		setContentView(R.layout.checkbox);
		checkboxs.add((CheckBox) findViewById(R.id.checkboxdotNet));
		checkboxs.add((CheckBox) findViewById(R.id.checkboxjava));
		checkboxs.add((CheckBox) findViewById(R.id.checkboxphp));
		checkboxs.get(1).setChecked(true);// 设置成选中状态
		for (CheckBox box : checkboxs) {
			box.setOnCheckedChangeListener(listener);
		}
		Button button = (Button) findViewById(R.id.checkboxButton);
		button.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				List<String> values = new ArrayList<String>();
				for (CheckBox box : checkboxs) {
					if (box.isChecked()) {
						values.add(box.getText().toString());
					}
				}
				Toast.makeText(CheckBoxActivity.this, values.toString(), 1)
						.show();
			}
		});
}

	CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
		@Override
		// isChecked表示是否被选中
		public void onCheckedChanged(CompoundButton buttonView,
				boolean isChecked) {
			CheckBox checkBox = (CheckBox) buttonView;
			Log.i(TAG,
					"isChecked=" + isChecked + ",value=" + checkBox.getText());// 输出单选框的值
		}
	};
	
}

  

 CheckBoxActivity中

//多选项列表对话框
		final String[] items = {"java", ".net", "php"};
		new AlertDialog.Builder(this).setCancelable(false)
		.setTitle("选择语言")
		.setMultiChoiceItems(items, new boolean[]{false,true,false}, new DialogInterface.OnMultiChoiceClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which, boolean isChecked) {
				if(isChecked){
				Toast.makeText(getApplicationContext(), items[which], 
					Toast.LENGTH_SHORT).show();
				}
				}
			})
		.setPositiveButton("确认",
			new DialogInterface.OnClickListener(){
			public void onClick(DialogInterface dialoginterface, int i){
				dialoginterface.dismiss();//解除对话框
			 }
		})
		.show();//显示对话框

 下拉列表框(Spinner)


 

 在spinner.xml中(图一图二图三用)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
  <Spinner android:id="@+id/spinner"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"/>
</LinearLayout>

 stylespinner.xml中(图三用)

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
   android:id="@+id/contentTextView"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:background="#F4FDFF"
    />

 SpinnerActivity中(图一图二图三用)

public class SpinnerActivity extends Activity {
	private static final String TAG = "SpinnerActivity";

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.spinner);
		
		/*// 第二个参数为下拉列表框每一项的界面样式,该界面样式由Android系统提供,当然您也可以自定义
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
				android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);//换一种下拉框的式样
		adapter.add("java");
		adapter.add("dotNet");
		adapter.add("php");
		Spinner spinner = (Spinner) findViewById(R.id.spinner);
		spinner.setAdapter(adapter);
//		spinner.setSelection(0, false);
		spinner.setSelection(2);//设定默认值
		spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
			@Override
			public void onItemSelected(AdapterView<?> adapterView, View view,
					int position, long id) {
				Spinner spinner = (Spinner) adapterView;
				String itemContent = (String) adapterView
						.getItemAtPosition(position);
				Toast.makeText(getApplicationContext(), itemContent,Toast.LENGTH_SHORT).show();
			}

			@Override
			public void onNothingSelected(AdapterView<?> view) {
				Log.i(TAG, view.getClass().getName());
			}
		});*/
		/////////////////////////////采用javabean作为Adapter元素(图二)///////////////////////////////////////////////
	/*	 ArrayAdapter<Person> adapter = new ArrayAdapter<Person>(this, android.R.layout.simple_spinner_item);
	        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
	        adapter.add(new Person(12, "李明"));
	        adapter.add(new Person(100, "李明"));
	        adapter.add(new Person(62, "张天"));
	        Spinner spinner = (Spinner) findViewById(R.id.spinner);
	        spinner.setAdapter(adapter);
	        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
		@Override
		public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
			Spinner spinner = (Spinner)adapterView;
			Person person = (Person)adapterView.getItemAtPosition(position);
			Toast.makeText(getApplicationContext(), person.getId().toString(),Toast.LENGTH_SHORT).show();
		}
		@Override
		public void onNothingSelected(AdapterView<?> view) {
			Log.i(TAG,  view.getClass().getName());
		}
	        });*/
        /////////////////////////////自定义选项界面样式(图三)///////////////////////////////////////////////
		   //第二个参数为layout文件在R文件的id,第三个参数为TextView在layout文件的id
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.stylespinner, R.id.contentTextView);
        adapter.add("java");
        adapter.add("dotNet");
        adapter.add("php");
        Spinner spinner = (Spinner) findViewById(R.id.spinner);
        spinner.setAdapter(adapter);
        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
	@Override
	public void onItemSelected(AdapterView<?> adapterView, View view, int position, long id) {
		Spinner spinner = (Spinner)adapterView;
		String itemContent = (String)adapterView.getItemAtPosition(position);
		Toast.makeText(getApplicationContext(), itemContent,Toast.LENGTH_SHORT).show();
	}
	@Override
	public void onNothingSelected(AdapterView<?> view) {
		Log.i(TAG,  view.getClass().getName());
	}
        });

	}
}

 拖动条(SeekBar)

 

seekbar.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical">
  <SeekBar
    android:id="@+id/seekBar"
    android:layout_height="wrap_content"
    android:layout_width="fill_parent"/>
    
    <Button android:id="@+id/seekBarButton"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:text="获取值"
    />
</LinearLayout>

 SeekBarAvtivity中

private SeekBar seekBar;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.seekbar);
        seekBar = (SeekBar) findViewById(R.id.seekBar);
        seekBar.setMax(100);//设置最大刻度,即0到99
        seekBar.setProgress(30);//设置当前刻度
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
                Log.v("onProgressChanged()", String.valueOf(progress) + ", " + String.valueOf(fromTouch));
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {//开始拖动
                Log.v("onStartTrackingTouch()", String.valueOf(seekBar.getProgress()));
            }
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {//结束拖动
                Log.v("onStopTrackingTouch()", String.valueOf(seekBar.getProgress()));
            }
        });
        Button button = (Button)this.findViewById(R.id.seekBarButton);
        button.setOnClickListener(new View.OnClickListener() {			
	@Override
	public void onClick(View v) {
	Toast.makeText(getApplicationContext(), String.valueOf(seekBar.getProgress()), 1).show();
	}
         }); 
    }

 菜单(Menu)

 

·重写Activity的onCreateOptionsMenu(Menu menu)方法,该方法用于创建选项菜单,在用户按下手机的“Menu”按钮时就会显示创建好的菜单,在onCreateOptionsMenu(Menu menu)方法内部可以调用Menu.add()方法实现菜单的添加。

在第一次初始化了选项菜单后,如果我们需要动态更改选项菜单的话,则需要重新实现onPrepareOptionsMenu()回调方法,他会在每次显示选项菜单之前调用。
·重写Activity的onMenuItemSelected()方法,该方法用于处理菜单被选择事件

在MainActivity中:

private static final int MENU_ADD = Menu.FIRST;
private static final int MENU_UPDATE = Menu.FIRST + 1; 

...............................................................
...............................................................
 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
	menu.add(Menu.NONE, MENU_ADD, Menu.NONE, "添加");//参数:组ID,菜单项ID,排列顺序,显示标题  
	menu.add(Menu.NONE, MENU_UPDATE, Menu.NONE, "更新");
	return super.onCreateOptionsMenu(menu);
    }
    @Override
    public boolean onMenuItemSelected(int featureId, MenuItem item) {
	switch (item.getItemId()) {
	  case MENU_ADD:
	       Log.i(TAG, "add was selected");
	       return true;
	  case MENU_UPDATE:
	       Log.i(TAG, "update was selected");
	       return true;
	  default:
              return super.onMenuItemSelected(featureId, item);
	  }
    }

子菜单(SubMenu)

 

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
	menu.add(Menu.NONE, MENU_ADD, Menu.NONE, "添加").setCheckable(true);  
	menu.add(Menu.NONE, MENU_UPDATE, Menu.NONE, "更新");
	SubMenu sub = menu.addSubMenu("搜索");//子菜单
    sub.setIcon(android.R.drawable.ic_menu_search); sub.add(Menu.NONE,Menu.FIRST+8,Menu.NONE,"本地"); sub.add(Menu.NONE,Menu.FIRST+9,Menu.NONE,"网络");
	menu.add(Menu.NONE, Menu.FIRST+2, Menu.NONE, "保存").setIcon(android.R.drawable.ic_menu_save);
	menu.add(Menu.NONE, Menu.FIRST+3, Menu.NONE, "删除").setIcon(android.R.drawable.ic_menu_delete);
	menu.add(Menu.NONE, Menu.FIRST+4, Menu.NONE, "增加").setIcon(android.R.drawable.ic_menu_add);
	menu.add(Menu.NONE, Menu.FIRST+5, Menu.NONE, "电话").setIcon(android.R.drawable.ic_menu_call);
	menu.add(Menu.NONE, Menu.FIRST+6, Menu.NONE, "电话1");
	menu.add(Menu.NONE, Menu.FIRST+7, Menu.NONE, "电话2");

	return super.onCreateOptionsMenu(menu);
    }

上下文菜单(ContextMenu)

上下文菜单的初始化回调方法并不只调用一次,它会在每次呼出上下文菜单时被调用(public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) )。

方法一:注册

 

...
...
...
 registerForContextMenu(findViewById(R.id.contextMenu));//注册上下文菜单
...
...
@Override 
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
	      case C_MENU_NEW:
	          //做新建的那些事。
	          break;
	       case C_MENU_OPEN:
	          //做打开的那些事。
	          break;
	      }
		return super.onContextItemSelected(item);
	}
	@Override
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		menu.setHeaderTitle("这是上下文菜单");
		 menu.add(0, C_MENU_NEW, 0, "新建");
	        menu.add(0, C_MENU_OPEN, 0, "打开");
		super.onCreateContextMenu(menu, v, menuInfo);
	}

 方法二:监听

 

((Button)this.findViewById(R.id.contextMenu2)).setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() {
			
			@Override
			public void onCreateContextMenu(ContextMenu menu, View v,
					ContextMenuInfo menuInfo) {
				menu.setHeaderTitle("这是上下文菜单2");
				 menu.add(0, C_MENU_NEW, 0, "新建");
			        menu.add(0, C_MENU_OPEN, 0, "打开");
			}
		});

 

进度对话框(ProgressDialog)

·使用代码ProgressDialog.show(ProgressDialogActivity.this, "请稍等", "数据正在加载中...", true);创建并显示一个进度对话框。
·调用setProgressStyle()方法设置进度对话框风格。有两种风格:
     ProgressDialog.STYLE_SPINNER 旋体进度条风格 (为默认风格)
     ProgressDialog.STYLE_HORIZONTAL 横向进度条风格

在MainActivity中:

.........................................................
private ProgressDialog progressDialog;//进度对话框
   
	 private Runnable finishDialog = new Runnable() {
         @Override
         public void run() {           
         	progressDialog.dismiss();
         }
    };
	@Override
    public void onCreate(Bundle savedInstanceState) {
    	progressDialog = ProgressDialog.show(MainActivity.this, "请稍等", "病毒正在加载中...", true);
    	//开始一条专门处理耗时工作的线程
        new Thread(new Runnable(){
	        @Override
	        public void run() {
	           try {
			Thread.sleep(5*1000);//假设这项工作需要5秒才能完成
          //progressDialog.dismiss();//关闭进程对话框
			runOnUiThread(finishDialog);//要求运行在UI线程
		   } catch (InterruptedException e) {}
	        }
        }).start();   
................................................................

 创建进度条(ProgressBar)


 在布局xml文件中添加进度条代码:
<ProgressBar android:layout_width="fill_parent" android:layout_height="20px"
    style="?android:attr/progressBarStyleHorizontal"
    android:id="@+id/downloadbar"/>

在代码中操作进度条:
ProgressBar.setMax(100);//设置总长度为100
ProgressBar.setProgress(0);//设置已经开启长度为0,假设设置为50,进度条将进行到一半
一般用于下载的进度条

 

 Android中的通知(Notification)

通知用于在状态栏显示消息,消息到来时以图标方式表示,如下:



 在MainActivity中:

..................
 //获取通知管理器
        NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        int icon = android.R.drawable.stat_notify_chat;
        long when = System.currentTimeMillis();
        //新建一个通知,指定其图标和标题
        Notification notification = new Notification(icon, null, when);//第一个参数为图标,第二个参数为标题,第三个为通知时间
        Intent openintent = new Intent(this, CodeUIActivity.class);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0, openintent, 0);//当点击消息时就会向系统发送openintent意图
        notification.setLatestEventInfo(this, "标题", "内容", contentIntent);
        mNotificationManager.notify(0, notification);

..................

DatePicherDialog


 

new DatePickerDialog(this,
                    new OnDateSetListener() {
						
                        @Override
                        public void onDateSet(DatePicker v, int y,
                                int m, int d) {
                            /*
                             * 这是设置好日期后的回调函数,
                             * 可以根据设置的内容更新用户界面
                             * 或者系统时间。
                             */
                        }
                     }, c.get(Calendar.YEAR),
                    c.get(Calendar.MONTH), 
                    c.get(Calendar.DAY_OF_MONTH))

TimePicherDialog

 

new TimePickerDialog(this,
                    new  OnTimeSetListener() {
						@Override
						public void onTimeSet(TimePicker arg0, int arg1, int arg2) {
							 /*
                             * 这是设置好时间后的回调函数,
                             * 可以根据设置的内容更新用户界面
                             * 或者系统时间。
                             */
							
						}
					}, c.get(Calendar.HOUR_OF_DAY),
                    c.get(Calendar.MINUTE), 
                    false);

AnalogClock     和   DigitalClock

 

     <AnalogClock  
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" />
    <DigitalClock  
        android:layout_width="wrap_content" 
        android:layout_height="wrap_content" />

ToggleButton

 

      <ToggleButton 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

在Activity中编程实现UI   

在CodeUIActivity中:

TextView textView = new TextView(this);
	        textView.setText(R.string.code_UI);
	        textView.setId(90);
	        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
	        		ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
	        linearLayout.addView(textView, params);
	        
	        params = new LinearLayout.LayoutParams(
	        		ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
	        setContentView(linearLayout, params);

用html作为UI

Android通过WebView实现了JS代码与Java代码互相通信的功能,使的android软件的界面开发也可以采用HTML网页技术。



 主要代码

/assets/index.html

<script type="text/javascript">
	function show(jsondata){//[{id:21,name:"xxx",mobile:"12332213"},{}]
	        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);
		        //设置列内容和属性
		        td1.innerHTML = jsonobjs[y].id; 
		        td2.innerHTML = jsonobjs[y].name; 
		        td3.innerHTML = "<a href='javascript:cactus.call(\""+ jsonobjs[y].mobile+ "\")'>"+ jsonobjs[y].mobile+ "</a>"; 
			}
	}
</script>
</head>
<!-- js代码通过webView调用其插件中的java代码 -->
<body onload="javascript:cactus.personlist()">
   <table border="0" width="100%" id="personTable" cellspacing="0">
		<tr>
			<td width="20%">编号</td>
			<td width="30%" align="center">姓名</td>
			<td >电话</td>
		</tr>
	</table>
	<a href="javascript:window.location.reload()">刷新</a>
</body>

HtmlActivity.java

private WebView webView;
	private Handler handler = new Handler();// 异步使用

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.htmlui);

		webView = (WebView) this.findViewById(R.id.webview);
		webView.getSettings().setJavaScriptEnabled(true);// 允许JavaScript
		webView.getSettings().setSaveFormData(false);
		webView.getSettings().setSavePassword(false);
		webView.getSettings().setSupportZoom(false);// 不准改变大小
		webView.addJavascriptInterface(new CactusJavaScript(this, handler),
				"cactus");// addJavascriptInterface方法中要绑定的Java对象
		webView.setWebChromeClient(new CactusWebClient());
		webView.loadUrl("file:///android_asset/index.html");
	}

	private final class CactusWebClient extends WebChromeClient {
		// WebView上alert是弹不出来东西的,需要定制你的WebChromeClient处理弹出
		@Override
		public boolean onJsAlert(WebView view, String url, String message,
				JsResult result) {
			new AlertDialog.Builder(HtmlActivity.this)
					.setTitle("提示信息")
					.setMessage(message)
					.setPositiveButton("确定",
							new DialogInterface.OnClickListener() {
								public void onClick(
										DialogInterface dialoginterface, int i) {
								}
							}).show();
			return true;
		}
	}

CactusJavaScript.java

private Context context;
	private WebView webView;
	private Handler handler;
	public CactusJavaScript(Context context, Handler handler) {
		super();
		this.context = context;
		this.webView = (WebView) ((Activity)context).findViewById(R.id.webview);
		this.handler = handler ;
	}

	public void personlist() {
		handler.post(new Runnable() {// Handler与调用者处于同一线程,如果Handler里面做耗时的动作,调用者线程会阻塞
			public void run() {
				webView.loadUrl("javascript:show('" + getPersonJson()
						+ "')");
			}
		});
	}

	public void call(final String phone) {
		handler.post(new Runnable() {
			public void run() {
				context.startActivity(new Intent(Intent.ACTION_CALL, Uri.parse("tel:"
						+ phone)));
				
			}
		});
	}

	public  String getPersonJson() {// 生成json字符串
		try {
			List<Person> persons=getContacts();
			JSONArray jsonArray=new JSONArray();
			for (Person person : persons) {
				JSONObject jsonObject=new JSONObject();
				jsonObject.put("id", person.getId());
				jsonObject.put("name", person.getName());
				jsonObject.put("mobile", person.getMobile());
				jsonArray.put(jsonObject);
			}
			return jsonArray.toString();
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return "";
	}
	

	public List<Person> getContacts(){
		 List<Person>  persons = new ArrayList<Person>();
		 persons.add(new Person(78, "张飞", "1384949494"));
		 persons.add(new Person(12, "李静", "194505555"));
		 persons.add(new Person(89, "赵薇", "1785959595"));
		return persons;
	}