最近做功能开发时候需要显示当前手机安装的app信息.这里我使用Dialog来显示.截图如下:
如上截图所示,这个dialog显示了当前手机安装的app,当点击一个菜单项时候就会在上面显示一个上锁的图案(如上图:视频/相机/联系人).这时一个可以对app上锁的设计界面.
首先来看看dialog的创建:
private void Init_create_dialog(){
if(null == show_app_dialog){
show_app_dialog = new Dialog(getActivity()){
protected void onStop() {
super.onStop();
FingerPrint_Utils.FingerPrint_save_LockApp(getActivity());
}
};
show_app_dialog.setContentView(R.layout.finger_gride_app_choose);
show_app_dialog.setTitle(R.string.finger_print_set_unlock_app_title);
GridView gvApp = ((GridView)show_app_dialog.findViewById(R.id.gv_app));
final List<FingerPrintApplicationInfo> list = FingerPrint_Utils.get_LockApplicationInfoList();
gvApp.setAdapter(new AppChooseAdapter(list));
gvApp.setOnItemClickListener(new AdapterView.OnItemClickListener(){
public void onItemClick(AdapterView<?> parent, View view, int position, long id){
FingerPrintApplicationInfo Fingerappinfo = (FingerPrintApplicationInfo)parent.getItemAtPosition(position);
ResolveInfo appinfo = Fingerappinfo.launcher_activity;
//CharSequence name = appinfo.loadLabel(package_manager);
AppChooseAdapter.ViewHolder hold = (AppChooseAdapter.ViewHolder) view.getTag();
if(Fingerappinfo.locked){
hold.app_icon.setImageResource(0);
Fingerappinfo.locked = false;
FingerPrint_Utils.FingerPrint_Dele_LockApp(appinfo.activityInfo.packageName);//activityInfo.packageName
}else{
hold.app_icon.setImageResource(R.drawable.lock_app_icon);
Fingerappinfo.locked = true;
FingerPrint_Utils.FingerPrint_AddNew_LockApp(appinfo.activityInfo.packageName);
}
//selected_str = appinfo.packageName;
//if(DEBUG) Log.d(TAG,"FingerPrintSettingMain: name="+name+"; appinfo.packageName="+appinfo.packageName);
//show_app_dialog.dismiss();
}
});
/*
show_app_dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
public void onDismiss(final DialogInterface dialog) {
FingerPrint_Utils.FingerPrint_save_LockApp(getActivity());
}
});*/
show_app_dialog.getWindow().setCloseOnTouchOutside(true);
show_app_dialog.setCanceledOnTouchOutside(true);
}
}
再看看其layout的文件:finger_gride_app_choose.xml
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gv_app"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"
android:padding="10dp"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:gravity="center"
/>
实际上就是一个GridView,所以整个界面的重点其实就是这个GridView的Adapter设计.所以看看这个Adapter:AppChooseAdapter
class AppChooseAdapter extends BaseAdapter{
private List<FingerPrintApplicationInfo> applicationInfos;
private PackageManager pm;
class ViewHolder {
TextView app_name;
ImageView app_icon;
//ImageView locked_icon;
}
public AppChooseAdapter(List<FingerPrintApplicationInfo> list){
applicationInfos = list;
}
public int getCount(){
return applicationInfos.size();
}
public Object getItem(int position){
return applicationInfos.get(position);
}
public long getItemId(int position){
return position;
}
public View getView(int position, View view, ViewGroup parent){
//PackageManager pm = package_manager;
final ViewHolder hold;
if (view == null){
if(DEBUG) Log.d(TAG,"AppChooseAdapter: (view == null) position="+position);
Context context = parent.getContext();
view = LayoutInflater.from(context).inflate(R.layout.item_app_gride, null);
hold = new ViewHolder();
hold.app_icon = (ImageView)view.findViewById(R.id.iv_icon);
//hold.locked_icon = (ImageView)view.findViewById(R.id.lock_statu_img);
hold.app_name = (TextView)view.findViewById(R.id.tv_name);
view.setTag(hold);
}else{
if(DEBUG) Log.d(TAG,"AppChooseAdapter: (view != null) position="+position);
hold = (ViewHolder) view.getTag();
}
final int curr_position = position;
view.post(new Runnable() {
public void run() {
//ViewHolder hold = (ViewHolder) view.getTag();
PackageManager pm = package_manager;
if(hold != null){
FingerPrintApplicationInfo aInfo = (FingerPrintApplicationInfo)applicationInfos.get(curr_position);
String package_name = aInfo.launcher_activity.activityInfo.packageName;//aInfo.app.packageName;
if(aInfo.locked){
hold.app_icon.setImageResource(R.drawable.lock_app_icon);
}else{
hold.app_icon.setImageResource(0);
}
hold.app_name.setText(aInfo.launcher_activity.loadLabel(pm));
hold.app_icon.setBackgroundDrawable(aInfo.launcher_activity.loadIcon(pm)); //image.setImageDrawable(aInfo.app.loadIcon(pm));
}
}
});
return view;
}
}
上面已经贴出了基本所有代码.下面做一下说明:
(1)每一次显示这个dialog都会一点延时,如何解决这个问题.我有了两个办法来解决:
首先,加载手机安装的app信息,我会在显示这个dialog之前就加载好,然后只需要通过FingerPrint_Utils.get_LockApplicationInfoList()来获取就可以.其中加载app信息使用AsyncTask来完成的.AsyncTask的使用比较简单了,这里我只给出加载app的信息的代码:
private static ArrayList<FingerPrintApplicationInfo> getInstalledLaunchableApps(FingerPrintSettingMain.AppLabelComparator mcomparator){
final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
PackageManager pm = mcomparator.getPackageManager();
List list = pm.queryIntentActivities(mainIntent, 0);//查询获取安装的所有app
ArrayList<FingerPrintApplicationInfo> array = new ArrayList<FingerPrintApplicationInfo>();
ArrayList<FingerPrintApplicationInfo> array1 = new ArrayList<FingerPrintApplicationInfo>();
int size = list.size();
String[] APP_DELE = ALL_APP_DELE_PACKAGENAME;
String[] LOCK_APP_DELE = LOCK_APP_DELE_PACKAGENAME;
//Log.d(TAG,"getInstalledLaunchableApps: size="+size);
boolean has = false;
String locked_packagename = app_locked_PackageName!=null?app_locked_PackageName.toString():null;
ResolveInfo curr;
for (int i=0; i<size; i++){
has = false;
curr = (ResolveInfo)list.get(i);
if(null == curr){
continue;
}
String str = curr.activityInfo.packageName;
if(!wei_xing_install && 0 == weixing_package.compareTo(str)){//检测是否安装微信
wei_xing_install = true;
}
Iterator iterator = array.iterator();
if(null != APP_DELE){
for(int j = 0; j < APP_DELE.length; j++){//有一些app不需要在这里显示,过滤掉一些app
if(APP_DELE[j].compareTo(str) == 0){
has = true;
}
}
}
if(has) continue;
FingerPrintApplicationInfo app = new FingerPrintApplicationInfo();
app.launcher_activity = curr;
if(locked_packagename != null && locked_packagename.indexOf(str)>-1){
app.locked = true;
}
array.add(app);
if(null != LOCK_APP_DELE){
for(int n = 0; n < LOCK_APP_DELE.length; n++){
if(LOCK_APP_DELE[n].compareTo(str) == 0){
has = true;
}
}
}
if(has) continue;
array1.add(app);
}
Collections.sort(array, mcomparator);
Collections.sort(array1, mcomparator);
if(array1 != null){
unlock_pacakegename_app_dele = array1;
}
return array;
}
即使在显示dialog之前就加载好app信息,在显示dialog时候也会有一个较长的延迟,这是因为加载每一个app的icon和text_name也是需要时间的.所以,如上面的代码AppChooseAdapter的getView中我使用了view.post(new Runnable())的方法来加载显示的信息.
(2)如何实现点击一个app菜单选项时候能够在上面显示一个锁的图像.仔细看上面的源码可以发现,这里我使用了ImageView的image和背景来做的.首先ImageView的背景图片用来显示app的icon,而ImageView的image来显示是锁的图片.如果上锁则这个ImageView就设置image:
hold.app_icon.setImageResource(R.drawable.lock_app_icon);
否则:
hold.app_icon.setImageResource(0);