編輯:Android開發實例
快速撥話程序是之前學習android appWidget(窗口小部件)時在eoe找下載的一個appWidget程序,
它主要是在桌面上產生一個聯系人的widget,點擊可以直接撥打電話。因為感覺缺少點內容,不是
那麼完美,所以現在有時間了就將它完善完善,添加了讀取聯系人圖像,ListView的數據源采用重
寫BaseAdapter進行綁定,並且添加了一個多線程加載聯系人信息等。而這個apk主要圍繞的內容也
是這幾方面Android下的AppWidget、Tab的使用、多線程(AsyncTask)的使用,聯系人的讀取
、自定義ListView使用。也許這些方面講得不深,就需要各位看官自己多多學習使用了。
效果圖:
(1)Tab:選項卡,在同一個界面中,選擇不同的選項卡,呈現不同界面布局。這裡添加選項卡一方
面是讀取系統中的聯系人列表、另一方面允許用戶自行輸入一個昵稱和電話號碼而產生一個快捷撥話
Widget。android中的Tab,一個TabSpec表示一個選項卡,而所有的TabSpec都由TabHost管理。
TabHost載入基本的xml布局文件。R.layout.main:最外層是框架布局,爾後是兩個TapSpec的LinearLayout布局
<FrameLayout android:id="@+id/FrameLayout01"
android:layout_width="fill_parent" android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout android:id="@+id/listPhone"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<ListView android:id="@+id/lvphone"
android:layout_width="fill_parent" android:layout_height="wrap_content"></ListView></LinearLayout>
<LinearLayout android:id="@+id/inputPhone"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical">
<TextView android:text="姓名"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></TextView>
<EditText android:id="@+id/etname"
android:layout_width="200px"
android:layout_height="wrap_content"
android:hint="請輸入聯系人姓名"></EditText>
<TextView android:text="電話號碼"
android:layout_width="wrap_content"
android:layout_height="wrap_content"></TextView>
<EditText android:id="@+id/etphone"
android:layout_width="200px"
android:layout_height="wrap_content"
android:phoneNumber="true"
android:hint="請輸入電話號碼"></EditText>
<Button android:id="@+id/btnadd"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text=" 保 存 "></Button>
<ImageView android:id="@+id/imgshow"
android:layout_width="wrap_content" android:layout_height="wrap_content"></ImageView>
</LinearLayout>
</FrameLayout>
Activity中載入Tab:
tabhost=this.getTabHost();
LayoutInflater.from(this).inflate(R.layout.main, tabhost.getTabContentView(),true);
TabSpec spec1=tabhost.newTabSpec("listPhone");
//setIndicator設置了TabSpec顯示的標題、圖標
spec1.setIndicator("聯系人", this.getResources().getDrawable(R.drawable.icon));
//R.id.listPhone是R.layout.main布局文件中的一個LinearLayout布局
spec1.setContent(R.id.listPhone);
TabSpec spec2=tabhost.newTabSpec("inputPhone");
spec2.setIndicator("直接錄入", this.getResources().getDrawable(R.drawable.icon));
spec2.setContent(R.id.inputPhone);
tabhost.addTab(spec1);
tabhost.addTab(spec2);
setContentView(tabhost);
(2)AppWidget:android的AppWidget使用也是配置比較多,首先是顯示在桌面上的布局appwidget.xml,很簡
單只有一個ImageView和TextView用來顯示聯系人的圖標和昵稱;其次是AppWidget配置xml,新建xml選擇
AppWidget Provider會自動產生一個文件在res/xml中,它包含了Widget在桌面的大小(74*單元格-2),
單位dip,Widget自動更新的周期(android:updatePeriodMillis),添加Widget時假如要先進入一個界面進行配置,
這個就指定了配置Activity是誰(android:configure="com.android.cbin.Main");最後就是在manifest.xml中
關於AppWidget的配置了桌面Widget布局xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:orientation="vertical"
android:id="@+id/widLinear" android:focusable="true" android:focusableInTouchMode="true"
android:clickable="true" android:clipChildren="true" android:background="@drawable/shortcallbg">
<ImageView android:layout_width="70px" android:layout_height="58px"
android:id="@+id/img"
android:layout_gravity="center"
android:layout_marginTop="10dip"
android:layout_marginLeft="1px" android:layout_marginRight="1px"
android:focusable="true" android:clickable="true"></ImageView>
<TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
android:singleLine="false" android:id="@+id/txtname"
android:layout_gravity="center"
android:gravity="center" android:layout_marginBottom="2px"></TextView>
</LinearLayout>
AppWidget配置xml:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="72dip" android:updatePeriodMillis="0" android:minHeight="72dip"
android:configure="com.android.cbin.Main">
</appwidget-provider>
manifest.xml中AppWidget配置信息:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.cbin"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".Main"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"></action>
</intent-filter>
</activity>
<receiver android:name="CallWidget">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action>
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/callwidget"></meta-data>
</receiver>
</application>
<uses-sdk android:minSdkVersion="7" />
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
</manifest>
(3)聯系人信息的讀取:包括電話號碼和姓名還有相片ID
public List<Map<String,Object>> getData(){
list=new ArrayList<Map<String,Object>>();
Map<String,Object> map;
ContentResolver resolver=this.getContentResolver();
Cursor cursor=resolver.query(ContactsContract.Contacts.CONTENT_URI, null
, null, null, null);
while(cursor.moveToNext()){
int cname=cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME);
String name=cursor.getString(cname);//獲得聯系人姓名
int cpid=cursor.getColumnIndex(PhoneLookup.PHOTO_ID);
String photoid=cursor.getString(cpid);
int cid=cursor.getColumnIndex(PhoneLookup._ID);
String id=cursor.getString(cid);//獲得聯系人ID
//聯系人是否有電話號碼
int has_p_n=cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER);
int phoneCount=cursor.getInt(has_p_n);
if(phoneCount>0){
Cursor numbers=resolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"="+id, null, null);
String number="";
while(numbers.moveToNext()){
int cnumber=numbers.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
number=numbers.getString(cnumber);
map =new HashMap<String, Object>();
map.put("name", name);
map.put("phone", number);
map.put("photo", photoid);
list.add(map);
}
numbers.close();
}
}
cursor.close();
return list;
}
通過聯系人PhotoID得到一個Bitmap對象
//獲取聯系人圖片
public static Bitmap getPhoto(Context ct,Object photo_id){
Bitmap bmp=BitmapFactory.decodeResource(ct.getResources(),
R.drawable.ic_contact_picture);
if(photo_id!="" && photo_id!=null){
String[] projection = new String[]{ContactsContract.Data.DATA15};
String selection = "ContactsContract.Data._ID = "+photo_id.toString() ;
Cursor cur = ct.getContentResolver().query(ContactsContract.Data.CONTENT_URI, projection, selection, null, null);
if(cur!=null){
cur.moveToFirst();
byte[] contactIcon = null;
contactIcon=cur.getBlob(cur.getColumnIndex(ContactsContract.Data.DATA15));
if(contactIcon!=null){
bmp=BitmapFactory.decodeByteArray(contactIcon, 0, contactIcon.length);
}
}
}
return bmp;
}
(4)自定義ListView:因為是自定義ListView所以我們必須重寫ListView的數據源對象BaseAdapter。添加一個與Item相對於的控件類ViewHolder,添加一個構造函數,傳入Context和List數據,Context對象用於獲得LayouInfalter(加載ListView的單個Item對象).重寫其中的
getCount()、getItem()、getItemId()、getView()四個方法;
public class MyAdapter extends BaseAdapter {
private Context context;
private List<Map<String,Object>> list;
private LayoutInflater mInflater;
public MyAdapter(Context ct,List<Map<String,Object>> lt){
context=ct;
list=lt;
mInflater=LayoutInflater.from(context);
}
public final class ViewHolder{
public ImageView image;
public TextView tvname;
public TextView tvphone;
public QuickContactBadge qcbimg;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
//返回List的size
if(list!=null){
return list.size();
}else{
return 0;
}
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
if(list!=null){
//返回某個位置的Map<String,Object>
return list.get(position);
}else{
return null;
}
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
//返回當前位置
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
//返回某個位置的View
ViewHolder holder=null;
if(convertView==null){
holder=new ViewHolder();
convertView=mInflater.inflate(R.layout.listitem, null);
holder.qcbimg=(QuickContactBadge) convertView.findViewById(R.id.qubimg);
holder.tvname=(TextView)convertView.findViewById(R.id.txtname);
holder.tvphone=(TextView)convertView.findViewById(R.id.txtphone);
convertView.setTag(holder);
}else{
holder=(ViewHolder) convertView.getTag();
}
holder.tvname.setText(list.get(position).get("name").toString());
holder.tvphone.setText(list.get(position).get("phone").toString());
holder.qcbimg.setImageBitmap(Main.getPhoto(context,list.get(position).get("photo")));
return convertView;
}
}
(5)多線程加載聯系人信息:因為加載聯系人信息可能是一個比較耗時的操作,所以用到了AsyncTask
private class LoadAnysTack extends AsyncTask<String,Void,BaseAdapter>{
@Override
protected BaseAdapter doInBackground(String... arg0) {
// TODO Auto-generated method stub
BaseAdapter adapter=new MyAdapter(Main.this,getData());
return adapter;
}
protected void onPostExecute(BaseAdapter ada){
lview.setAdapter(ada);
dialog.dismiss();
}
}
調用AsyncTask
new LoadAnysTack().execute("");
實現定時器有很多種方式,在這裡我簡單的介紹幾種方式 (1)使用Handler + Runnable的方式 代碼如下: Handler handler = new
APK是Android系統的發布的工程包,很多時候我們想在電腦上而非Android手機上面運行它。下面就提供下Android APK文件在電腦上面運行方法。 首先
本文實例講述了Android編程實現圓角邊框的方法。分享給大家供大家參考,具體如下: 設置邊框圓角可以在drawable-mdpi目錄裡定義一個xml: &l
效果: http://www.56.com/u82/v_OTM4MDk5MTk.html第一步: 創建anim文件夾放置動畫xml文件在res文件夾下,