Android笔记-Dialog,动画,传感器等

本文详细介绍了 Android 中的各种 UI 控件及其使用方法,包括通知、对话框、下拉列表框、进度条等,并提供了丰富的代码示例。

Android的状态栏通知(Notification)

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

如果需要查看消息,可以拖动状态栏到屏幕下方即可查看消息。

发送消息的代码如下:

//获取通知管理器

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);//第一个参数为图标,第二个参数为标题,第三个为通知时间

notification.defaults = Notification.DEFAULT_SOUND;//发出默认声音

Intent openintent = new Intent(this, OtherActivity.class);

PendingIntent contentIntent = PendingIntent.getActivity(this, 0, openintent, 0);//当点击消息时就会向系统发送openintent意图

notification.setLatestEventInfo(this, “标题”“我是内容", contentIntent);

mNotificationManager.notify(0, notification);//第一个参数为自定义的通知唯一标识

 对话框通知(Dialog Notification)

Java语言:
//当你的应用需要显示一个进度条或需要用户对信息进行确认时,可以使用对话框来完成。
//下面代码将打开一个如右图所示的对话框:
new  AlertDialog . Builder( context)
. setTitle( "java培训")
. setCancelable( false//设置不能通过“后退”按钮关闭对话框
. setMessage( "浏览传智播客网站?")
. setPositiveButton( "确认" ,
new  DialogInterface . OnClickListener (){
public  void  onClick( DialogInterface  dialoginterface ,  int  i ){
Uri  uri  =  Uri . parse( "http://www.itcast.cn/"); //打开链接
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()这些方法,他们的返回值都是当前对话框对象。

 

创建带单选项列表的对话框

Java语言:
//下面代码将打开一个如右上图所示的选项列表对话框:
final  String []  items  =  { "java" ,  ".net" ,  "php" };
new  AlertDialog . Builder( SenderNotificationActivity . this ). setTitle( "选择语言")
. setItems( items ,  new  DialogInterface . OnClickListener()  {
public  void  onClick( DialogInterface  dialog ,  int  item{
Toast . makeText( getApplicationContext (),  items [ item ],
Toast . LENGTH_SHORT ). show();
}
}). show(); //显示对话框
//下面代码将打开一个如右下图所示的带单选框的列表对话框:
final  String []  items  =  { "java" ,  ".net" ,  "php" };
new  AlertDialog . Builder( SenderNotificationActivity . this ). setTitle( "选择语言")
. setSingleChoiceItems( items ,  1 ,  new  DialogInterface . OnClickListener()  {
public  void  onClick( DialogInterface  dialog ,  int  item{
Toast . makeText( getApplicationContext (),  items [ item ],
Toast . LENGTH_SHORT ). show();
dialog . cancel();
}
}). show(); //显示对话框
//setSingleChoiceItems()的第二个参数是设置默认选项,
//选项索引从0开始,-1代表不选择任何选项。

 

创建带多选项列表的对话框

Java语言:
//下面代码将打开一个如右下图所示的多选项列表对话框:
final  String []  items  =  { "java" ,  ".net" ,  "php" };
new  AlertDialog . Builder( SenderNotificationActivity . 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(); //显示对话框

 

进度对话框(ProgressDialog)

使用代码ProgressDialog.show(ProgressDialogActivity.this, "请稍等", "数据正在加载中...", true);创建并显示一个进度对话框。

调用setProgressStyle()方法设置进度对话框风格。有两种风格:

ProgressDialog.STYLE_SPINNER 旋体进度条风格 (为默认风格)

ProgressDialog.STYLE_HORIZONTAL 横向进度条风格

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

 

单选框(RadioButton)

要完成单选框显示,我们需要使用到RadioGroupRadioButton(单选框)RadioGroup用于对单选框进行分组,相同组内的单选框只有一个单选框能被选中。(例子代码请见下方备注栏)

RadioGroup.check(R.id.dotNet);id名为dotNet的单选框设置成选中状态。

(RadioButton) findViewById(radioGroup.getCheckedRadioButtonId());//获取被选中的单选框。

RadioButton.getText();//获取单选框的值

调用setOnCheckedChangeListener()方法,处理单选框被选择事件,把RadioGroup.OnCheckedChangeListener实例作为参数传入。

Java语言:
//界面设计:
<? xml  version = "1.0"  encoding = "utf-8" ?>
< LinearLayout  xmlns: android = "http://schemas.android.com/apk/res/android"
android: orientation = "vertical"
android: layout_width = "fill_parent"
android: layout_height = "fill_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/java"
android: layout_width = "wrap_content"
android: layout_height = "wrap_content"
android: text = "java"  />
< RadioButton  android: id = "@+id/dotNet"
android: layout_width = "wrap_content"
android: layout_height = "wrap_content"
android: text = "dotNet"  />
< RadioButton  android: id = "@+id/php"
android: layout_width = "wrap_content"
android: layout_height = "wrap_content"
android: text = "PHP"  />
</ RadioGroup >
</ LinearLayout > //处理程序:
public  void  onCreate( Bundle  savedInstanceState{
......
RadioGroup  radioGroup  = ( RadioGroupfindViewById( R . id . radioGroup);
radioGroup . setOnCheckedChangeListener( new  RadioGroup . OnCheckedChangeListener()  {
public  void  onCheckedChanged( RadioGroup  group ,  int  checkedId{
RadioButton  radioButton  = ( RadioButtonfindViewById( checkedId);
Log . i( TAG ,  String . valueOf( radioButton . getText()));
}
});
}

 

多选框(CheckBox)

每个多选框都是独立的,可以通过迭代所有多选框,然后根据其状态是否被选中再获取其值。

CheckBox.setChecked(true);//设置成选中状态。

CheckBox.getText();//获取多选框的值

调用setOnCheckedChangeListener()方法,处理多选框被选择事件,把CompoundButton.OnCheckedChangeListener实例作为参数传入。

Java语言:
//界面设计:
<? 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 = "fill_parent" >
< 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 > //代码处理:
public  class  CheckBoxActivity  extends  Activity  {
private  static  final  String  TAG  =  "CheckBoxActivity";
private  List < CheckBox >  checkboxs  =  new  ArrayList < CheckBox >(); @Override
public  void  onCreate( Bundle  savedInstanceState{
super . onCreate( savedInstanceState);
setContentView( R . layout . checkbox);
checkboxs . add(( CheckBoxfindViewById( R . id . checkboxdotNet));
checkboxs . add(( CheckBoxfindViewById( R . id . checkboxjava));
checkboxs . add(( CheckBoxfindViewById( 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
public  void  onCheckedChanged( CompoundButton  buttonView ,  boolean  isChecked{
CheckBox  checkBox  = ( CheckBoxbuttonView;
Log . i( TAG ,  "isChecked=" +  isChecked  + ",value=" +  checkBox . getText()); //输出单选框的值
}
};
}

 

下拉列表框(Spinner)

 Spinner.getItemAtPosition(Spinner.getSelectedItemPosition());获取下拉列表框的值

调用setOnItemSelectedListener()方法,处理下拉列表框被选择事件,把AdapterView.OnItemSelectedListener实例作为参数传入

Java语言:
//界面设计:
<? 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 > //代码处理:
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  = ( SpinnerfindViewById( 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);
}
@Override
public  void  onNothingSelected( AdapterView <?>  view{
Log . i( TAG ,   view . getClass (). getName());
}
});
}
}

 

下拉列表框—采用javabean作为Adapter元素

很多时候显示在下拉列表框的值并不是希望得到的值,如果要做一个联系人下拉列表框,列表框列出的是联系人的姓名,因为姓名有可能相同,所以我们希望得到的值应该为该联系人的id,要实现这种需求我们需要自定义Adapter,当然自定义Adapter需要我们编写一小段代码,如果我们不想编写Adapter,又能实现我们的需求,那是最好不过的了。通过观察ArrayAdaptergetView(int position, View convertView, ViewGroup parent)的内部代码发现,如果为ArrayAdapter指定的实际泛型参数类型没有实现CharSequence(字符串)接口,将会调用该类型对象的toString()向下拉列表框输出显示值。利用这个特点我们可以重写javaBeantoString()向下拉列表框提供显示值。

Java语言:
//界面设计:
<? 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 > //代码处理:
public  class  SpinnerActivity  extends  Activity  {
private  static  final  String  TAG  =  "SpinnerActivity";
@Override
public  void  onCreate( Bundle  savedInstanceState{
super . onCreate( savedInstanceState);
setContentView( R . layout . spinner);
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  = ( SpinnerfindViewById( 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);
}
@Override
public  void  onNothingSelected( AdapterView <?>  view{
Log . i( TAG ,   view . getClass (). getName());
}
});
}
} Person . java :
public  class  Person  {
private  Integer  id;
private  String  name; public  Person( Integer  id ,  String  name{
this . id  =  id;
this . name  =  name;
}
public  Integer  getId()  {
return  id;
}
public  void  setId( Integer  id{
this . id  =  id;
}
public  String  getName()  {
return  name;
}
public  void  setName( String  name{
this . name  =  name;
}
@Override
public  String  toString()  {
return  name;
}
}

 

下拉列表框--自定义选项界面样式

Spinner.getItemAtPosition(Spinner.getSelectedItemPosition());获取下拉列表框的值

调用setOnItemSelectedListener()方法,处理下拉列表框被选择事件,把AdapterView.OnItemSelectedListener实例作为参数传入

Java语言:
//主界面设计:
<? 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"
/> //代码处理:
public  class  SpinnerActivity  extends  Activity  {
private  static  final  String  TAG  =  "SpinnerActivity";
@Override
public  void  onCreate( Bundle  savedInstanceState{
super . onCreate( savedInstanceState);
setContentView( R . layout . spinner);
//第二个参数为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  = ( SpinnerfindViewById( 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);
}
@Override
public  void  onNothingSelected( AdapterView <?>  view{
Log . i( TAG ,   view . getClass (). getName());
}
});
}
}

 

拖动条(SeekBar)

SeekBar.getProgress()获取拖动条当前值

调用setOnSeekBarChangeListener()方法,处理拖动条值变化事件,把SeekBar.OnSeekBarChangeListener实例作为参数传入。

Java语言:
//主界面设计:
<? 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 > //代码处理:
public  class  SeekBarActivity  extends  Activity  {
private  SeekBar  seekBar;
@Override
public  void  onCreate( Bundle  savedInstanceState{
super . onCreate( savedInstanceState);
setContentView( R . layout . seekbar);
seekBar  = ( SeekBarfindViewById( R . id . seekBar);
seekBar . setMax( 100); //设置最大刻度
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( SeekBarActivity . this ,  String . valueOf( seekBar . getProgress ()),  1 ). show();
}
});
}
}

 

菜单(Menu)

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

重写ActivityonMenuItemSelected()方法,该方法用于处理菜单被选择事件

 

通过手机上提供的“MENU”按钮可以打开菜单,如果希望通过代码打开菜单,可以调用ActivityopenOptionsMenu()方法。

Java语言:
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{
menu . add( Menu . NONE ,  MENU_ADD ,  Menu . NONE ,  "添加");
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);
}
}
}

 

进度条(ProgressBar)

Java语言:
//在布局xml文件中添加进度条代码:
< ProgressBar
android: layout_width = "fill_parent"
android: layout_height = "20px"
style = "?android:attr/progressBarStyleHorizontal"
android: id = "@+id/downloadbar" /> //在代码中操作进度条:
ProgressBar . setMax( 100); //设置最大刻度
ProgressBar . setProgress( 0); //设置进度条的当前刻度,如果进度条的最大刻度为100,当前刻度为50,进度条将进行到一半。

 

输入内容自动完成文本框(AutoCompleteTextView )

AutoCompleteTextViewEditText组件类似,都可以输入文本。

AutoCompleteTextView组件可以和一个字符串数组或List对象

绑定,当用户输入两个及以上字符时,系统将在

AutoCompleteTextView组件下方列出字符串数组中所有以输入

字符开头的字符串,这一点和www.google.com的搜索框非常相似,

当输入某一个要查找的字符串时,google搜索框就会列出以这个

字符串开头的最热门的搜索字符串列表。

<AutoCompleteTextView

android:layout_width="fill_parent“  android:layout_height="wrap_content

<!– completionThreshold 指定至少输入几个字符后才会出现自动提示功能 à

android:completionThreshold="1“  

android:id="@+id/name" />

 

public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);

setContentView(R.layout.main);

String[] names = {"老张", "老方", "老毕", "李明" , "李丽", "陈江", "abc", "acc"};

AutoCompleteTextView nameText = (AutoCompleteTextView)this.findViewById(R.id.name);

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, names);

nameText.setAdapter(adapter);

}

 多次输入-内容自动完成文本框(MultiAutoCompleteTextView)

除了AutoCompleteTextView控件外,我们还可以使用MultiAutoCompleteTextView控件来完成连续输入的功能。也就是说,当输入完一个字符串后,在该字符串后面输入一个逗号(,),在逗号前后可以有任意多个空格,然后再输入一个字符串,仍然会显示自动提示列表。

使用MultiAutoCompleteTextView时,需要为它的setTokenizer方法指定MultiAutoCompleteTextView.CommaTokenizer类对象实例,

该对象表示采用逗号作为输入多个字符串的分隔符。

 

< MultiAutoCompleteTextView

android:layout_width="fill_parent“  android:layout_height="wrap_content

<!– completionThreshold 指定至少输入几个字符后才会出现自动提示功能à

android:completionThreshold="1“  

android:id="@+id/name" />

 

public void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);

setContentView(R.layout.main);

String[] names = {"老张", "老方", "老毕", "李明" , "李丽", "陈江", "abc", "acc"};

MultiAutoCompleteTextView nameText = (MultiAutoCompleteTextView)this.findViewById(R.id.name);

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line,    names);

nameText.setAdapter(adapter);

nameText.setTokenizer(new MultiAutoCompleteTextView.CommaTokenizer());}

 NinePatch图片

NinePatch是一种很有用的PNG图片格式,它可以在特定区域随文字大小进行缩放。如下:

从上图可以看到,背景图片的中间区域会随着文字的大小进行缩放。背景图片是一张NinePatch图片。 NinePatch图片可以使用android自带的draw9patch工具来制作,该工具在SDK安装路径的tools目录下。执行该工具,然后点击“File->open 9-path”打开一张用于制作NinePatch图片的原来图片。在画布的上方和左方的边上画线指定缩放区域,

勾选“Show patches”可显示画定的区域,绿色

为固定大小区域,红色为缩放区域,文字会摆放在红色

区域。制作完后,点击“File”à “save 9-path”保存

图片,draw9patch工具会自动为图片加上*.9.png后缀。

把制作好的图片拷贝进项目的res/drawable目录,然后

编写代码。如下:

 

<TextView android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="退出" android:textColor="#330000"

android:background="@drawable/button"/>

 手势识别

第一步:建立手势库

使用SDK自带例子GestureBuilder建立手势库(位置:android-sdk-windows\samples\android-8\GestureBuilder)。使用GestureBuilder之前,你需要恢复其到开发环境,然后进行编绎并部署到手机上。此时,就可以使用GestureBuilder建立手势库,生成的手势库文件在SCDard上,默认文件名称为:gestures

 

第二步:在应用中加载手势库文件,然后开发手势识别代码。

把手势库文件gestures文件拷贝到项目的res/raw目录下。然后在布局文件中添加用于手势绘制的View

<android.gesture.GestureOverlayView

android:id="@+id/gestures"

android:layout_width="fill_parent“ android:layout_height="0dip"

android:layout_weight="1.0"

/>

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

 

手势识别代码见下方

Java语言:
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 {
@Override
public  void  onGesturePerformed( GestureOverlayView  overlay ,  Gesture  gesture{
if( state ){
List < Prediction >  predictions  =  mLibrary . recognize( gesture); //从手势库中查询匹配的内容,匹配的结果可能包括多个相似的结果,匹配度高的结果放在最前面
if (! predictions . isEmpty ()){
Prediction  prediction  =  predictions . get( 0);
//prediction的score属性代表了与手势的相似程度
//prediction的name代表手势对应的字母
if( prediction . score  >  1 ){
addressText . setText( prediction . name);
}
}
}
}
}
}

 

动画(Animation)

Android提供了2种动画:

1> Tween动画,通过对 View 的内容进行一系列的图形变换 (包括平移、缩放、旋转、改变透明度)来实现动画效果。动画效果的定义可以采用XML来做也可以采用编码来做。Tween动画有4种类型:

2> Frame动画,即顺序播放事先做好的图像,跟电影类似。开发步骤:

1)把准备好的图片放进项目res/ drawable下。

2)在项目的res目录下创建文件夹anim,然后在anim文件夹下面定义动画XML文件,文件名称可以自定义。当然也可以采用编码方式定义动画效果(使用AnimationDrawable类)。

3)为View控件绑定动画效果。调用代表动画的AnimationDrawablestart()方法开始动画。

Java语言:
本例要实现对 ImageView 对象进行渐变尺寸缩放动画效果
1 >  在项目的 res 目录下创建文件夹 anim ,然后在 anim 文件夹下面定义动画 XML 文件 , 文件名称可以自定义,如: scale . xml ,内容如下:
<? xml  version = "1.0"  encoding = "utf-8" ?>
< set  xmlns: android = "http://schemas.android.com/apk/res/android" >
< scale  android: interpolator = "@android:anim/accelerate_decelerate_interpolator"
android: fromXScale = "0.0"
android: toXScale = "5"
android: fromYScale = "0.0"
android: toYScale = "5"
android: pivotX = "50%"
android: pivotY = "50%"
android: fillAfter = "false"
android: duration = "5000"
/>
</ set >
动画的进度使用 interpolator 控制, android 提供了几个 Interpolator  子类,实现了不同的速度曲线,如 LinearInterpolator 实现了匀速效果、 Accelerateinterpolator 实现了加速效果、 DecelerateInterpolator 实现了减速效果等。还可以定义自己的 Interpolator 子类,实现抛物线、自由落体等物理效果。 fromXScale (浮点型)  属性为动画起始时 X 坐标上的缩放尺寸
fromYScale (浮点型)  属性为动画起始时 Y 坐标上的缩放尺寸
toXScale (浮点型)    属性为动画结束时 X 坐标上的缩放尺寸
toYScale (浮点型)    属性为动画结束时 Y 坐标上的缩放尺寸
说明 :  以上四种属性值
0.0 表示收缩到没有
1.0 表示正常无缩放
值小于 1.0 表示收缩
值大于 1.0 表示放大
pivotX (浮点型)      属性为动画相对于物件的 X 坐标的开始位置
pivotY (浮点型)      属性为动画相对于物件的 Y 坐标的开始位置
说明 :
以上两个属性值  0 %- 100 % 中取值
50 % 为物件的 X Y 方向坐标上的中点位置
duration (长整型)属性为动画持续时间  。说明 :    时间以毫秒为单位
fillAfter (布尔型)属性当设置为 true ,该动画转化在动画结束后被应用 2 >  layout 文件添加 < ImageView > 节点:
<? xml  version = "1.0"  encoding = "utf-8" ?>
< LinearLayout  xmlns: android = "http://schemas.android.com/apk/res/android"
android: orientation = "horizontal"
android: layout_width = "fill_parent"
android: layout_height = "fill_parent"
>
< ImageView
android: layout_width = "wrap_content"
android: layout_height = "wrap_content"
android: src = "@drawable/icon"
android: id = "@+id/imageView"
/>
</ LinearLayout >
说明:除了可以对 < ImageView > 实现动画效果,其实也可以对其他 View 实现动画效果,如: < TextView > 3 > Activity 里对 ImageView 使用前面定义好的动画效果:
public  class  AnimationActivity  extends  Activity  {
@Override
public  void  onCreate( Bundle  savedInstanceState{
super . onCreate( savedInstanceState);
setContentView( R . layout . main);
ImageView  imageView  = ( ImageView) this . findViewById( R . id . imageView);
//加载动画XML文件,生成动画指令
Animation  animation  =  AnimationUtils . loadAnimation( this ,  R . anim . scale);
//开始执行动画
imageView . startAnimation( animation);
}
} 备注:上面采用的是 xml 文件定义动画效果,作为代替,也可以采用编码方式实现。下面采用编码方式实现上述例子同样的效果:
public  class  AnimationActivity  extends  Activity  {
@Override
public  void  onCreate( Bundle  savedInstanceState{
super . onCreate( savedInstanceState);
setContentView( R . layout . main);
ImageView  imageView  = ( ImageView) this . findViewById( R . id . imageView);
ScaleAnimation  animation  =  new  ScaleAnimation( 0.0f ,  5 f ,  0.0f ,  5 f ,
Animation . RELATIVE_TO_SELF ,  0.5f ,  Animation . RELATIVE_TO_SELF ,  0.5f);
animation . setDuration( 5000);  //设置持续时间5秒
imageView . startAnimation( animation);
}
} =====================   Frame 动画例子   ===============================
1 )把准备好的图片放进项目 res /  drawable 下。
图片有: girl_1 . gif ,  girl_2 . gif ,  girl_3 . gif
2 )在项目的 res 目录下创建文件夹 anim ,然后在 anim 文件夹下面定义动画 XML 文件,文件名称可以自定义 , 如: frame . xml
<? xml  version = "1.0"  encoding = "utf-8" ?>
< animation - list  xmlns: android = "http://schemas.android.com/apk/res/android"
android: oneshot = "false" >
< item  android: drawable = "@drawable/girl_1"  android: duration = "200"  />
< item  android: drawable = "@drawable/girl_2"  android: duration = "200"  />
< item  android: drawable = "@drawable/girl_3"  android: duration = "200"  />
</ animation - list >
上面的 XML 就定义了一个 Frame 动画,其包含 3 帧动画, 3 帧动画中分别应用了 drawable 中的 3 张图片: girl_1 . gif , girl_2 . gif ,  girl_3 . gif ,每帧动画持续 200 毫秒。 android: oneshot 属性如果为 true ,表示动画只播放一次停止在最后一帧上,如果设置为 false 表示动画循环播放。
3 )为 View 控件绑定动画效果,调用代表动画的 AnimationDrawable start() 方法开始动画。
public  class  FrameActivity  extends  Activity  {
private  AnimationDrawable  animationDrawable;
@Override
public  void  onCreate( Bundle  savedInstanceState{
super . onCreate( savedInstanceState);
setContentView( R . layout . main);
ImageView  imageView  = ( ImageView) this . findViewById( R . id . imageView);
imageView . setBackgroundResource( R . anim . frame);
animationDrawable  = ( AnimationDrawableimageView . getBackground();
}
@Override
public  boolean  onTouchEvent( MotionEvent  event{
if ( event . getAction()  ==  MotionEvent . ACTION_DOWN{ //按下
animationDrawable . start();
return  true;
}
return  super . onTouchEvent( event);
}
}
有一点需要强调的是:启动 Frame 动画的代码 animationDrawable . start(); 不能应用在 OnCreate() 方法中,因为在 OnCreate()   AnimationDrawable 还没有完全的与 ImageView 绑定。在 OnCreate() 中启动动画,只能看到第一张图片。这里在拖曳事件中实现的。

 

android样式和主题(style&theme)

XML语言:
android中的样式和CSS样式作用相似,都是用于为界面元素定义显示风格,它是一个包含一个或者多个view控件属性的集合。如:需要定义字体的颜色和大小。
在CSS中是这样定义的:
<style>
.itcast{COLOR:#0000CC;font-size:18px;}
</style>
可以像这样使用上面的css样式: <div  class= "itcast" >传智播客 </div>
在Android中可以这样定义样式:
在res/values/styles.xml文件中添加以下内容
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style  name= “itcast” >  <!-- 为样式定义一个全局唯一的名字-->
<item  name= “android:textSize” >18px </item>  <!-- name属性的值为使用了该样式的View控件的属性 -->
<item  name= "android:textColor" >#0000CC </item>
</style>
</resources>
在layout文件中可以像下面这样使用上面的android样式:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout  xmlns:android= "http://schemas.android.com/apk/res/android"  .... >
<TextView  style= "@style/itcast"
.....   />
</LinearLayout>
XML语言:
<style>元素中有一个parent属性。这个属性可以让当前样式继承一个父样式,并且具有父样式的值。当然,如果父样式的值不符合你的需求,你也可以对它进行修改,如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style  name= "itcast" >
<item  name= "android:textSize" >18px </item>  <!-- name属性为样式要用在的View控件持有的属性 -->
<item  name= "android:textColor" >#0000CC </item>
</style>
<style  name= "subitcast"  parent= "@style/itcast" >
<item  name= "android:textColor" >#FF0000 </item>
</style>
</resources>

 

 android中主题也是用于为应用定义显示风格,它的定义和样式的定义相同,如下:

<?xml version="1.0" encoding="utf-8"?>

<resources>

<style name=itcastTheme">

<item name=android:windowNoTitle>true</item> <!– 没标题 à

<item name=android:windowFullscreen>?android:windowNoTitle</item> <!– 全屏显示 à

</style>

</resources>

上面“?android:windowNoTitle”中的问号用于引用在当前主题中定义过的资源的值。下面代码显示在AndroidManifest.xml中如何为应用设置上面定义的主题:

<application android:icon="@drawable/icon" android:label="@string/app_name"

android:theme="@style/itcastTheme">

......

</application>

除了可以在AndroidManifest.xml中设置主题,同样也可以在代码中设置主题,如下:

setTheme(R.style.itcastTheme);

尽管在定义上,样式和主题基本相同,但是它们使用的地方不同。样式用在单独的View,如:EditTextTextView等;主题通过AndroidManifest.xml中的<application><activity>用在整个应用或者某个 Activity,主题对整个应用或某个Activity进行全局性影响。如果一个应用使用了主题,同时应用下的view也使用了样式,那么当主题和样式属性发生冲突时,样式的优先级高于主题。

另外android系统也定义了一些主题,例如:<activity android:theme=@android:style/Theme.Dialog>,该主题可以让Activity看起来像一个对话框,还有透明主题:@android:style/Theme.Translucent 。如果需要查阅这些主题,可以在文档的referenceàandroid-->R.style 中查看。

 使用html开发软件界面

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

HTML语言:
在项目的assets目录放入index.html文件
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta  http-equiv= "Content-Type"  content= "text/html; charset=UTF-8" >
<title>Insert title here </title>
<style  type= "text/css" >
A  {
COLOR :  #FFFFFFTEXT - DECORATION :  none
}
</style>
<script  type= "text/javascript" >
function  show( jsondata ){
var  jsonobjs  =  eval( jsondata);
var  table  =  document . getElementById( "personTable");
for( var  y = 0y < jsonobjs . lengthy ++ ){
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  =  "<a href='javascript:itcast.call(\"5554\")'>" +  jsonobjs [ y ]. name  +  "</a>";
td3 . innerHTML  =  jsonobjs [ y ]. phone;
}
}
</script>
</head>
<body  bgcolor= "#000000"  text= "#FFFFFF"  style= "margin:0 0 0 0"  onload= "javascript:itcast.personlist()" >
<table  border= "0"  width= "100%"  id= "personTable"  cellspacing= "0" >
<tr>
<td  width= "15%" >编号 </td><td  align= "center" >姓名 </td><td  width= "15%" >电话 </td>
</tr>
</table>
<a  href= "javascript:window.location.reload()" >刷新 </a>
</body>
</html>
Java语言:
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  ItcastJavaScript (),  itcast ); //addJavascriptInterface方法中要绑定的Java对象
webView . setWebChromeClient( new  ItcastWebClient());
webView . loadUrl( "file:///android_asset/index.html");
} private  final  class  ItcastJavaScript {
public  void  personlist (){
webview . loadUrl( "javascript:contactlist('" +  getPersonJson()  +  "')");
} public  void  call( final  String  phone ){
startActivity( new  Intent( Intent . ACTION_CALL ,  Uri . parse( "tel:" +  phone)));
}
public  static  String  getPersonJson()  { //生成json字符串
try  {
JSONObject  jsonObject  =  new  JSONObject();
jsonObject . put( "id" ,  56);
jsonObject . put( "name" ,  "老张");
jsonObject . put( "phone" ,  "5556");
JSONObject  jsonObject2  =  new  JSONObject();
jsonObject2 . put( "id" ,  89);
jsonObject2 . put( "name" ,  "老方");
jsonObject2 . put( "phone" ,  "5558");
JSONArray  jsonArray  =  new  JSONArray();
jsonArray . put( jsonObject);
jsonArray . put( jsonObject2);
return  jsonArray . toString();
}  catch ( JSONException  e{
e . printStackTrace();
}
return  "";
}
}
private  final  class  ItcastWebClient  extends  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;
}
}
}

 

安装外部程序

首先需要AndroidManifest.xml中加入安装程序权限:

<!-- 安装程序权限 -->

<uses-permission android:name="android.permission.INSTALL_PACKAGES"/>

 

第二步把安装程序添加进SDCard。如把文件名为” sogouinput_android_1.40_sweb.apk.zip”的sogou拼音输入法安装文件放进SDCard。可以点击下面按钮:

第三步在程序中添加以下代码:

Intent intent = new Intent();

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.setAction(android.content.Intent.ACTION_VIEW);

intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory(), "sogouinput_android_1.40_sweb.apk.zip")),"application/vnd.android.package-archive");

startActivity(intent);

关闭应用

当应用不再使用时,通常需要关闭应用,可以使用以下两种方法关闭android应用:

 

第一种方法:首先获取当前进程的id,然后杀死该进程。 (建议使用)

android.os.Process.killProcess(android.os.Process.myPid())

 

第二种方法:终止当前正在运行的Java虚拟机,导致程序终止

System.exit(0);

 

第三种方法:强制关闭与该包有关联的一切执行

ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

manager.restartPackage(getPackageName());

<uses-permission android:name="android.permission.RESTART_PACKAGES" />

 判断SIM卡属于哪个移动运营商

在文件AndroidManifest.xml中添加权限

<uses-permission android:name="android.permission.READ_PHONE_STATE"/>

Java语言:
//第一种方法:
//获取手机的IMSI码,并判断是中国移动\中国联通\中国电信
TelephonyManager  telManager  = ( TelephonyManagergetSystemService( Context . TELEPHONY_SERVICE);
/** 获取SIM卡的IMSI码
        * SIM卡唯一标识:IMSI 国际移动用户识别码(IMSI:International Mobile Subscriber Identification Number)是区别移动用户的标志,
        * 储存在SIM卡中,可用于区别移动用户的有效信息。IMSI由MCC、MNC、MSIN组成,其中MCC为移动国家号码,由3位数字组成,
        * 唯一地识别移动客户所属的国家,我国为460;MNC为网络id,由2位数字组成,
        * 用于识别移动客户所归属的移动网络,中国移动为00,中国联通为01,中国电信为03;MSIN为移动客户识别码,采用等长11位数字构成。
        * 唯一地识别国内GSM移动通信网中移动客户。所以要区分是移动还是联通,只需取得SIM卡中的MNC字段即可
        */
String  imsi  =  telManager . getSubscriberId();
if( imsi != null ){
if( imsi . startsWith( "46000") ||  imsi . startsWith( "46002" )){ //因为移动网络编号46000下的IMSI已经用完,所以虚拟了一个46002编号,134/159号段使用了此编号
//中国移动
} else  if( imsi . startsWith( "46001" )){
//中国联通
} else  if( imsi . startsWith( "46003" )){
//中国电信
}
} //第二种方法
TelephonyManager  telManager  = ( TelephonyManagergetSystemService( Context . TELEPHONY_SERVICE);
String  operator  =  telManager . getSimOperator();
if( operator != null ){
if( operator . equals( "46000") ||  operator . equals( "46002" )){
//中国移动
} else  if( operator . equals( "46001" )){
//中国联通
} else  if( operator . equals( "46003" )){
//中国电信
}
}

 

从SIM卡中获取联系人信息

Java语言:
Uri  uri  =  Uri . parse( "content://icc/adn");
String []  projection  =  { "_id" ,  "name" ,  "number" };
Cursor  cursor  =  managedQuery( uri ,  projection ,  null ,  null ,  "name");
if( cursor != null ){
while( cursor . moveToNext ()){
String  name  =  cursor . getString( cursor . getColumnIndex( "name"));
String  phone  =  cursor . getString( cursor . getColumnIndex( "number"));
}
} //在文件AndroidManifest.xml中添加权限
< uses - permission  android: name = "android.permission.READ_PHONE_STATE" /> //Android系统内部通过Contentprovider对外共享Sim卡存放的联系人等信息,你可以通过操作Contentprovider来实现Sim卡信息的添删改查操作。 内部实现源代码参见下方:
Java语言:
package  com . android . internal . telephony; import  android.content.ContentProvider;
import  android.content.UriMatcher;
import  android.content.ContentValues;
import  com.android.internal.database.ArrayListCursor;
import  android.database.Cursor;
import  android.net.Uri;
import  android.os.SystemProperties;
import  android.os.RemoteException;
import  android.os.ServiceManager;
import  android.text.TextUtils;
import  android.util.Log; import  java.util.ArrayList;
import  java.util.List; import  com.android.internal.telephony.IccConstants;
import  com.android.internal.telephony.AdnRecord;
import  com.android.internal.telephony.IIccPhoneBook;

public class IccProvider extends ContentProvider {
private static final String TAG = "IccProvider";
private static final boolean DBG = false;

private static final String[] ADDRESS_BOOK_COLUMN_NAMES = new String[] {
"name",
"number"
};

private static final int ADN = 1;
private static final int FDN = 2;
private static final int SDN = 3;

private static final String STR_TAG = "tag";
private static final String STR_NUMBER = "number";
private static final String STR_PIN2 = "pin2";

private static final UriMatcher URL_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);

static {
URL_MATCHER.addURI("icc", "adn", ADN);
URL_MATCHER.addURI("icc", "fdn", FDN);
URL_MATCHER.addURI("icc", "sdn", SDN);
}

private boolean mSimulator;

@Override
public boolean onCreate() {
String device = SystemProperties.get("ro.product.device");
if (!TextUtils.isEmpty(device)) {
mSimulator = false;
} else {
// simulator
mSimulator = true;
}
return true;
}

@Override
public Cursor query(Uri url, String[] projection, String selection,
String[] selectionArgs, String sort{
ArrayList<ArrayList> results;

if (!mSimulator{
switch (URL_MATCHER.match(url)) {
case ADN:
results = loadFromEf(IccConstants.EF_ADN);
break;

case FDN:
results = loadFromEf(IccConstants.EF_FDN);
break;

case SDN:
results = loadFromEf(IccConstants.EF_SDN);
break;

default:
throw new IllegalArgumentException("Unknown URL " + url);
}
} else {
// Fake up some data for the simulator
results = new ArrayList<ArrayList>(4);
ArrayList<String> contact;

contact = new ArrayList<String>();
contact.add("Ron Stevens/H");
contact.add("512-555-5038");
results.add(contact);

contact = new ArrayList<String>();
contact.add("Ron Stevens/M");
contact.add("512-555-8305");
results.add(contact);

contact = new ArrayList<String>();
contact.add("Melissa Owens");
contact.add("512-555-8305");
results.add(contact);

contact = new ArrayList<String>();
contact.add("Directory Assistence");
contact.add("411");
results.add(contact);
}

return new ArrayListCursor(ADDRESS_BOOK_COLUMN_NAMES, results);
}

@Override
public String getType(Uri url{
switch (URL_MATCHER.match(url)) {
case ADN:
case FDN:
case SDN:
return "vnd.android.cursor.dir/sim-contact";

default:
throw new IllegalArgumentException("Unknown URL " + url);
}
}

@Override
public Uri insert(Uri url, ContentValues initialValues{
Uri resultUri;
int efType;
String pin2 = null;

if (DBGlog("insert");

int match = URL_MATCHER.match(url);
switch (match{
case ADN:
efType = IccConstants.EF_ADN;
break;

case FDN:
efType = IccConstants.EF_FDN;
pin2 = initialValues.getAsString("pin2");
break;

default:
throw new UnsupportedOperationException(
"Cannot insert into URL: " + url);
}

String tag = initialValues.getAsString("tag");
String number = initialValues.getAsString("number");
boolean success = addIccRecordToEf(efType, tag, number, pin2);

if (!success{
return null;
}

StringBuilder buf = new StringBuilder("content://im/");
switch (match{
case ADN:
buf.append("adn/");
break;

case FDN:
buf.append("fdn/");
break;
}

// TODO: we need to find out the rowId for the newly added record
buf.append(0);

resultUri = Uri.parse(buf.toString());

/*
       // notify interested parties that an insertion happened
       getContext().getContentResolver().notifyInsert(
               resultUri, rowID, null);
       */

return resultUri;
}

private String normalizeValue(String inVal{
int len = inVal.length();
String retVal = inVal;

if (inVal.charAt(0== '\'' && inVal.charAt(len-1== '\''{
retVal = inVal.substring(1, len-1);
}

return retVal;
}

@Override
public int delete(Uri url, String where, String[] whereArgs{
int efType;

if (DBGlog("delete");

int match = URL_MATCHER.match(url);
switch (match{
case ADN:
efType = IccConstants.EF_ADN;
break;

case FDN:
efType = IccConstants.EF_FDN;
break;

default:
throw new UnsupportedOperationException(
"Cannot insert into URL: " + url);
}

// parse where clause
String tag = null;
String number = null;
String pin2 = null;

String[] tokens = where.split("AND");
int n = tokens.length;

while (-->= 0{
String param = tokens[n];
if (DBGlog("parsing '" + param + "'");

String[] pair = param.split("=");

if (pair.length != 2{
Log.e(TAG, "resolve: bad whereClause parameter: " + param);
continue;
}

String key = pair[0].trim();
String val = pair[1].trim();

if (STR_TAG.equals(key)) {
tag = normalizeValue(val);
} else if (STR_NUMBER.equals(key)) {
number = normalizeValue(val);
} else if (STR_PIN2.equals(key)) {
pin2 = normalizeValue(val);
}
}

if (TextUtils.isEmpty(tag)) {
return 0;
}

if (efType == FDN && TextUtils.isEmpty(pin2)) {
return 0;
}

boolean success = deleteIccRecordFromEf(efType, tag, number, pin2);
if (!success{
return 0;
}

return 1;
}

@Override
public int update(Uri url, ContentValues values, String where, String[] whereArgs{
int efType;
String pin2 = null;

if (DBGlog("update");

int match = URL_MATCHER.match(url);
switch (match{
case ADN:
efType = IccConstants.EF_ADN;
break;

case FDN:
efType = IccConstants.EF_FDN;
pin2 = values.getAsString("pin2");
break;

default:
throw new UnsupportedOperationException(
"Cannot insert into URL: " + url);
}

String tag = values.getAsString("tag");
String number = values.getAsString("number");
String newTag = values.getAsString("newTag");
String newNumber = values.getAsString("newNumber");

boolean success = updateIccRecordInEf(efType, tag, number,
newTag, newNumber, pin2);

if (!success{
return 0;
}

return 1;
}

private ArrayList<ArrayList> loadFromEf(int efType{
ArrayList<ArrayList> results = new ArrayList<ArrayList>();
List<AdnRecord> adnRecords = null;

if (DBGlog("loadFromEf: efType=" + efType);

try {
IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
ServiceManager.getService("simphonebook"));
if (iccIpb != null{
adnRecords = iccIpb.getAdnRecordsInEf(efType);
}
} catch (RemoteException ex{
// ignore it
} catch (SecurityException ex{
if (DBGlog(ex.toString());
}
if (adnRecords != null{
// Load the results

int N = adnRecords.size();
if (DBGlog("adnRecords.size=" + N);
for (int i = 0i < N ; i++) {
loadRecord(adnRecords.get(i), results);
}
} else {
// No results to load
Log.w(TAG, "Cannot load ADN records");
results.clear();
}
if (DBGlog("loadFromEf: return results");
return results;
}

private boolean
addIccRecordToEf(int efType, String name, String number, String pin2{
if (DBGlog("addIccRecordToEf: efType=" + efType + ", name=" + name +
", number=" + number);

boolean success = false;

// TODO: do we need to call getAdnRecordsInEf() before calling
// updateAdnRecordsInEfBySearch()? In any case, we will leave
// the UI level logic to fill that prereq if necessary. But
// hopefully, we can remove this requirement.

try {
IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
ServiceManager.getService("simphonebook"));
if (iccIpb != null{
success = iccIpb.updateAdnRecordsInEfBySearch(efType, "", "",
name, number, pin2);
}
} catch (RemoteException ex{
// ignore it
} catch (SecurityException ex{
if (DBGlog(ex.toString());
}
if (DBGlog("addIccRecordToEf: " + success);
return success;
}

private boolean
updateIccRecordInEf(int efType, String oldName, String oldNumber,
String newName, String newNumber,String pin2{
if (DBGlog("updateIccRecordInEf: efType=" + efType +
", oldname=" + oldName + ", oldnumber=" + oldNumber +
", newname=" + newName + ", newnumber=" + newNumber);
boolean success = false;

try {
IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
ServiceManager.getService("simphonebook"));
if (iccIpb != null{
success = iccIpb.updateAdnRecordsInEfBySearch(efType,
oldName, oldNumber, newName, newNumber, pin2);
}
} catch (RemoteException ex{
// ignore it
} catch (SecurityException ex{
if (DBGlog(ex.toString());
}
if (DBGlog("updateIccRecordInEf: " + success);
return success;
}

private boolean deleteIccRecordFromEf(int efType, String name, String number, String pin2{
if (DBGlog("deleteIccRecordFromEf: efType=" + efType +
", name=" + name + ", number=" + number + ", pin2=" + pin2);

boolean success = false;

try {
IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
ServiceManager.getService("simphonebook"));
if (iccIpb != null{
success = iccIpb.updateAdnRecordsInEfBySearch(efType,
name, number, "", "", pin2);
}
} catch (RemoteException ex{
// ignore it
} catch (SecurityException ex{
if (DBGlog(ex.toString());
}
if (DBGlog("deleteIccRecordFromEf: " + success);
return success;
}

/**
    * Loads an AdnRecord into an ArrayList. Must be called with mLock held.
    *
    * @param record the ADN record to load from
    * @param results the array list to put the results in
    */
private void loadRecord(AdnRecord record,
ArrayList<ArrayList> results{
if (!record.isEmpty()) {
ArrayList<String> contact = new ArrayList<String>(2);
String alphaTag = record.getAlphaTag();
String number = record.getNumber();

if (DBGlog("loadRecord: " + alphaTag + ", " + number);
contact.add(alphaTag);
contact.add(number);
results.add(contact);
}
}

private void log(String msg{
Log.d(TAG, "[IccProvider] " + msg);
}
}

 传感器的使用

传感器类型:方向、加速度(重力)、光线、磁场、距离(临近性)、温度等。 

方向传感器:   Sensor.TYPE_ORIENTATION

加速度(重力)传感器: Sensor.TYPE_ACCELEROMETER

光线传感器:    Sensor.TYPE_LIGHT

磁场传感器:   Sensor.TYPE_MAGNETIC_FIELD

距离(临近性)传感器: Sensor.TYPE_PROXIMITY

温度传感器:   Sensor.TYPE_TEMPERATURE

//获取某种类型的感应器

Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);

//注册监听,获取传感器变化值

sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_GAME);

上面第三个参数为采样率:最快、游戏、普通、用户界面。当应用程序请求特定的采样率时,其实只是对传感器子系统的一个建议,不保证特定的采样率可用。

最快: SensorManager.SENSOR_DELAY_FASTEST

最低延迟,一般不是特别敏感的处理不推荐使用,该种模式可能造成手机电力大量消耗,由于传递的为原始数据,算法不处理好将会影响游戏逻辑和UI的性能。

游戏: SensorManager.SENSOR_DELAY_GAME

游戏延迟,一般绝大多数的实时性较高的游戏都使用该级别。

普通: SensorManager.SENSOR_DELAY_NORMAL 

标准延迟,对于一般的益智类或EASY级别的游戏可以使用,但过低的采样率可能对一些赛车类游戏有跳帧现象。

用户界面: SensorManager.SENSOR_DELAY_UI

一般对于屏幕方向自动旋转使用,相对节省电能和逻辑处理,一般游戏开发中我们不使用。

Java语言:
//下面介绍如何获取加速度(重力)传感器和方向传感器的测量值: public  class  MainActivity  extends  Activity  {
private  TextView  accelerometer;
private  TextView  orientation;
private  SensorManager  sensorManager;

@Override
public void onCreate(Bundle savedInstanceState{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//获取感应器管理器
sensorManager = (SensorManagergetSystemService(SENSOR_SERVICE);
accelerometer = (TextViewfindViewById(R.id.accelerometer);
orientation = (TextViewfindViewById(R.id.orientation);
}

@Override
protected void onResume() {
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//获取重力加速度传感器
sensorManager.registerListener(listener, sensor, SensorManager.SENSOR_DELAY_GAME);
Sensor sensor1 = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);//获取方向传感器
sensorManager.registerListener(listener, sensor1, SensorManager.SENSOR_DELAY_GAME);
super.onResume();
}

@Override
protected void onPause() {
sensorManager.unregisterListener(listener);//注消所有传感器监听
super.onPause();
}

private SensorEventListener listener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event{//当传感器的值发生变化            
float x = event.values[SensorManager.DATA_X];
float y = event.values[SensorManager.DATA_Y];
float z = event.values[SensorManager.DATA_Z];
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
accelerometer.setText("Accelerometer Sensor: " + x + ", " + y + ", " + z);
break;

case Sensor.TYPE_ORIENTATION:
/*x该值表示方位,0代表北(North);90代表东(East);180代表南(South);270代表西(West)
                 如果x值正好是这4个值之一,并且手机是水平放置,手机的顶部对准的方向就是该值代表的方向。

               y值表示倾斜度,或手机翘起的程度。当手机绕着X轴倾斜时该值发生变化。y值的取值范围是-180≤y值 ≤180。
               假设将手机屏幕朝上水平放在桌子上,这时如果桌子是完全水平的,y值应该是0(由于很少有桌子是绝对水平的,
               因此,该值很可能不为0,但一般都是-5和5之间的某个值)。这时从手机顶部开始抬起,直到将手机沿X轴旋转180度(屏幕向下水平放在桌面上)。
               在这个旋转过程中,y值会在0到-180之间变化,也就是说,从手机顶部抬起时,y的值会逐渐变小,
               直到等于-180。如果从手机底部开始抬起,直到将手机沿X轴旋转180度,这时y值会在0到180之间变化。
               也就是y值会逐渐增大,直到等于180。可以利用y值和z值来测量桌子等物体的倾斜度。

               z值表示手机沿着Y轴的滚动角度。表示手机沿着Y轴的滚动角度。取值范围是-90≤z值≤90。
               假设将手机屏幕朝上水平放在桌面上,这时如果桌面是平的,z值应为0。将手机左侧逐渐抬起时,
               z值逐渐变小,直到手机垂直于桌面放置,这时z值是-90。将手机右侧逐渐抬起时,z值逐渐增大,
               直到手机垂直于桌面放置,这时z值是90。在垂直位置时继续向右或向左滚动,z值会继续在-90至90之间变化。
               */
orientation.setText("Orientation Sensor: " + x + ", " + y + ", " + z);
break;
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy{//当传感器的精度变化时        
}
};
}


--转自http://uaapp.com/?p=362--

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值