Android数据存储的三种方式-SharedPrefrences,File,SQLite
最后更新于:2022-04-01 16:14:59
1,使用SharedPrefrences
用于简单少量的数据,数据的格式简单:都是普通的字符串,标量类型的值等,比如各种配置信息等等
**SharedPrefrences与Editor简介**:
创建SharedPreferences实例,通过Context.getSharedPreferences(String name,int mode);方法来获取SharedPreferences的实例
mode的值:
*Context.MODE_PRIVATE;该SharedPreferences数据只能被本应用程序调读,写
* Context.MODE_WORLD_READABLE;该SharedPreferences数据能被其他程序读,但是不能写
* Context.MODE_WORLD_WRITEABLE;该SharedPreferences数据能被其他程序读,写
SharedPreferences保存的数据主要是类似于配置信息格式的数据,因此他保存的数据主要是简单类型的key-value对
* SharedPreferences接口主要负责读取应用程序的Preferences数据,提供如下常用的方法访问key-value对
* boolean contains(String key);判断是否包含key的数据
* abstract Map getAll();获取全部键值对
* boolean getXxx(String key,xxx,defValue);获取指定的key对应的value值,如果key不存在,返回默认defvalue,xxx可以是Boolean,float,int,long,String等各种基本类型的值
SharedPreferences接口本身并没有提供写入数据的能力,而是通过 SharedPreferences的内部接口Editor写入数据,SharedPreferences调用edit()方法即可获得它所对应的Editor对象
Editor提供了如下方法:
* SharedPreferences.Editor clear();清空所有数据
* SharedPreferences.Editor putXxx(String key,xxx value);存入指定key对应的数据,xxx可以是Boolean,float,int,long,String等各种基本类型的值
* SharedPreferences.Editor remove(String key);删除指定key的数据
* Boolean commit();当Editor编辑完成之后,调用该方法提交修改
例子:一个按钮写数据,一个按钮读数据
activity_main.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Write_SharedPreference" />
<Button
android:id="@+id/button2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Read_SharedPreference" />
</LinearLayout>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b218fe9.jpg)
MainActivity.java
~~~
package com.hust.sharedpreferences;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;
/*
* 创建SharedPreferences实例,通过Context.getSharedPreferences(String name,int mode);方法来获取SharedPreferences的实例
* mode的值:
* Context.MODE_PRIVATE;该SharedPreferences数据只能被本应用程序调读,写
* Context.MODE_WORLD_READABLE;该SharedPreferences数据能被其他程序读,但是不能写
* Context.MODE_WORLD_WRITEABLE;该SharedPreferences数据能被其他程序读,写
*
*
* SharedPreferences保存的数据主要是类似于配置信息格式的数据,因此他保存的数据主要是简单类型的key-value对
*
* SharedPreferences接口主要负责读取应用程序的Preferences数据,提供如下常用的方法访问key-value对
* boolean contains(String key);判断是否包含key的数据
* abstract Map<String,?> getAll();获取全部键值对
* boolean getXxx(String key,xxx,defValue);获取指定的key对应的value值,如果key不存在,返回默认defvalue,xxx可以是Boolean,float,int,long,String等各种基本类型的值
*
* SharedPreferences接口本身并没有提供写入数据的能力,而是通过 SharedPreferences的内部接口Editor写入数据,SharedPreferences调用edit()方法即可互殴它所对应的Editor对象
* Editor提供了如下方法:
* SharedPreferences.Editor clear();清空所有数据
* SharedPreferences.Editor putXxx(String key,xxx value);存入指定key对应的数据,xxx可以是Boolean,float,int,long,String等各种基本类型的值
* SharedPreferences.Editor remove(String key);删除指定key的数据
* Boolean commit();当Editor编辑完成之后,调用该方法提交修改
*
* */
public class MainActivity extends Activity {
//
SharedPreferences preferences;
SharedPreferences.Editor editor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化SharedPreferences对象,读数据
preferences=getSharedPreferences("test",Context.MODE_WORLD_READABLE);
//实例化Editor对象,写数据
editor=preferences.edit();
Button read=(Button) findViewById(R.id.button2);
Button write=(Button) findViewById(R.id.button1);
read.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String time=preferences.getString("time", null);
int rnd=preferences.getInt("rnd", 0);
String result=time==null?"您暂时还未写入数据":"写入时间:"+time+"\n上次生成的数据数是:"+rnd;
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
}
});
write.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
SimpleDateFormat sdf=new SimpleDateFormat("yyyy年MM月dd日"+"hh:mm:ss");
editor.putString("time", sdf.format(new Date()));
editor.putInt("rnd", (int)(Math.random()*1000));
editor.commit();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
SharedPrefrences文件的存储位置:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b22cca0.jpg)
test.xml
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b246262.jpg)
待续。。。
使用Action,Data属性启动系统Activity
最后更新于:2022-04-01 16:14:56
几个Action属性和Data属性的特殊组合:
ACTION_VIEW content://com.android.contacts/contacts/1:显示标识为1的联系人的信息
ACTION_EDIT content://com.android.contacts/contacts/1:编辑标识为1的联系人的信息
ACTION_DIAL content://com.android.contacts/contacts/1:显示向标识为1的联系人拨号的界面
ACTION_VIEW tel:123:显示向指定号码123拨号的界面
ACTION_DIAL tel:123:显示向指定号码123拨号的界面
ACTION_VIEW content://contacts/people/:显示所有联系人列表的信息,通过这种组合可以方便地查看系统联系人
MainActivity.java
~~~
package com.hust.actiondataonsystemactivity;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button brower=(Button) findViewById(R.id.button1);
Button edit=(Button) findViewById(R.id.button2);
Button call=(Button) findViewById(R.id.button3);
//浏览网页
brower.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent =new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
//编辑联系人页面
edit.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent =new Intent();
intent.setAction(Intent.ACTION_EDIT);
intent.setData(Uri.parse("content://com.android.contacts/contacts/2"));
startActivity(intent);
}
});
//拨号页面
call.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent =new Intent();
intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:02780108225"));
startActivity(intent);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b1a6d1b.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b1bd60c.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b1ddc78.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b1f4086.jpg)
使用指定的Action,Category调用系统Activity
最后更新于:2022-04-01 16:14:54
Android提供了大量的标准Action,Category:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b12e7d7.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b146ae9.jpg)
例子,查看并获取联系人电话
用户点击按钮值会显示系统的联系人列表,当用户单击联系人之后,程序将会显示该联系人的名字和电话
MainActivity.java
~~~
package com.hust.getcontacts;
import android.app.Activity;
import android.content.CursorLoader;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
final int PICK_CONTACT=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn=(Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//创建intent
Intent intent=new Intent();
//设置Intent的Action属性
intent.setAction(Intent.ACTION_GET_CONTENT);
//设置Intent的Type属性
intent.setType("vnd.android.cursor.item/phone");
//启动Activity,并希望获取该Activity的结果
startActivityForResult(intent,PICK_CONTACT);
}
});
}
//重写该方法,处理返回的联系人数据在参数Intent data中
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode)
{
case (PICK_CONTACT):
if(resultCode==Activity.RESULT_OK){//Activity.RESULT_OK标准Activity结果 -1
//获取返回的联系人数据
Uri contactdata=data.getData();
CursorLoader cursorloader=new CursorLoader(this, contactdata, null, null, null, null);
//查询联系人信息表
Cursor cursor=cursorloader.loadInBackground();
//如果查询到指定的联系人
if(cursor.moveToFirst()){
//获取联系人的Id
String contactId=cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
//获取联系人的名字
String name=cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts.DISPLAY_NAME));
String phoneNumber="此联系人暂未输入电话号码";
//根据联系人查询该联系人的详细信息
Cursor phones=getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"="+contactId, null, null);
//
if(phones.moveToFirst()){
//取出电话号码
phoneNumber=phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
}
phones.close();
EditText show=(EditText) findViewById(R.id.editText1);
show.setText(name);
EditText phone=(EditText) findViewById(R.id.editText2);
phone.setText(phoneNumber);
}
cursor.close();
}
break;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b16153d.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b1776aa.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b19192d.jpg)
Intent对象详解(二)
最后更新于:2022-04-01 16:14:52
**3,Action、Category属性与intent-filter配置**
Intent的Action和Category属性都是一个普通的字符串,其中Action代表该Intent所要完成的一个抽象“动作”,Category则用于为Action增加额外的附加类别信息,通常,Action与Category结合使用。
元素里通常可包括如下子元素:
a、0~N个子元素
b、0~N个子元素
c、0~1个子元素
子元素的配置非常简单,它们都可指定android:name属性,该属性的值就是一个普通字符串。
当元素里的子元素里包含多个子元素(相当于指定了多个字符串)时,就表明该Activity能响应Action属性值为其中任意一个字符串的Intent。
一个Intent对象最多只能包括一个Action属性,程序调用Intent的setAction(String str)方法来设置Action属性值;但一个Intent对象可包含多个Category属性,调用Intent的addCategory(String str)方法添加。
当程序创建Intent时,该Intent默认启动Category属性值为Intent.CATEGORY_DEFAULT常量(常量值为android.intent.category.DEFAULT)的组件。
~~~
public class ActionCateAttr extends Activity
{
// 定义一个Action常量
final static String _ACTION =
"com.intent.action._ACTION";
// 定义一个Category常量
final static String _CATEGORY =
"com.intent.category._CATEGORY";
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button bn = (Button) findViewById(R.id.bn);
bn.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
Intent intent = new Intent();
// 设置Action属性
intent.setAction(ActionCateAttr._ACTION);
// 添加Category属性
intent.addCategory(ActionCateAttr._CATEGORY);
startActivity(intent);
}
});
}
}
~~~
~~~
public class SecondActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
EditText show = (EditText) findViewById(R.id.show);
// 获取该Activity对应的Intent的Action属性
String action = getIntent().getAction();
// 显示Action属性
show.setText("Action为:" + action);
EditText cate = (EditText) findViewById(R.id.cate);
// 获取该Activity对应的Intent的Category属性
Set<String> cates = getIntent().getCategories();
// 显示Action属性
cate.setText("Category属性为:" + cates);
}
}
~~~
Manifest.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.crazyit.intent"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="17" />
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name">
<activity android:name=".ActionCateAttr"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".SecondActivity"
android:label="@string/app_name">
<intent-filter>
<!-- 指定该Activity能响应action为指定字符串的Intent -->
<action android:name="com.intent.action._ACTION" />
<!-- 指定该Activity能响应category为指定字符串的Intent -->
<category android:name="com.intent.category.CRAZYIT_CATEGORY" />
<!-- 指定该Activity能响应category为android.intent.category.DEFAULT的Intent -->
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
</manifest>
~~~
**3、Data、Type属性与intent-filter配置**
Data属性通常用于向Action属性提供操作的数据,Data属性接收一个Uri对象,一个Uri对象通常通过如下形式的字符串表示:
content://com.android.contracts/contacts/1
tel:123
上面两个字符串的冒号前面大致指定了数据的类型,冒号后面是数据部分。
Uri字符串总满足如下格式:
scheme://host.port/path
Type属性则用于明确指定Data属性所指定数据的类型或MIME类型,当Intent不指定Data属性时Type属性才会起作用,否则Android系统将会根据Data属性值来分析数据的类型,因此无需指定Type属性。
一旦为Intent同时指定Action、Data属性,那么Android将可根据指定的数据类型来启动特定的应用程序,并对指定数据执行相应的操作。下面介绍几个Action、Data属性的组合:
ACTION_VIEW content://com.android.contacts/contacts/1:显示标识为1的联系人的信息
ACTION_EDIT content://com.android.contacts/contacts/1:编辑标识为1的联系人的信息
ACTION_DIAL content://com.android.contacts/contacts/1:显示向标识为1的联系人拨号的界面
ACTION_VIEW tel:123:显示向指定号码123拨号的界面
ACTION_DIAL tel:123:显示向指定号码123拨号的界面
ACTION_VIEW content://contacts/people/:显示所有联系人列表的信息,通过这种组合可以方便地查看系统联系人
Intent对象详解(一)
最后更新于:2022-04-01 16:14:50
Intent的定义:
Android中提供了Intent机制来协助应用间的交互与通讯,或者采用更准确的说法是,Intent不仅可用于应用程序之间,也可用于应用程序内部的activity, service和broadcast receiver之间的交互。Intent这个英语单词的本意是“目的、意向、意图”。
使用Intent启动系统组件:
三种应用程序基本组件——activity, service和broadcast receiver——是使用称为intent的消息来激活的。Intent消息传递是一种组件间运行时绑定的机制. intent是Intent对象, 它包含了需要做的操作的描述, 或者, 对于广播来说, 包含了正在通知的消息内容. 对于向这三种组件发送intent有不同的机制:
使用Context.startActivity() 或 Activity.startActivityForResult(), 传入一个intent来启动一个activity. 使用 Activity.setResult(), 传入一个intent来从activity中返回结果.
将intent对象传给Context.startService()来启动一个service或者传消息给一个运行的service. 将intent对象传给 Context.bindService()来绑定一个service.
将intent对象传给 Context.sendBroadcast(), Context.sendOrderedBroadcast(),或者Context.sendStickyBroadcast()等广播方法,则它们被 传给 broadcast receiver.
在上述三种情况下, android系统会自己找到合适的activity, service, 或者 broadcast receivers来响应intent. 三者的intent相互独立互不干扰.
Intent的属性:
component(组件):目的组件
action(动作):用来表现意图的行动
category(类别):用来表现动作的类别
data(数据):表示与动作要操纵的数据
type(数据类型):对于data范例的描写
extras(扩展信息):扩展信息
Flags(标志位):期望这个意图的运行模式
**1,component(组件):目的组件**
Component属性明确指定Intent的目标组件的类名称。(属于直接Intent)
ComponentName对象包含的构造器:
ComponentName(String pkg,String cls)创建在pkg所在报下的cls类所对应的组件
ComponentName(Context pkg,String cls)创建在pkg所在报下的cls类所对应的组件
ComponentName(Context pkg,Class cls)创建在pkg所在报下的cls类所对应的组件
一个ComponentName需要指定包名和类名--这就可以唯一确定一个组件类
另外Intent可以根据给定的组件类去启动特定的组件,Intent有下面的方法:
setClass(Context packageContext,Class cls):设置该Intent将要启动的组件对应的类
setClassName(Context packageContext,String className):设置该Intent将要启动的组件对应的类
setClassName(String packageContext,String className):设置该Intent将要启动的组件对应的类
**以上方法中的两个参数其实就确定了一个Component组件**
Intent类型分为显式Intent(直接类型)、隐式Intent(间接类型)。官方建议使用隐式Intent。上述属性中,component属性为直接类型,其他均为间接类型。
启动第二个Activity时:
~~~
// 为bn按钮绑定事件监听器
bn.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View arg0)
{
// 创建一个ComponentName对象
ComponentName comp = new ComponentName(ComponentAttr.this,
SecondActivity.class);
Intent intent = new Intent();
// 为Intent设置Component属性
intent.setComponent(comp);
// Intent intent = new Intent(ComponentAttr.this,
// SecondActivity.class);
startActivity(intent);
}
});
~~~
可以这样写:
~~~
Intent intent = new Intent();
//setClass函数的第一个参数是一个Context对象
//Context是一个类,Activity是Context类的子类,也就是说,所有的Activity对象,都可以向上转型为Context对象
//setClass函数的第二个参数是一个Class对象,在当前场景下,应该传入需要被启动的Activity类的class对象
intent.setClass(MainActivity.this, SecondActivity.class);
startActivity(intent);
~~~
还可以这样写:
~~~
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
~~~
**2、Action(动作):用来表现意图的行动**
Action 是一个用户定义的普通字符串,代表该Intent索要完成的一个抽象“动作”。用于描述一个 Android 应用程序组件,一个 Intent Filter 可以包含多个 Action。在 AndroidManifest.xml 的Activity 定义时,可以在其 节点指定一个 Action列表用于标识 Activity 所能接受的“动作”
Action要完成的知识一个抽象的动作,这个动作具体由哪个组件(Activity,Service,BroadcastReceiver)来完成,Action这个字符不管。比如Android提供的标准Action:Intent.ACTION_VIEW,它值表示一个抽象的查看动作,但具体什么,启动哪个Activity来看,Intent.ACTION_VIEW并不知道---这取决于Activity的配置,只要某个Activity的配置中包含了该ACTION_VIEW,该Activity就有可能被启动。
一句话总就是说,哪个Activity的intent-filter...>配置中有Intent设置的Action属性,就可能被启动。
MainActivity .java
~~~
public class MainActivity extends Activity {
public final static String ACTION="com.hust.actiontest";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn=(Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent();
intent.setAction(MainActivity.ACTION);
startActivity(intent);
}
});
}
~~~
~~~
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.hust.actionattrtest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="20"
android:targetSdkVersion="22" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SeclondActivity"
android:label="@string/title_activity_seclond" >
<intent-filter>
<!-- 指定该Activity能响应Action为指定字符串的Intent -->
<action android:name="com.hust.actiontest" />
<!-- 指定该Action能响应Category属性为指定字符串的Intent -->
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
~~~
SecondActivity.java
~~~
public class SeclondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_seclond);
TextView show = (TextView) findViewById(R.id.show);
// 获取该Activity对应的Intent的Action属性
String action = getIntent().getAction();
// 显示Action属性
show.setText("Action为:" + action);
}
~~~
因为SeclondActivity的的action有com.hust.actiontest所以就可能被MainActivity启动
使用Intent的Action属性启动组件的过程大概是:主Activity的Intent的Action属性设置为一个字符串str比如“com.hust.edu”,然后再去Manifest.xml中查找各个Activity组件的的action是否有这个字符串str=com.hust.edu,如果有,这个Activity可能被启动。
通过 Intent 传递类对象
最后更新于:2022-04-01 16:14:47
Android中Intent传递类对象提供了两种方式一种是 通过实现Serializable接口传递对象,一种是通过实现Parcelable接口传递对象。
要求被传递的对象必须实现上述2种接口中的一种才能通过Intent直接传递
Intent中传递这2种对象的方法:
~~~
Bundle.putSerializable(Key,Object); //实现Serializable接口的对象
Bundle.putParcelable(Key, Object); //实现Parcelable接口的对象
~~~
Person.java
~~~
package com.hust.bundletest;
import java.io.Serializable;
public class Person implements Serializable {
String name;
String password;
String sex;
public Person(String name, String password, String sex) {
super();
this.name = name;
this.password = password;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
~~~
注册窗体发送Intent的代码:
~~~
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn=(Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//获得的三个组件
EditText name=(EditText) findViewById(R.id.name);
EditText password=(EditText) findViewById(R.id.password);
RadioButton male=(RadioButton) findViewById(R.id.radio0);
//判断是否被选
String sex=(male.isChecked())?"男":"女";
//封装成一个对象
Person p=new Person(name.getText().toString(),password.getText().toString(),sex);
//创建Bundle对象
Bundle bundle=new Bundle();
bundle.putSerializable("person", p);//Bundle中放一个对象
//创建一个Intent对象
Intent intent=new Intent(MainActivity.this,ResultActivity.class);
intent.putExtras(bundle);
//启动intent对应的Activity
startActivity(intent);
}
});
~~~
接收端的代码:
~~~
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
//获取显示组件
TextView name=(TextView) findViewById(R.id.text1);
TextView password=(TextView) findViewById(R.id.text2);
TextView sex=(TextView) findViewById(R.id.text3);
//获取Intent对象
Intent intent=getIntent();
//从Intent对象中获取序列数据
//Person p=(Person) intent.getSerializableExtra("person");相当于
Bundle bundle=intent.getExtras();//获取Bundle对象
Person p=(Person) bundle.getSerializable("person");//Bundle对象中获取可序列化对象
name.setText(p.getName());
password.setText(p.getPassword());
sex.setText(p.getSex());
}
~~~
以上就可以实现对象的传递。
如果传递的是List,可以把list强转成Serializable类型,而且object类型也必须实现了Serializable接口
~~~
Intent.putExtras(key, (Serializable)list)
~~~
~~~
(List)getIntent().getSerializable(key)
~~~
Bundle在Activity之间交换数据
最后更新于:2022-04-01 16:14:45
在Activity之间进行数据交换有一个“信使”:Intent,因此主要是将需要交换的数据放入Intent即可
Intent提供了多个重载方法,“携带”额外的数据:
**放入Bundle数据:**
putExtras(Bundle data);向Intent中放入需要“携带”数据包
Bundle getExtras();取出Intent所“携带”的数据包
**放入键值数据:**(源码底层实际上还是使用的Bundle)
putExtra(String name,Xxx value);按key-value形式放入数据,Xxx是任意类型
getXxxExtra(String name);按key值取出指定类型的数据
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b093caa.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b0aa352.jpg)
Bundle就是一个简单的数据携带包,Bundle方法:
**放入基本类型:**
putXxx(String key,Xxx data);向Bundle中放入Int,Long等各种类型的数据
getXxx(String key);取出Int,Long等各种类型数据
**放入对象**:
putSeralizable(String key,Seralizable data);放入一个可序列化的对象
getSeralizable(String key,Seralizable data);取出一个可序列化的对象
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b0cac16.jpg)
一般第一个Activity中:
* Bundle放数据用:
* putXxx(String key,Xxx value);想Bundle中放入int,Long等简单数据类型
* putSerializable(String key,Serializable data);想Bundle中放入可序列化的对象,主要用于放对象
* Intent放Bundle用:
* putExtras(Bundle data):向Intent中放入需要“携带”的数据包
被启动的Activity中:
* Intent取数据:
* Bundle getExtras();取出Intent所“携带”的数据包
* getXxxExtras(String key);从Intent中按key取出指定类型的数据,便携方式取Bundle中的数据
用第二个Activity处理注册信息:
activity_main.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="请输入您的注册信息"
android:textSize="20dp" />
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="账号:"
android:textSize="20dp" />
<EditText
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="请输入账号"
android:selectAllOnFocus="true" >
</EditText>
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码:"
android:textSize="20dp" />
<EditText
android:id="@+id/password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="请输入密码"
android:inputType="textPassword" />
</TableRow>
<TableRow
android:id="@+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="性别:"
android:textSize="20dp" />
<RadioGroup
android:id="@+id/radioGroup1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<RadioButton
android:id="@+id/radio0"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"
android:text="男" />
<RadioButton
android:id="@+id/radio1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="女" />
</RadioGroup>
</TableRow>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="注册" />
</TableLayout>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b0e9cc6.jpg)
MainActivity.java
~~~
package com.hust.bundletest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
/*用第二个Activity处理注册信息。
* 在Activity之间进行数据交换是同过Intent信使来实现的。Intent提供了多种重载的方法,来携带额外数据:
* 1,使用Bundle对象捆绑数据,Intent携带Bundle对象
* putExtras(Bundle data):向Intent中放入需要“携带”的数据包
* Bundle getExtras();取出Intent所“携带”的数据包
* 2,对于简单的数据类型,可以使用便携的方法直接存,取Intent所携带的Bundle对象,源码里可发现都是先创建的Bundle对象
* putExtras(String key,Xxx value);想Intent中按键值对(key-value)的形式存入数据
* getXxxExtras(String key);从Intent中按key取出指定类型的数据
* */
/*
* Bundle就是一个简单的数据携带包,该Bundle对象包含了多种方法:
* 1,放入简单的数据类型
* putXxx(String key,Xxx value);想Bundle中放入int,Long等简单数据类型
* getXxx(String key);取出int,long个中简单的数据类型
*2,放入可序列化的对象,实现Seriliable接口的对象
* putSerializable(String key,Serializable data);想Bundle中放入可序列化的对象
* getSerializable(String key);取出可序列化的对象
*
* 一般第一个Activity中:
* Bundle放数据用:
* putXxx(String key,Xxx value);想Bundle中放入int,Long等简单数据类型
* putSerializable(String key,Serializable data);想Bundle中放入可序列化的对象,主要用于放对象
* Intent放Bundle用:
* putExtras(Bundle data):向Intent中放入需要“携带”的数据包
*
* 被启动的Activity中:
* Intent取数据:
* Bundle getExtras();取出Intent所“携带”的数据包
* getXxxExtras(String key);从Intent中按key取出指定类型的数据,便携方式取Bundle中的数据
* */
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn=(Button) findViewById(R.id.button1);
btn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//获得的三个组件
EditText name=(EditText) findViewById(R.id.name);
EditText password=(EditText) findViewById(R.id.password);
RadioButton male=(RadioButton) findViewById(R.id.radio0);
//判断是否被选
String sex=(male.isChecked())?"男":"女";
//封装成一个对象
Person p=new Person(name.getText().toString(),password.getText().toString(),sex);
//创建Bundle对象
Bundle bundle=new Bundle();
bundle.putSerializable("person", p);
//创建一个Intent对象
Intent intent=new Intent(MainActivity.this,ResultActivity.class);
intent.putExtras(bundle);
//启动intent对应的Activity
startActivity(intent);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
Person.java
~~~
package com.hust.bundletest;
import java.io.Serializable;
public class Person implements Serializable {
String name;
String password;
String sex;
public Person(String name, String password, String sex) {
super();
this.name = name;
this.password = password;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
~~~
ResultActivity.java
~~~
package com.hust.bundletest;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class ResultActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_result);
//获取显示组件
TextView name=(TextView) findViewById(R.id.text1);
TextView password=(TextView) findViewById(R.id.text2);
TextView sex=(TextView) findViewById(R.id.text3);
//获取Intent对象
Intent intent=getIntent();
//从Intent对象中获取序列数据
//Person p=(Person) intent.getSerializableExtra("person");相当于
Bundle bundle=intent.getExtras();//获取Bundle对象
Person p=(Person) bundle.getSerializable("person");//Bundle对象中获取可序列化对象
name.setText(p.getName());
password.setText(p.getPassword());
sex.setText(p.getSex());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.result, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b10fdbc.jpg)
Activity的生命周期理解
最后更新于:2022-04-01 16:14:43
Activity拥有4个基本状态:
活动状态:当前Activity位于前台,可以看见也可以获得焦点,可以接受用户输入的
暂停状态:其他Activity位于前台,该Activity依然可见,但是不能获得焦点(比如一个非全屏或者透明的Activity在你的Activity的上方拥有焦点),它的状态是暂停的。一个暂停状态下的Activity是活着的,但在系统极端低的状态下可以被杀死
停止状态:当一个Activity完全被另一个Activity遮盖,它的状态是停止的。该Activity不可见,失去焦点。这种状态很容易被系统杀死
销毁状态:该Activity被系统 结束,该Activity结束或Activity所在的Dalvik进程被结束
Activity的生命周期图:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b07785e.jpg)
我们来说一下Activity的生命周期过程:
运行-暂停-运行:
onCreate->onStart->**onResume->****onPause->onResume**
1.启动Activity:系统会先调用onCreate方法,然后调用onStart方法,最后调用onResume,Activity进入运行状态。
2.当前Activity被其他Activity覆盖其上或被锁屏:系统会调用onPause方法,暂停当前Activity的执行。
3.当前Activity由被覆盖状态回到前台或解锁屏:系统会调用onResume方法,再次进入运行状态。
运行-停止-运行:
onCreate->onStart->onResume->**onPause->****onStop->****onRestart->****onStart->onResume**
4.当前Activity转到新的Activity界面或按Home键回到主屏,自身退居后台,不可见失去焦点:系统会先调用onPause方法,然后调用onStop方法,进入停滞状态。
5.用户后退回到此Activity:系统会先调用onRestart方法,然后调用onStart方法,最后调用onResume方法,再次进入运行状态。
运行-销毁:
6.当前Activity处于被覆盖状态或者后台不可见状态,即第2步和第4步,系统内存不足,杀死当前Activity,而后用户退回当前Activity:再次调用onCreate方法、onStart方法、onResume方法,进入运行状态。
7.用户退出当前Activity:系统先调用onPause方法,然后调用onStop方法,最后调用onDestory方法,结束当前Activity。
Activity有三个关键的循环:
整个的生命周期,从onCreate(Bundle)开始到onDestroy()结束。Activity在onCreate()设置所有的“全局”状态,在onDestory()释放所有的资源。例如:某个Activity有一个在后台运行的线程,用于从网络下载数据,则该Activity可以在onCreate()中创建线程,在onDestory()中停止线程。
可见的生命周期,从onStart()开始到onStop()结束。在这段时间,可以看到Activity在屏幕上,尽管有可能不在前台,不能和用户交互。在这两个接口之间,需要保持显示给用户的UI数据和资源等,例如:可以在onStart中注册一个IntentReceiver来监听数据变化导致UI的变动,当不再需要显示时候,可以在onStop()中注销它。onStart(),onStop()都可以被多次调用,因为Activity随时可以在可见和隐藏之间转换。
前台的生命周期,从onResume()开始到onPause()结束。在这段时间里,该Activity处于所有 Activity的最前面,和用户进行交互。Activity可以经常性地在resumed和paused状态之间切换,例如:当设备准备休眠时,当一个 Activity处理结果被分发时,当一个新的Intent被分发时。所以在这些接口方法中的代码应该属于非常轻量级的。
MainActivity.java
~~~
package com.example.activitylifecircle;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity {
final String TAG="-Activity State-";
Button finish,start;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "--OnCreate--");
finish=(Button) findViewById(R.id.button1);
start=(Button) findViewById(R.id.button2);
start.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
}
});
finish.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//结束该Activity
MainActivity.this.finish();
}
});
}
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Log.d(TAG, "--OnStart--");
}
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Log.d(TAG, "--OnRestart--");
}
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Log.d(TAG, "--OnResume--");
}
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Log.d(TAG, "--OnPause--");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.d(TAG, "--OnStop--");
}
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.d(TAG, "--OnDestroy--");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
启动Activity的两种方式startActivity和startActivityForResult(二)
最后更新于:2022-04-01 16:14:41
startActivityForResult用于启动其他指定的Activity,而且期望获取该指定Activity返回的结果。
启动其他Activity并返回结果过程:
当前ActivityA需要调用startActivityForResult(int requestCode,Intent intent)请求调用参数intent对应的ActivityB,请求码是requestCode,同时需要重写onActivityResult(int requestCode,int resultCode,Intent intent),当被启动的ActivityB返回结果时,必须使用setResult(int resultCode,Intent intent)将携带数据的intent传回到ActivityA,这个传回动作响应的结果码是resultCode,此时会触发onActivityResult,然后请求码和结果码就唯一确定一个过程,然后就可以接下来处理了
请求码和结果码
一个Activity中可能包含多个按钮,并调用多个startActivityForResult方法来打开不同的Activity处理业务,当这些新Activity关闭后,系统会调用前面的Activity的onActivityResult方法。为了知道该方法是由哪个请求结果所触发的,可利用requestCode标识,为了知道返回的数据来自于那个新的Activity,可利用resultCode标识
例,第二个Activity让用户选择信息然后把结果返回给第一个Activity
MainActivity.java
~~~
package com.hust.activityforresult;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
public class MainActivity extends Activity {
Button bn;
EditText edit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bn=(Button) findViewById(R.id.button1);
edit=(EditText) findViewById(R.id.editText1);
bn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//创建需要对应目标Activity的intent
Intent intent=new Intent(MainActivity.this,CityActivity.class);
//启动指定Activity并等待返回的结果,0是请求码。用于表示该请求
startActivityForResult(intent ,0);
}
});
}
//重写该方法,以回调的形式来获取Activity返回的结果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// TODO Auto-generated method stub
super.onActivityResult(requestCode, resultCode, data);
//当请求码和结果码都是0时,也就是处理的特定结果
if(requestCode==0&&resultCode==0){
//获取Bundle中的数据
Bundle bundle=data.getExtras();
String city=bundle.getString("city");
//修改编辑框的内容
edit.setText(city);
}
}
~~~
CityActivity.java
~~~
package com.hust.activityforresult;
import android.app.ExpandableListActivity;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseExpandableListAdapter;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.TextView;
public class CityActivity extends ExpandableListActivity {
//定义省份
private String[] provinces={
"广东","湖北","河南"
};
//定义城市
private String[][] cities={
{"广州","深圳","珠海","惠州"},
{"武汉","襄阳","随州","十堰"},
{"郑州","平顶山","信阳","驻马店"}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_city);
ExpandableListAdapter ad=new BaseExpandableListAdapter(){
private TextView getTextView(){
AbsListView.LayoutParams lp=new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,64);
TextView textview =new TextView(CityActivity.this);
textview.setLayoutParams(lp);
textview.setTextSize(16);
textview.setGravity(Gravity.CENTER_VERTICAL|Gravity.LEFT);
textview.setPadding(30, 5, 0, 5);
return textview;
}
@Override
public int getGroupCount() {
// TODO Auto-generated method stub
return provinces.length;
}
@Override
public int getChildrenCount(int groupPosition) {
// TODO Auto-generated method stub
return cities[groupPosition].length;
}
@Override
public Object getGroup(int groupPosition) {
// TODO Auto-generated method stub
return provinces[groupPosition];
}
@Override
public Object getChild(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return cities[groupPosition][childPosition];
}
@Override
public long getGroupId(int groupPosition) {
// TODO Auto-generated method stub
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
// TODO Auto-generated method stub
return childPosition;
}
@Override
public boolean hasStableIds() {
// TODO Auto-generated method stub
return false;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
TextView text=getTextView();
text.setTextColor(Color.RED);
text.setText(getGroup(groupPosition).toString());
return text;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
TextView text=getTextView();
text.setText(getChild(groupPosition, childPosition)
.toString());
return text;
}
//主要在给子选项设置监听器时,这个函数一定要返回true,否则监听器没有用
@Override
public boolean isChildSelectable(int groupPosition,
int childPosition) {
// TODO Auto-generated method stub
return true;
}
};
//设置adapter
setListAdapter(ad);
//为每个子选项添加监听器
getExpandableListView().setOnChildClickListener(new OnChildClickListener(){
@Override
public boolean onChildClick(ExpandableListView parent, View v,
int groupPosition, int childPosition, long id) {
// TODO Auto-generated method stub
//获取启动该Activity之前的Activity对应的Intent
Intent intent=getIntent();
intent.putExtra("city", cities[groupPosition][childPosition]);
//设置该Activity的结果码,并设置结束之后退回的Activity
CityActivity.this.setResult(0, intent);
//结束本Activity
CityActivity.this.finish();
return false;
}
});
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b037ede.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b04d634.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b06135b.jpg)
启动Activity的两种方式startActivity和startActivityForResult(一)
最后更新于:2022-04-01 16:14:38
启动Activity有两种方式:
1,startActivity(Intent intent);启动其他Activity
2,startActivityForResult(Intent intent,int requestCode):以指定指定的请求码(requestCode)启动Activity,并且程序将会等到新启动Activity的结果(通过重写onActivityResult()方法来获取)
启动Activity是可指定一个requestCode参数,该参数代表了启动Activity的请求码。这个请求码的值由开发者自己设置,其实就是一个int整数值,只是用于表示请求来源
关闭Activity的两种方法:
1,finish():结束当前Activity;
2,finishActivity(intrequestCode):结束以startActivityForResult(Intent intent,int requestCode)方法启动的Activity。
startActivity和startActivityForResult的区别:
startActivity在启动其他Activity之后是不会被回调回来的,相当于启动者和被启动者在启动完毕之后是没有关系的
startActivityForResult在启动了其他Activity之后是由回调的,也就是说启动者与被启动者在启动完毕之后依然是有关系的
第一种方式比较直接,通过A的界面组件(比如按钮)可以启动第二个ActivityB,但是A和B之间不会传递数据,也就是无法进行通信
其基本代码模板是:
~~~
// 创建需要启动的Activity对应的Intent
Intent intent = new Intent(StartActivity.this,SecondActivity.class);
// 启动intent对应的Activity
startActivity(intent);
~~~
例,第一个Activity很简单,值由一个按钮,该按钮进入第二个Activity,第二个Activity只有两个按钮,一个按钮简单的返回第一个Activity,但是不会结束自己,第二个按钮结束自己并返回上一个Activity
StartActivity.java
~~~
public class StartActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取应用程序中的bn按钮
Button bn = (Button) findViewById(R.id.bn);
// 为bn按钮绑定事件监听器
bn.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
// 创建需要启动的Activity对应的Intent
Intent intent = new Intent(StartActivity.this,
SecondActivity.class);
// 启动intent对应的Activity
startActivity(intent);
}
});
}
}
~~~
SecondActivity.java
~~~
public class SecondActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.second);
// 获取应用程序中的previous按钮
Button previous = (Button) findViewById(R.id.previous);
// 获取应用程序中的close按钮
Button close = (Button) findViewById(R.id.close);
// 为previous按钮绑定事件监听器
previous.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
// 获取启动当前Activity的上一个Intent
Intent intent = new Intent(SecondActivity.this,
StartActivity.class);
// 启动intent对应的Activity
startActivity(intent);
}
});
// 为close按钮绑定事件监听器
close.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
// 获取启动当前Activity的上一个Intent
Intent intent = new Intent(SecondActivity.this,
StartActivity.class);
// 启动intent对应的Activity
startActivity(intent);
// 结束当前Activity
finish();
}
});
}
}
~~~
Handler消息传递机制(二)Handler,Loop,Message,MessageQueue的工作原理
最后更新于:2022-04-01 16:14:36
Loop,Message,MessageQueue概念理解:
Message:Handler发送、接收和处理的消息对象
Looper:每个线程只能拥有一个Looper.它的looper()方法负责循环读取MessageQueue中的消息并将读取到的消息交给发送该消息的handler进行处理。
MessageQueue:消息队列,它采用先进先出的方式来管理Message。程序在创建Looper对象时,会在它的构造器中创建MessageQueue
Looper提供的源码如下:
~~~
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
~~~
从源码第2行中可以看出,在创建Looper对象时会创建一个与之关联的MessageQueue对象。构造器是private修饰的,所以程序员是无法创建Looper对象的,就是说**创建Looper同时就创建了MessageQueue对象**
Handler:前面说Handler作用有两个---发送消息和处理消息,Handler发送的消息必须被送到指定的MessageQueue,也就是说,要想Handler正常工作必须在当前线程中有一个MessageQueue,否则消息没法保存。**而MessageQueue是由Looper负责管理的**,因此要想Handler正常工作,**必须在当前线程中有一个Looper对象**,这里分为两种情况:
1>主线程(UI线程),系统已经初始化了一个Looper对象,因此程序直接创建Handler即可
2>程序员自己创建的子线程,这时,程序员必须创建一个Looper对象,并启动它。
创建Looper:使用Looper.prepare(),查看源码
~~~
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
~~~
通过方法调用,第9行创建Looper对象,创建Looper对象时同时会创建MessageQueue对象(第13行)。此外,可以看出prepare()允许一个线程最多有一个Looper被创建
启动Looper:Looper.loop(),loop()使用一个死循环不断取出MessageQueue中的消息,并将消息发送给对应的Handler进行处理。下面是Looper类中looper()方法的部分源码
~~~
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
~~~
很明显第1行用了一个死循环,第2行从queue中取出Message,第15行通过dispatchMessage(Message msg)方法将消息发送给Handler。
Looper,MessageQueue,Handler的各自作用如下:
Looper:每个线程只有一个Looper,他负责管理MessageQueue,会不断的从MessageQueue中取出消息,将消息交给对应的Handler处理
MessageQueue:由Looper负责管理,是用来存放线程放入的消息。
Handler:它把消息发送给Looper管理的MessageQueue,并负责处理Looper分给它的消息
在线程中Handler的使用步骤是:
(1)调用 Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue。
(2)有了Looper之后,创建Handler子类的实例,重写HandlerMessage()方法,该方法负责处理来自其它线程的消息。
(3)调用Looper的loop()方法启动Looper。
Handler消息传递机制(一)
最后更新于:2022-04-01 16:14:34
为什么要用Handler:
出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发操作UI组件,可能导致线程安全问题。为了解决这个问题,Android制定了一条简单的原则:只允许UI线程(亦即主线程)修改Activity中的UI组件。
当一个程序第一次启动时,Android会同时启动一条主线程,主线程主要负责处理与UI相关的事件,如用户的按键事件、用户接触屏幕的事件、屏幕绘图事件,并把相关的事件分发到相应的组件进行处理,所以主线程通常又叫做UI线程。
Handler的概念:
1)**执行计划任务**,可以在预定的时间执行某些任务,可以模拟定时器
2)**线程间通信**。在Android的应用启动时,会创建一个主线程,主线程会创建一个
消息队列来处理各种消息。**当你创建子线程时,你可以在你的子线程中拿到父线程中
创建的Handler 对象,就可以通过该对象向父线程的消息队列发送消息了**。由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面。
Handler类包含如下方法用于发送、处理消息:
♦ void handlerMessage(Message msg):处理消息的方法,该方法通常用于被重写。
♦ final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息。
♦ sendEmptyMessage(int what):发送空消息
♦ final boolean sendMessage(Message msg):立即发送消息,注意这块返回值,如果message成功的被放到message queue里面则返回true,反之,返回false;(个人建议:对于这类问题不必主观去记它,当实际使用时,直接查看源码即可,源码中有详细的注释)
Handler的作用:
(1)在一个线程中发送消息。
(2)在另一个线程中获取、处理消息。
Handler处理的基本原理:
为了让主线程能及时处理子线程发送的消息,显然只能通过回调的方法来实现----开发者只要重写Handler类中的方法,**当新启动的线程发送消息时,消息会发送至与之关联的MessageQueue,而Handler会不断的从MessageQuere中获取并处理消息**-----这将导致Handler类中处理消息的方法被回调。
在线程中使用Handler的基本步骤如下:
在被调用线程中完成以下内容:
(1)调用 Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue。
(2)有了Looper之后,创建Handler子类的实例,重写HandlerMessage()方法,该方法负责处理来自其它线程的消息。
(3)调用Looper的loop()方法启动Looper。
注:若被调用线程是主线程类,由于系统自动为主线程创建了Looper的实例,因此第一、三步骤可省略,而只需要做第2步即可。
在调用线程中完成:
(1)创建message,并填充内容。
(2)使用被调用类创建的Handler实例,调用sendMessage(Message msg)方法。
Handler 与线程的关系
Handler 一般运行于主线程内,也可以运行在子线程中,但是一定要创建Looper对象。主线程中Android已经为之创建了Looper对象
使用Handler的两种常见情况:
1、只能在主UI中修改UI。但实际上,**有部分UI需要在子线程中控制其修改逻辑,因此子线程需要通过handler通知主线程修改UI**。这在游戏开发中尤其常见,比如需要让新启动的线程周期性的改变UI。、
**子线程通知主UI线程修改UI组件**的例子,新线程周期性的修改ImageView所显示的图片:
**这个例子是Handler在主线程中获取,处理消息,在子线程中发送消息**
~~~
public class HandlerTest extends Activity
{
// 定义周期性显示的图片的ID
int[] imageIds = new int[]
{
R.drawable.java,
R.drawable.ee,
R.drawable.ajax,
R.drawable.xml,
R.drawable.classic
};
int currentImageId = 0;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ImageView show = (ImageView) findViewById(R.id.show);
final Handler myHandler = new Handler()//在主线程中,获取,处理消息,更新UI组件,可以修改UI组件
{
@Override
public void handleMessage(Message msg)
{
// 如果该消息是本程序所发送的
if (msg.what == 0x1233)
{
// 动态地修改所显示的图片
show.setImageResource(imageIds[currentImageId++
% imageIds.length]);
}
}
};
// 定义一个计时器,让该计时器周期性地执行指定任务。子线程通知主线程修改UI组件,实现进程间通信
new Timer().schedule(new TimerTask()
{
@Override
public void run()
{
// 发送空消息
myHandler.sendEmptyMessage(0x1233);在线程中发送消息
}
}, 0, 1200);
}
}
~~~
2、为避免ANR,**应该在子线程中执行耗时较长的操作,而此操作完成后,有可能需要通知主线程修改UI**。
**在子线程中执行耗时任务后,通知主线程修改UI组件**的例子:使用新进程计算质数,并用Toast显示
**这个例子是在主线程中发送消息,在子线程中获取,处理消息**
~~~
public class CalPrime extends Activity
{
static final String UPPER_NUM = "upper";
EditText etNum;
CalThread calThread;
// 定义一个线程类
class CalThread extends Thread
{
public Handler mHandler;
public void run()
{
Looper.prepare();//创建Looper对象,每个线程使用Handler时都要有一个Looper对象
mHandler = new Handler()//在子线程中用handler获取,处理消息
{
// 定义处理消息的方法
@Override
public void handleMessage(Message msg)
{
if(msg.what == 0x123)
{
int upper = msg.getData().getInt(UPPER_NUM);
List<Integer> nums = new ArrayList<Integer>();
// 计算从2开始、到upper的所有质数
outer:
for (int i = 2 ; i <= upper ; i++)
{
// 用i处于从2开始、到i的平方根的所有数
for (int j = 2 ; j <= Math.sqrt(i) ; j++)
{
// 如果可以整除,表明这个数不是质数
if(i != 2 && i % j == 0)
{
continue outer;
}
}
nums.add(i);
}
// 使用Toast显示统计出来的所有质数
Toast.makeText(CalPrime.this , nums.toString()
, Toast.LENGTH_LONG).show();
}
}
};
Looper.loop();//启动Looper
}
}
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
etNum = (EditText)findViewById(R.id.etNum);
calThread = new CalThread();
// 启动新线程
calThread.start();
}
// 为按钮的点击事件提供事件处理函数
public void cal(View source)
{
// 创建消息
Message msg = new Message();
msg.what = 0x123;
Bundle bundle = new Bundle();
bundle.putInt(UPPER_NUM ,
Integer.parseInt(etNum.getText().toString()));
msg.setData(bundle);
// 在主线程中向新线程中的Handler发送消息
calThread.mHandler.sendMessage(msg);//在主线程中发送消息
}
}
~~~
Android基于回调的事件处理
最后更新于:2022-04-01 16:14:32
基于回调的事件处理模型更加简单:
如果说事件监听机制是一种委托式的事件处理,那么回调机制则恰好与之相反:对于基于回调的时间处理模型来说,事件源和事件监听器是统一的,或者说事件监听器完全消失了。当用户在GUI组件上激发某个事件时,组件自己特定的方法将会负责处理该事件
因此回调监听机制只需继承该组件,并重写该组件类的事件处理方法来实现
为了事件回调机制的事件处理,Android为所有GUI组件都提供了一些事件处理回调方法,以View为例:
Boolean onKeyDown(int keyCode,KeyEvent event);当用户在该组件上按下某个按键时触发该方法
boolean onKeyShortcut(int keyCode,KeyEvent event);当一个键盘快捷键事件发生时触发该方法
Boolean onKeyLongPress(int keyCode,KeyEvent event),当用户在该组件上长按某个按键时触发该方法
boolean onTouchEvent(int keyCode,KeyEvent event);当用户在该组件上触发触摸屏事件时触发该方法
...等等
MainActivity.java
~~~
public class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
~~~
main.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"
>
<!-- 使用自定义View时应使用全限定类名 -->
<org.crazyit.event.MyButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="单击我"
/>
</LinearLayout>
~~~
MyButton.java
~~~
public class MyButton extends Button
{
public MyButton(Context context, AttributeSet set)
{
super(context, set);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
super.onKeyDown(keyCode, event);
Log.v("-crazyit.org-", "the onKeyDown in MyButton");
// 返回true,表明该事件不会向外扩散
return true;
}
}
~~~
Android基于监听的事件处理机制
最后更新于:2022-04-01 16:14:29
Android提供了强大的事件处理机制,主要包括两大类:
1,基于监听的事件处理机制:主要做法是为Android界面组件绑定特定的事件监听器
2,基于回调的事件处理机制:主要做法是重写Android组件特定的回调方法,或重写Activity的回调方法。也就是说Android的绝大多数的界面组件都提供了事件响应的回调方法,开发者只要重写它们即可
基于监听的事件处理是一种更加面向对象的事件处理,这种事件处理方式与Java的Swing处理方式几乎相同。
**监听处理模型:**
**事件源(Event Source)**:事件发生的场所,就是各个组件,比如按钮,窗口,菜单等
**事件(Event)**:事件封装了界面组件上发生的特定事情(就是用户操作)。如果程序需要获得界面组件上所发生事件的相关信息,一般通过Event对象来获取
**事件监听器(Event Listener)**:负责监听事件源所发生的时间,并且对各个事件作出响应。
**委派式事件处理方法:**
普通组件(事件源)将整个事件处理委派给特定的对象(事件监听器);当该事件源发生指定的时间是,就通知所委派的事件监听器来处理这个事件。
每个组件都可以针对特定的时间指定一个事件监听器,每个事件监听器也可以监听一个或多个事件源。因为同一个事件源上可能发生多个事件,委派式事件处理方式可以吧事件源上所有可能发生的时间分别授权给不同的事件处理器来处理;同时也可以让一类事件都使用同一个事件监听器来处理。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9b015680.jpg)
activity_main.xml
~~~
<?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"
android:gravity="center_horizontal"
>
<EditText
android:id="@+id/txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:editable="false"
android:cursorVisible="false"
android:textSize="12pt"
/>
<!-- 定义一个按钮,该按钮将作为事件源 -->
<Button
android:id="@+id/bn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="单击我"
/>
</LinearLayout>
~~~
MainActivity.java
~~~
public class <span style="font-size:24px;">MainActivity </span>extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取应用程序中的bn按钮
Button bn = (Button) findViewById(R.id.bn);
// 为按钮绑定事件监听器。
bn.setOnClickListener(new MyClickListener()); // ①
}
// 定义一个单击事件的监听器
class MyClickListener implements View.OnClickListener
{
// 实现监听器类必须实现的方法,该方法将会作为事件处理器
@Override
public void onClick(View v)
{
EditText txt = (EditText) findViewById(R.id.txt);
txt.setText("bn按钮被单击了!");
}
}
}
~~~
基于监听器的事件处理模型的编程步骤如下:
1,获取普通界面组件(事件源),也就是被监听的对象
2,实现时间监听类,该监听器类是一个特殊的Java类,必须实现一个XxxListener接口
3,调用事件源的setXXXListener方法,将事件监听器对象注册给普通组件(事件源)
事件监听器必须实现事件监听接口,Android的不同界面组件提供了不同的监听器接口,这些接口通常以内部类的形式存在。以View类为例,包含如下监听接口:
View.OnClickListener单击事件的事件监听器必须时间的接口
View.OnCreateContextMenuListener:创建上下文菜单时间的事件监听器必须实现的接口
View.onFocusChangeListener:焦点改变事件的事件监听器必须实现的接口
View.OnKeyListener:按键事件的时间监听器必须实现的接口
**所谓事件监听器,其实就是实现了特定接口的java类的实例。在程序上一般有几种形式:**
1,内部类形式:将事件监听器定义成当前类的内部类
~~~
public class EventQs extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取应用程序中的bn按钮
Button bn = (Button) findViewById(R.id.bn);
// 为按钮绑定事件监听器。
bn.setOnClickListener(new MyClickListener()); //
}
// 定义一个单击事件的监听器,内部类形式
class MyClickListener implements View.OnClickListener
{
// 实现监听器类必须实现的方法,该方法将会作为事件处理器
@Override
public void onClick(View v)
{
EditText txt = (EditText) findViewById(R.id.txt);
txt.setText("bn按钮被单击了!");
}
}
}
~~~
**因为监听器是内部类,所以可以自由访问外部类的所有界面组件,这也是内部类的优势。**
2,外部类形式:将事件监听器类定义成一个外部类
外部类形式的事件监听器不能自由访问创建GUI界面类的组件,使用时需要向监听器类传递GUI界面类的组件的引用 ,所以用的比较少
MainActivity.java
~~~
public class MainActivity extends Activity
{
EditText address;
EditText content;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 获取页面中收件人地址、短信内容
address = (EditText)findViewById(R.id.address);
content = (EditText)findViewById(R.id.content);
Button bn = (Button)findViewById(R.id.send);
bn.setOnLongClickListener(new SendSmsListener(
this , address, content));//外部类形式,需要传递本类组件
}
}
~~~
SendSmsListener.java
~~~
public class SendSmsListener implements OnLongClickListener
{
private Activity act;
private EditText address;
private EditText content;
public SendSmsListener(Activity act, EditText address
, EditText content)
{
this.act = act;
this.address = address;
this.content = content;
}
@Override
public boolean onLongClick(View source)
{
String addressStr = address.getText().toString();
String contentStr = content.getText().toString();
// 获取短信管理器
SmsManager smsManager = SmsManager.getDefault();
// 创建发送短信的PendingIntent
PendingIntent sentIntent = PendingIntent.getBroadcast(act
, 0, new Intent(), 0);
// 发送文本短信
smsManager.sendTextMessage(addressStr, null, contentStr
, sentIntent, null);
Toast.makeText(act, "短信发送完成", Toast.LENGTH_LONG).show();
return false;
}
}
~~~
3,Activity本身作为事件监听器类:让Activity本身实现监听接口,并实现事件处理器方法
~~~
// <span style="font-size:24px;">Activity</span>实现事件监听器接口
public class ActivityListener extends Activity
implements OnClickListener
{
EditText show;
Button bn;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
show = (EditText) findViewById(R.id.show);
bn = (Button) findViewById(R.id.bn);
// 直接使用Activity作为事件监听器
bn.setOnClickListener(this);
}
// 实现事件处理方法
@Override
public void onClick(View v)
{
show.setText("bn按钮被单击了!");
}
}
~~~
4,匿名内部类形式:使用匿名内部类创建事件监听器对象。代码简单的情况,只能用一次
~~~
public class MainActivity extends Activity
{
EditText show;
Button bn;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
show = (EditText) findViewById(R.id.show);
bn = (Button) findViewById(R.id.bn);
// 直接使用Activity作为事件监听器
bn.setOnClickListener(new OnClickListener()
{
// 实现事件处理方法
@Override
public void onClick(View v)
{
show.setText("bn按钮被单击了!");
}
});
}
~~~
AlertDialog创建6种对话框的用法
最后更新于:2022-04-01 16:14:27
AlertDialog生成的对话框可分为4个区域:图标区,标题区,内容区,按钮区
结构如图:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9af34ce4.jpg)
AlertDialog对话框的使用:
1,**创建AlertDialog.Builder对象**
2,调用Builder对象的**setTitle()设置标题,setIcon设置图标**
3,调用Builder对象的相关方法**设置内容**,AlertDialog提供如下六中设置指定对话框的内容:
setMessage();设置简单文本框的内容
setItems();设置简单列表的内容,数组
setSingleChoiceItems();;设置单选列表的内容,内容参数可以是数组Cursor,ListAdapter
setMultiChoiceItems();设置多选列表项的内容,内容参数可以是数组,Cursor
setAdapter();设置内容,内容是ListAdapter,常用的BaseAdapter,SimpleAdapter,ArrayAdapter
setView();设置内容,参数是自定义的View
4,调用Builder对象的**setPositiveButton()和 setNegativeButton()设置按钮和监听器**
5,调用Builder对象的**create()方法**创建AlertDialog对象,再调用AlertDialog对象的**show()方法**显示对话框
总之:调用Builder对象设置图标,标题,内容,按钮,在create(),show()
代码模板:
~~~
new AlertDialog.Builder(this)
// 设置对话框标题
.setTitle("简单对话框")
// 设置图标
.setIcon(R.drawable.tools)
//设置内容,可代替
.setMessage("对话框的测试内容\n第二行内容").setPositiveButton("确定",listener).setNegativeButton("取消",listener).create().show();
~~~
acitivity_main.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="TextView" />
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TableRow
android:id="@+id/tableRow1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="simple"
android:text="简单文本" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="simpleList"
android:text="数组列表" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="singleChoice"
android:text="单选列表" />
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal" >
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="multiChoice"
android:text="多选列表" />
<Button
android:id="@+id/button5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="customList"
android:text="自定义列表" />
<Button
android:id="@+id/button6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="customView"
android:text="自定义View" />
</TableRow>
</TableLayout>
</LinearLayout>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9af45e91.jpg)
MainActivity.java
~~~
package com.hust.alertdialogtest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.DialogInterface.OnMultiChoiceClickListener;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.TableLayout;
import android.widget.TextView;
/*AlertDialog对话框的使用:
* AlertDialog对话框有四个区域:图标区,标题区,内容区,按钮区
* 1,创建AlertDialog.Builder对象
* 2,调用Builder对象的setTitle()设置标题,setIcon设置图标
* 3,调用Builder对象的相关方法设置内容
* setMessage();设置简单文本框的内容
* setItems();设置简单列表的内容,数组
* setSingleChoiceItems();;设置单选列表的内容,内容参数可以是数组,Cursor,ListAdapter
* setMultiChoiceItems();设置多选列表项的内容,内容参数可以是数组,Cursor
* setAdapter();设置内容,内容是ListAdapter,常用的BaseAdapter,SimpleAdapter,ArrayAdapter
* setView();设置内容,参数是自定义的View
* 4,调用Builder对象的setPositiveButton()和 setNegativeButton()设置按钮和监听器
* 5,调用Builder对象的create()方法创建AlertDialog对象,再调用AlertDialog对象的show()方法显示对话框
*
*
* 总之:调用Builder对象设置图标,标题,内容,按钮,在create(),show()
* */
public class MainActivity extends Activity {
TextView show;
String[] items=new String[]{
"湖北省","福建省","贵州省","四川省"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show=(TextView) findViewById(R.id.textView1);
}
/*简单文本对话框:builder.setMessage()设置内容*/
public void simple(View v){
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("简单对话框");
builder.setIcon(R.drawable.tools);
builder.setMessage("这是简单文本对话框\n第二行内容");
//为builder对象添加确定按钮,不过这里嵌套了一个函数
setPositiveButton(builder);
//为builder对象添加取消按钮
builder=setNegativeButton(builder);
//builder创建对话框对象AlertDialog
AlertDialog simpledialog=builder.create();
simpledialog.show();
}
/*简单列表对话框(数组对话框):builder.setItems()设置内容*/
public void simpleList(View v){
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("数组列表对话框");
builder.setIcon(R.drawable.tools);
builder.setItems(items, new OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
show.setText("你单击了 "+items[which]);
}
});
setPositiveButton(builder);
builder=setNegativeButton(builder);
AlertDialog simplelistdialog=builder.create();
simplelistdialog.show();
}
/*单选列表项对话框:builder.setSingleChoiceItems()设置内容,内容参数可以是数组,Cursor,ListAdapter*/
public void singleChoice(View v){
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("单选列表项对话框");
builder.setIcon(R.drawable.tools);
//设置单选列表项,默认选中第二项
builder.setSingleChoiceItems(items,1, new OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
show.setText("你单击了 "+items[which]);
}
});
setPositiveButton(builder);
builder=setNegativeButton(builder);
AlertDialog simplechoicedialog=builder.create();
simplechoicedialog.show();
}
/*
*
*多选列表项对话框: builder.setMultiChoiceItems()设置内容,参数可以是数组,Cursor数据库返回结果集
*
* AlertDialog.Builder.setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, OnMultiChoiceClickListener listener)*/
public void multiChoice(View v){
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("多选列表项对话框");
builder.setIcon(R.drawable.tools);
//设置单多选列表项,默认选中第二项,第四项
builder.setMultiChoiceItems(items,new boolean[]{false,true,false,true},new OnMultiChoiceClickListener(){
@Override
public void onClick(DialogInterface dialog, int which,
boolean isChecked) {
// TODO Auto-generated method stub
//添加处理方法
}
});
setPositiveButton(builder);
builder=setNegativeButton(builder);
AlertDialog simplechoicedialog=builder.create();
simplechoicedialog.show();
}
/*自定义Adapter对话框:builder.setAdapter设置内容,内容是ListAdapter,常用的BaseAdapter,SimpleAdapter,ArrayAdapter*/
public void customList(View v){
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("自定义Adapter对话框");
builder.setIcon(R.drawable.tools);
builder.setAdapter(new ArrayAdapter<String>(this,R.layout.array_item,items), new OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
show.setText("你单击了 "+items[which]);
}
});
//为builder对象添加确定按钮,不过这里嵌套了一个函数
setPositiveButton(builder);
//为builder对象添加取消按钮
builder=setNegativeButton(builder);
//builder创建对话框对象AlertDialog
AlertDialog adapterdialog=builder.create();
adapterdialog.show();
}
/*自定义View对话框:builder.setView()设置View*/
public void customView(View v){
//获取xml布局文件对象
TableLayout loginform=(TableLayout) getLayoutInflater().inflate(R.layout.login, null);
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("自定义View对话框");
builder.setIcon(R.drawable.tools);
//设置对话框显示的View组件
builder.setView(loginform);
//为builder对象添加确定按钮,不过这里嵌套了一个函数
setPositiveButton(builder);
//为builder对象添加取消按钮
builder=setNegativeButton(builder);
//builder创建对话框对象AlertDialog
AlertDialog viewdialog=builder.create();
viewdialog.show();
}
//返回对象是原来的Builder对象
private AlertDialog.Builder setPositiveButton(AlertDialog.Builder builder) {
// TODO Auto-generated method stub
return builder.setPositiveButton("确定", new OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
show.setText("单击了【确定】按钮!");
}
});
}
//返回对象是Builder对象
private AlertDialog.Builder setNegativeButton(AlertDialog.Builder builder) {
// TODO Auto-generated method stub
return builder.setNegativeButton("取消", new OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
show.setText("单击了【取消】按钮!");
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9af5ad4a.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9af6f20f.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9af913ea.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9afab17c.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9afca5c9.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9afe773c.jpg)
TabHost选项卡的 功能和用法
最后更新于:2022-04-01 16:14:25
TabHost可以很方便地在窗口上放置多个标签页,每个标签页相当于获得了一个外部容器相同大小的组件摆放区域
TabHost的主要组件是:
TabWiget:代表一个选项卡标签条
TabSpec:代表选项卡的一个Tab页
TabHost的基本用法:
1,在界面布局中定义TabHost组件,并未改组件定义该选项卡的内容
2,继承TabActivity
3,调用TabActivity的getTabHost()方法获取TabHost对象(获取)
4,TabHost对象的addTab方法创建,添加选项卡(添加)
activity_main.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<!--TabHost布局文件的结构:
1,TabHost容器必须包含TabWidget,FrameLayout
2,FrameLayout则用于“层叠”组合多个选项页面,TabWidget定义选项卡的标题条,随FrameLayout中的层叠组件均分
3,三个组件的ID有要求:
TabHost的ID必须是android:id="@android:id/tabhost"
TabWidget的ID必须是 android:id="@android:id/tabs"
FrameLayout的ID必须是 android:id="@android:id/tabcontent"
-->
<!-- 定义一个TabHost, ID必须是android提供的ID,android:id="@android:id/tabhost"-->
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/tabhost"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_weight="1"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- 定义一个TabWiget选项卡标题条,ID必须是android提供的ID,android:id="@android:id/tabs" -->
<TabWidget
android:id="@android:id/tabs"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<!-- 定义一个帧布局FrameLayout,代表一个Tab页面,ID必须是android提供的ID, android:id="@android:id/tabcontent" -->
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!-- 当然可以放其他复杂的布局 -->
<LinearLayout
android:id="@+id/tab01"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="第一个Tab页"
android:textSize="20dp"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/tab02"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="第二个Tab页"
android:textSize="20dp"
/>
</LinearLayout>
<LinearLayout
android:id="@+id/tab03"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="第三个Tab页"
android:textSize="20dp"
/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
~~~
TabHost布局文件的特点是:
TabHost布局文件的结构:
1,TabHost容器必须包含TabWidget,FrameLayout
2,FrameLayout则用于“层叠”组合多个选项页面,TabWidget定义选项卡的标题条,随FrameLayout中的层叠组件均分
3,三个组件的ID有要求:
TabHost的ID必须是android:id="@android:id/tabhost"
TabWidget的ID必须是 android:id="@android:id/tabs"
FrameLayout的ID必须是 android:id="@android:id/tabcontent"
MainActivity.java
~~~
package com.example.tabhosttest;
import android.app.Activity;
import android.app.TabActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;
public class MainActivity extends TabActivity {//继承的是TabActivity
/*TabHost的基本用法:
* 1,在界面布局中定义TabHost组件,并未改组件定义该选项卡的内容
* 2,继承TabActivity
* 3,调用TabActivity的getTabHost()方法获取TabHost对象
* 4,TabHost对象的addTab方法创建,添加选项卡
* */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取该activity里面的TabHost组件
TabHost tabhost=getTabHost();
//创建第一个tab页对象,TabSpec代表一个选项卡页面,要设置标题和内容,内容是布局文件中FrameLayout中
TabSpec tab1=tabhost.newTabSpec("tab1");
tab1.setIndicator("已接电话");//设置标题
tab1.setContent(R.id.tab01);//设置内容
//添加tab页
tabhost.addTab(tab1);
//创建第二个tab页对象
TabSpec tab2=tabhost.newTabSpec("tab1");
tab2.setIndicator("已拨电话");//设置标题
tab2.setContent(R.id.tab02);//设置内容
//添加tab页
tabhost.addTab(tab2);
//创建第三个tab页对象
TabSpec tab3=tabhost.newTabSpec("tab1");
tab3.setIndicator("未接电话");//设置标题
tab3.setContent(R.id.tab03);//设置内容
//添加tab页
tabhost.addTab(tab3);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9aeebb38.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9af0a456.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9af1cf4d.jpg)
Toast的功能和用法
最后更新于:2022-04-01 16:14:23
使用Toast显示提示信息框:不仅可以显示简单的提示信息,还可以显示自定义的View
使用Toast显示提示信息非常简单:
1,调用Toast的构造器或者makeText()静态方法创建一个Toast对象
2,调用Toast的方法来设置消息提示的对齐方式,页边距等
3,调用Toast的show()方法将它显示出来
大部分时候Toast显示的是简单的消息文本;
~~~
Toast.makeText(MainActivity.this, "简单的提示信息", Toast.LENGTH_SHORT).show()
~~~
当要显示自定义的View,包含图片,列表之类的复杂提示时,需要调用Toast构造器创建实例,再调用setView方法设置该Toast的View组件
activity_main.xml
~~~
<?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"
>
<Button
android:id="@+id/simple"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示简单提示" />
<Button
android:id="@+id/bn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="显示带图片的提示"
/>
</LinearLayout>
~~~
MainActivity.java
~~~
package com.example.toast;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button simple = (Button) findViewById(R.id.simple);
// 为按钮的单击事件绑定事件监听器
simple.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
// 创建一个Toast提示信息
Toast toast = Toast.makeText(MainActivity.this
, "简单的提示信息"
// 设置该Toast提示信息的持续时间
, Toast.LENGTH_SHORT);
toast.show();
//或者Toast.makeText(MainActivity.this, "简单的提示信息", Toast.LENGTH_SHORT).show()
}
});
Button bn = (Button) findViewById(R.id.bn);
// 为按钮的单击事件绑定事件监听器
bn.setOnClickListener(new OnClickListener()
{
@Override
public void onClick(View source)
{
// 创建一个Toast提示信息
Toast toast = new Toast(MainActivity.this);
// 设置Toast的显示位置
toast.setGravity(Gravity.CENTER, 0, 0);
// 创建一个ImageView
ImageView image = new ImageView(MainActivity.this);
image.setImageResource(R.drawable.tools);
// 创建一个LinearLayout容器
LinearLayout ll = new LinearLayout(MainActivity.this);
// 向LinearLayout中添加图片、原有的View
ll.addView(image);
// 创建一个ImageView
TextView textView = new TextView(MainActivity.this);
textView.setText("带图片的提示信");
// 设置文本框内字体的大小和颜色
textView.setTextSize(30);
textView.setTextColor(Color.MAGENTA);
ll.addView(textView);
// 设置Toast显示自定义View ,Toast里面可以设置View
toast.setView(ll);
// 设置Toast的显示时间
toast.setDuration(Toast.LENGTH_LONG);
toast.show();
}
});
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9aeace97.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9aecd2f8.jpg)
ViewFlipper的功能和用法
最后更新于:2022-04-01 16:14:20
ViewFlipper组件继承了ViewAnimator,它可以调用addView(View v)添加多个组件向ViewFlipper中添加多个组件之后,ViewFlipper可使用动画控制多个组件之间的切换效果
ViewAnimator是一个基类,它继承的是FrameLayout,因此可以将多个View组件“叠加”在一起,ViewAnimator额外增加的功能就是可以在View切换时表现出动画效果。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ae49b7c.jpg)
ViewFlipper继承了ViewAnimation,额外增加的新功能如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ae5bd25.jpg)
eg.自动播放的图片库
acitivity_main.xml
~~~
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.viewflippertest.MainActivity" >
<!-- ViewFlipper组件,放了三个ImageView组件-->
<ViewFlipper
android:id="@+id/viewFlipper1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="80dp"
android:layout_marginTop="34dp"
android:flipInterval="1000" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/bomb10" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/bomb11" />
<ImageView
android:id="@+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/bomb12" />
</ViewFlipper>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="32dp"
android:onClick="prev"
android:text="<" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="@+id/button1"
android:onClick="auto"
android:text="Auto" />
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/button2"
android:layout_alignBottom="@+id/button2"
android:layout_toRightOf="@+id/button2"
android:onClick="next"
android:text=">" />
</RelativeLayout>
~~~
MainActvity.java
~~~
package com.example.viewflippertest;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ViewFlipper;
public class MainActivity extends Activity {
ViewFlipper cf;//ViewFlipper对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
cf=(ViewFlipper) findViewById(R.id.viewFlipper1);
}
//响应按钮函数
public void prev(View v){
cf.setInAnimation(this,R.anim.slide_in_right);
cf.setOutAnimation(this,R.anim.slide_out_left);
cf.showPrevious();
//停止切换
cf.stopFlipping();
};
//响应按钮函数
public void auto(View v){
cf.setInAnimation(this,R.anim.slide_in_right);
cf.setOutAnimation(this,R.anim.slide_out_left);
cf.startFlipping();
};
//响应按钮函数
public void next(View v){
cf.setInAnimation(this,R.anim.slide_in_left);
cf.setOutAnimation(this,R.anim.slide_out_right);
cf.showNext();
//停止切换
cf.stopFlipping();
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
slide_in_left.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置从左边拖进来的动画
android:duration指定动画持续时间 -->
<translate
android:fromXDelta="-100%p"
android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>
~~~
slide_in_right.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置从右边拖进来的动画
android:duration指定动画持续时间 -->
<translate
android:fromXDelta="100%p"
android:toXDelta="0"
android:duration="@android:integer/config_mediumAnimTime" />
</set>
~~~
slide_out_left.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置从左边拖出去的动画
android:duration指定动画持续时间 -->
<translate
android:fromXDelta="0"
android:toXDelta="-100%p"
android:duration="@android:integer/config_mediumAnimTime" />
</set>
~~~
slide_out_right.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 设置从左边拖出去的动画
android:duration指定动画持续时间 -->
<translate
android:fromXDelta="0"
android:toXDelta="100%p"
android:duration="@android:integer/config_mediumAnimTime" />
</set>
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ae75026.jpg)
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ae8f29c.jpg)
UI组件之ProgressBar及其子类(二)SeekBar拖动条和RatingBar星级评分条的使用
最后更新于:2022-04-01 16:14:18
拖动条采用拖动滑块的位置来表示数值
SeekBar的常用xml属性值:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9adab0c3.jpg)
**重要的android:thumb制定一个Drawable对象,改变滑块外观**
通过滑块来改变图片的透明度:
main.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="300dp"
android:src="@drawable/lijiang" />
<!-- android:thumb 是滑块的图片, android:progressDrawable是滑条的图片 -->
<SeekBar
android:id="@+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:max="255"
android:progress="255"
android:thumb="@drawable/ic_launcher" />
<TextView
android:id="@+id/textView1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="25dp" />
<TextView
android:id="@+id/textView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="25dp" />
</LinearLayout>
~~~
MainActivity.java
~~~
package com.example.seekbartest;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView image =(ImageView) findViewById(R.id.imageView1);
SeekBar seekbar=(SeekBar) findViewById(R.id.seekBar1);
final TextView textView1 = (TextView) this.findViewById(R.id.textView1);
final TextView textView2 = (TextView) this.findViewById(R.id.textView2);
//设置拖动条的状态改变监听器
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
//当拖动条的滑块位置发生改变时触发该方法
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
image.setAlpha(progress);//设置图片透明度
textView1.setText("当前值:"+progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
textView2.setText("拖动中...");
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
textView2.setText("拖动完毕");
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9adc1224.jpg)
自定义拖动条比较好,留着以后借鉴:[http://blog.csdn.net/imdxt1986/article/details/7609164](http://blog.csdn.net/imdxt1986/article/details/7609164)
星级评分条的常用xml属性:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9adedfcb.jpg)
android:isIndicator:设置该评分条是否允许用户改变(true为不允许修改)
android:numStars:设置总共有多少个星级
android:rating设置星级评分条默认的星级
android:stepSize设置没吃最少需要改变多少个星级,0.5半个星星,1就是1个星星
使用星级评分改变图片透明度:
main.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="300dp"
android:src="@drawable/lijiang" />
<RatingBar
android:id="@+id/ratingBar1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:max="255"
android:numStars="6"
android:progress="255"
android:stepSize="0.5" />
</LinearLayout>
~~~
MainActivity.java
~~~
package com.example.ratingbartest;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.RatingBar.OnRatingBarChangeListener;
import android.widget.SeekBar;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ImageView image =(ImageView) findViewById(R.id.imageView1);
RatingBar bar=(RatingBar) findViewById(R.id.ratingBar1);
//设置星级评论条状态改变监听器
bar.setOnRatingBarChangeListener(new OnRatingBarChangeListener(){
@Override
public void onRatingChanged(RatingBar ratingBar, float rating,
boolean fromUser) {
// TODO Auto-generated method stub
image.setAlpha((int)(rating*255/6));//设置图片透明度
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ae10f14.jpg)
UI组件之 ProgressBar及其子类(一)ProgressBar进度条的使用
最后更新于:2022-04-01 16:14:16
ProgressBar本身进度条组件,它派生了:SeekBar和RatingBar两个组件,他们的继承关系如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ad706fb.jpg)
**1、ProgressBar有两个进度,**一个是android:progress,另一个是android:secondaryProgress。后者主要是为缓存需要所涉及的,比如在看网络视频时候都会有一个缓存的进度条以及还要一个播放的进度,在这里缓存的进度就可以是android:secondaryProgress,而播放进度就是android:progress,有了secondProgress,可以很方便定制ProgressBar。
**2、ProgressBar分为确定的和不确定的**,确定的是我们能明确看到进度,相反不确定的就是不清楚、不确定一个操作需要多长时间来完成,这个时候就需要用的不确定的ProgressBar了。属性android:indeterminate如果设置为true的话,那么ProgressBar就可能是圆形的滚动条或者水平的滚动条(由样式决定),但是我们一般时候,是直接使用Style类型来区分圆形还是水平ProgressBar的。
进度条的常用xml属性如下:
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ad80548.jpg)
其中根据**Style属性**的设置不同,可以指定ProgressBar的3种环形进度条和1中水平进度条:
1,大环形进度条 style="?android:attr/progressBarStyleLarge或者style="?android:attr/progressBarStyleLargeInverse"
2,普通环形进度条:style="android:progressBarStyle"
3,小环形进度条:style="?android:attr/progressBarStyleSmall"
4,普通水平进度条:style=“?android:attr/progressBarStyleHorizontal”
**常用属性解释:**
android:max:设置进度条的最大值
android:progress:设置已完成进度条的进度值
android:progressDrawable:设置进度条轨道对应的Drawable对象。可以是一个LayerDrawable对象
android:indeterminate:设置属性是true,设置进度条不精确显示的进度,就是环形进度条的进度值
android:indeterminateDrawable:设置绘制不精确显示的精度的Drawable对象,就是环形进度的轨道Drawable对象;
android:indeterminateDuration;设置不精确显示精度的持续时间
mybar.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 设置轨道背景 -->
<item android:id="@android:id/background"
android:drawable="@drawable/no"></item>
<!-- 设置轨道上已完成背景的样式 ,在上面-->
<item android:id="@android:id/progress"
android:drawable="@drawable/ok"></item>
</layer-list>
~~~
main.xml
~~~
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<!-- 大环形进度条 style="?android:attr/progressBarStyleLarge"-->
<ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleLargeInverse"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- 普通的中等进度条 -->
<ProgressBar
android:id="@+id/progressBar2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<!-- 小环形进度条 style="?android:attr/progressBarStyleSmall"-->
<ProgressBar
android:id="@+id/ProgressBar3"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="任务完成的进度"
android:textSize="20dp" />
<!-- 普通的水平进度条 -->
<ProgressBar
android:id="@+id/progressBar4"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0"
android:visibility="visible" />
<!-- 水平进度条,改变轨道外观 ,外观图片是在drawable里面,xml文件的layer-list元素编写-->
<ProgressBar
android:id="@+id/progressBar5"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:max="100"
android:paddingTop="20dp"
android:progressDrawable="@drawable/mybar" />
</LinearLayout>
~~~
MainActivity.java
~~~
package com.hust.progresbartest;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ProgressBar;
public class MainActivity extends Activity {
/*给程序模拟填充长度为100的数组*/
private int[] data=new int[100];
int hasData=0;
//记录ProgressBar的完成进度
int status=0;
ProgressBar bar,bar2;
//创建一个负责更新进度的Handler
Handler h=new Handler(){
public void handleMessage(Message msg){
if(msg.what==0x111){
//进度条设置已完成的值
bar.setProgress(status);
bar2.setProgress(status);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bar=(ProgressBar) findViewById(R.id.progressBar4);
bar2=(ProgressBar) findViewById(R.id.progressBar5);
//启动线程来执行任务
new Thread(){
public void run(){
while(status<100){
//获取耗时操作完成百分比
status=dowork();
//发送消息
h.sendEmptyMessage(0x111);
}
}
}.start();
}
//模拟一个耗时的操作
public int dowork(){
//为数组元素赋值
data[hasData++]=(int)(Math.random()*100);
try{
Thread.sleep(100);
}catch(InterruptedException e){
e.printStackTrace();
}
return hasData;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
~~~
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-03-10_56e0d9ad92d61.jpg)