33、程序管理器--界面设计

实现效果如图:

33、程序管理器--界面设计_第1张图片

一个标题,一个分割条,两个文本一个用来显示可用内存一个显示sd卡的可用内存,一个列表显示安装的程序。

因此布局文件:

<?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">
    <TextView style="@style/title_center_text"
        android:text="程序管理器" />
    <View style="@style/splitter_view"/>

    <LinearLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent">
        <TextView style="@style/content_text"
            android:id="@+id/tv_mem_avail"
            android:layout_weight="1"
            android:text="内存可用:"/>
        <TextView style="@style/content_text"
            android:id="@+id/tv_sdcard_avail"
            android:layout_weight="1"
            android:text="SD卡可用:"/>
    </LinearLayout>

    <RelativeLayout
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:layout_alignParentBottom="true">
        <LinearLayout
            android:id="@+id/ll_appmanager_loading"
            android:orientation="vertical"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:layout_centerHorizontal="true"
            android:gravity="center">
            <ProgressBar
                android:layout_centerHorizontal="true"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content" />
            <TextView
                android:text="正在加载中……"
                android:gravity="center"
                android:layout_height="wrap_content"
                android:layout_width="match_parent" />
        </LinearLayout>
        <ListView
            android:id="@+id/lv_apps"
            android:layout_height="match_parent"
            android:layout_width="match_parent">
        </ListView>
    </RelativeLayout>
</LinearLayout>
这个设计方案和之前的差不多,也就是在listview上还有一个progressbar用来显示“加载中”,因为获取安装的app需要一定的时间。

AppManagerActivity的代码:

package com.example.mobilesafe;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.StatFs;
import android.text.format.Formatter;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.example.mobilesafe.engine.AppInfo;
import com.example.mobilesafe.engine.AppInfoProvider;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by sing on 14-1-21.
 * desc:程序管理器
 */
public class AppManagerActivity extends Activity {

    public static final String TAG = "AppManagerActivity";
    public static final int LOAD_FINISHED = 1;

    private TextView tv_mem_avail;
    private TextView tv_sdcard_avail;
    private View ll_appmanager_loading;
    private ListView lv_apps;

    private List<AppInfo> appInfos;
    private List<AppInfo> userappInfos;
    private List<AppInfo> systemappInfos;

    private BaseAdapter adapter = new AppManagerAdapter();

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == LOAD_FINISHED) {
                ll_appmanager_loading.setVisibility(View.INVISIBLE);
                lv_apps.setAdapter(adapter);
            }
        }
    };

    private class AppManagerAdapter extends BaseAdapter {
        @Override
        public int getCount() {
            //每个分组多一个标题头
            return userappInfos.size() + 1 + systemappInfos.size() + 1;
        }

        @Override
        public Object getItem(int i) {
            if (i == 0) {
                return i;
            }else if (i <= userappInfos.size()) {
                return userappInfos.get(i - 1);
            } else if (i == userappInfos.size() + 1) {
                return i;
            } else {
                return systemappInfos.get(i - userappInfos.size() - 2);
            }
        }

        @Override
        public long getItemId(int i) {
            return i;
        }

        @Override
        public View getView(int i, View view, ViewGroup viewGroup) {
            View v;
            ViewHolder holder;

            if (i == 0) {
                TextView tv = new TextView(getApplicationContext());
                tv.setTextSize(20);
                tv.setText("用户程序(" + userappInfos.size() + ")");
                return tv;
            }else if (i <= userappInfos.size()) {
                if (view==null || view instanceof TextView) {
                    v = View.inflate(getApplicationContext(), R.layout.app_manager_item, null);
                    holder = new ViewHolder();
                    holder.iv_icon = (ImageView) v.findViewById(R.id.iv_appmanager_icon);
                    holder.tv_name = (TextView) v.findViewById(R.id.tv_appmanager_name);
                    holder.tv_version = (TextView) v.findViewById(R.id.tv_appmanager_version);
                    v.setTag(holder);
                }else{
                    v = view;
                    holder = (ViewHolder) view.getTag();
                }

                AppInfo appInfo = userappInfos.get(i - 1);
                holder.iv_icon.setImageDrawable(appInfo.getAppicon());
                holder.tv_name.setText(appInfo.getAppname());
                holder.tv_version.setText("版本号:" + appInfo.getVersion());
                return v;
            } else if (i == userappInfos.size() + 1) {
                TextView tv = new TextView(getApplicationContext());
                tv.setTextSize(20);
                tv.setText("系统程序(" + systemappInfos.size() + ")");
                return tv;
            } else {
                if (view==null || view instanceof TextView) {
                    v = View.inflate(getApplicationContext(), R.layout.app_manager_item, null);
                    holder = new ViewHolder();
                    holder.iv_icon = (ImageView) v.findViewById(R.id.iv_appmanager_icon);
                    holder.tv_name = (TextView) v.findViewById(R.id.tv_appmanager_name);
                    holder.tv_version = (TextView) v.findViewById(R.id.tv_appmanager_version);
                    v.setTag(holder);
                }else{
                    v = view;
                    holder = (ViewHolder) view.getTag();
                }

                AppInfo appInfo = systemappInfos.get(i - userappInfos.size() - 2);
                holder.iv_icon.setImageDrawable(appInfo.getAppicon());
                holder.tv_name.setText(appInfo.getAppname());
                holder.tv_version.setText("版本号:" + appInfo.getVersion());
                return v;
            }
        }

        private class ViewHolder {
            ImageView iv_icon;
            TextView tv_name;
            TextView tv_version;
        }
    }

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.appmanager_layout);

        tv_mem_avail = (TextView) findViewById(R.id.tv_mem_avail);
        tv_sdcard_avail = (TextView) findViewById(R.id.tv_sdcard_avail);
        ll_appmanager_loading = findViewById(R.id.ll_appmanager_loading);
        lv_apps = (ListView) findViewById(R.id.lv_apps);

        tv_mem_avail.setText("内存可用" + getAvailROMSize());
        tv_sdcard_avail.setText("SD卡可用" + getAvailSDSize());

        ll_appmanager_loading.setVisibility(View.VISIBLE);
        new Thread(){
            @Override
            public void run() {
                AppInfoProvider provider = new AppInfoProvider(AppManagerActivity.this);
                appInfos = provider.getInstalledApps();
                initAppInfo();
                Message msg = Message.obtain();
                msg.what = LOAD_FINISHED;
                handler.sendMessage(msg);
            }
        }.start();
    }

    /**
     * 获取手机可用内存
     * @return
     */
    private String getAvailROMSize() {
        File path = Environment.getDataDirectory();
        StatFs statFs = new StatFs(path.getPath());
        long blockSize = statFs.getBlockSize();
        long availableBlocks = statFs.getAvailableBlocks();
        return Formatter.formatFileSize(this, availableBlocks * blockSize);
    }

    /**
     * 获取SD卡可用内存
     * @return
     */
    private String getAvailSDSize() {
        File path = Environment.getExternalStorageDirectory();
        StatFs statFs = new StatFs(path.getPath());
        long blockSize = statFs.getBlockSize();
        long availableBlocks = statFs.getAvailableBlocks();
        return Formatter.formatFileSize(this, availableBlocks * blockSize);
    }

    /**
     * 区分出用户程序和系统程序
     */
    private void initAppInfo() {
        userappInfos = new ArrayList<AppInfo>();
        systemappInfos = new ArrayList<AppInfo>();

        for (AppInfo appinfo : appInfos) {
            if (appinfo.isUserpp()) {
                userappInfos.add(appinfo);
            }else {
                systemappInfos.add(appinfo);
            }
        }
    }
}
其实可以使用ExpandableListView来显示分组用户程序和系统程序,但是之前有使用过,这里使用listview来显示分组,需要在第一个和用户程序之后显示一个分组的标题,是用textview来实现的,因此BaseAdapter的getView需要特别处理。

每一个item的布局文件:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/iv_appmanager_icon"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:layout_weight="0"
        android:layout_gravity="left"/>
    <RelativeLayout
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView style="@style/content_text"
            android:id="@+id/tv_appmanager_name"
            android:layout_alignParentTop="true"
            android:singleLine="true"
            android:ellipsize="end"
            android:textSize="20sp"/>
        <TextView style="@style/content_text"
            android:id="@+id/tv_appmanager_version"
            android:layout_alignParentBottom="true"
            android:textSize="12sp"/>
    </RelativeLayout>
</LinearLayout>
要求程序的图标文件是靠左的,右侧的应用程序名是靠顶显示,版本号靠底部显示。

因此把name和version放到一个RelativeLayout,让ImageView与RelativeLayout的layout_weight为0:1,也就是RelativeLayout占满父容器的剩余空间。

然后再在RelativeLayout里分配name和version的布局。

实际运行后发现有的程序的图标格外大:

解决方案是让imageview的高和宽设置为一个固定大小:

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <ImageView
        android:id="@+id/iv_appmanager_icon"
        android:layout_height="60dip"
        android:layout_width="60dip"
        android:layout_weight="0"
        android:layout_gravity="left"/>
    <RelativeLayout
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView style="@style/content_text"
            android:id="@+id/tv_appmanager_name"
            android:layout_alignParentTop="true"
            android:singleLine="true"
            android:ellipsize="end"
            android:textSize="30sp"/>
        <TextView style="@style/content_text"
            android:id="@+id/tv_appmanager_version"
            android:layout_alignParentBottom="true"
            android:textSize="12sp"/>
    </RelativeLayout>
</LinearLayout>
再编译运行后的效果图:

33、程序管理器--界面设计_第2张图片

你可能感兴趣的:(33、程序管理器--界面设计)