江湖传言,只要学会ApiDemo宝典,就掌握了android开发的致胜之道。于是我信了,如果您也是一名新手,大家可以一起探讨共勉,如果您是大神请指点。
废话不多说我们先来解析第一篇:ApiDemos的主界面
/**
* 设计思想,这是ApiDemos的启动activity,它继承了ListActivity,列出了当前ApiDemos八大类别的名称,当我们点击
* 某一类别后会进入相应的类别,并依次列出了该类目下的各个子类别,如果某一子类别是分类列表项则点击后会继续进入,如果子类别
* 已经是叶子列表项,则点击后会启动该示例。
*
*
*/
public class ApiDemos extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 当我们点击某一类目后,如果这个类目下面还有分类项,则通过再次启动自身的方式加载该类目下所有分类项的名称。并且在启动自身的同时
// 将该类目的路径传递到新启动的activity当中。所以我们需要在这里获取由上一个activity传递过来的路径值。
Intent intent = getIntent();
String path = intent.getStringExtra("com.example.api.path");
// 如果是第一次启动程序,paht==null
if (path == null) {
path = "";
}
/**
* 使用simpleAdapter适配器为ListActivity加载数据 SimpleAdapter(Context context,
* List<? extends Map<String, ?>> data, int resource, String[] from,
* int[] to)
* 其构造方法共有四个参数第一个上下文,第二个是数据集,数据集是一个list集合,这个集合的每一个元素是一个map集合或其子类
* ,第三个参数是我们的
* ListActivity第一个条目的布局id,这里使用的是系统提供的simple_list_item_1由一个TextView构成
* ,其id为text1。第四个参数是要显示
* 的数据列表组,这里只需要显示一列“title”,如果需要显示多列可以继续在数组中追加。第五个参数用来显示数据的组件的id
* ,当然同样可以有多个组件。 这里就是系统定义的那个id为text1的textView。
*/
setListAdapter(new SimpleAdapter(this, getDatas(path),
android.R.layout.simple_list_item_1, new String[] { "title" },
new int[] { android.R.id.text1 }));
// 当listView获得焦点时,当用户输入快速查询的字符时,允许根据用户的输入字符筛选出匹配的列表项
getListView().setTextFilterEnabled(true);
}
protected List<Map<String, Object>> getDatas(String prefix) {
List<Map<String, Object>> datas = new ArrayList<Map<String, Object>>();
// 从AndroidManifest.xml中筛选出所有apiDemo的activity信息
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
//为了与系统定义的类别相区别,这里随便定义了一个类别名称
mainIntent.addCategory("COM_FISHTOSKY_CODE");
PackageManager pm = getPackageManager();
List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
if (list == null) {
return datas;
}
// 定义一个字符串数组,用于存储将路径按“/”切割后的各个部分
String[] prefixPath;
// 存储加上“/”后的路径
String prefixWithSlash = prefix;
// 第一次启动prefix为“”
if (prefix.equals("")) {
prefixPath = new String[]{};
} else {
prefixPath = prefix.split("/");
prefixWithSlash = prefix + "/";
}
int len = list.size();
// 设置一个控制位,确保相同的类别只添加一次
Map<String, Boolean> entries = new HashMap<String, Boolean>();
for (int i = 0; i < len; i++) {
ResolveInfo info = list.get(i);
CharSequence labelSeq = info.loadLabel(pm);
// 获取activity的label对应的字符串,以hellowrold这个demo为例查看其label的值为:App/Activity/<b>Hello
// <i>World</i></b>
// <b>和<i>表示为字符设置属性<b>表示字符<i>表示字符为斜体
String label = labelSeq != null ? labelSeq.toString()
: info.activityInfo.name;
// 判断如果是第一次启动或者点击类目启动新的activity都可以满足条件
if (prefixPath.length == 0 || label.startsWith(prefixWithSlash)) {
String[] labelPath = label.split("/");
String nextLabel = prefixPath.length == 0 ? labelPath[0]
: labelPath[prefixPath.length];
// 将下一级目录中的内容展示出来
if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
addItem(datas,nextLabel,activityIntent(
info.activityInfo.applicationInfo.packageName,info.activityInfo.name));
} else {
// 判断是否忆经存在该类目
if (entries.get(nextLabel) == null) {
addItem(datas, nextLabel,
browseIntent(prefix.equals("") ? nextLabel
: prefix + "/" + nextLabel));
entries.put(nextLabel, true);
}
}
}
}
// 对集合进行排序
Collections.sort(datas, sDisplayNameComparator);
return datas;
}
// 定义一个排序器
private static final Comparator<Map<String, Object>> sDisplayNameComparator = new Comparator<Map<String, Object>>() {
//拿到一个比较器实例
private final Collator collator=Collator.getInstance();
@Override
public int compare(Map<String, Object> map1, Map<String, Object> map2) {
return collator.compare(map1.get("title"),map2.get("title"));
}
};
/**
* 分类项列表
*
* @param string
* 路径名
* @return
*/
private Intent browseIntent(String path) {
Intent result = new Intent(this, ApiDemos.class);
result.putExtra("com.example.api.path", path);
return result;
}
/**
* 叶子项列表
*
* @param packageName
* 包名
* @param activityName
* 类名
* @return
*/
private Intent activityIntent(String packageName, String activityName) {
Intent result = new Intent();
result.setClassName(packageName, activityName);
return result;
}
/**
* 向数据集中添加内容
* @param datas 数据集
* @param name 当前界面要展示的示例的title
* @param intent 点击条目时启动下一个界面的intent
*/
private void addItem(List<Map<String, Object>> datas, String name,
Intent intent) {
Map<String, Object> temp = new HashMap<String, Object>();
temp.put("title", name);
temp.put("intent", intent);
datas.add(temp);
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Map<String, Object> map=(Map<String, Object>) l.getItemAtPosition(position);
Intent intent=(Intent) map.get("intent");
startActivity(intent);
}
}
配置文件中只需改动:
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@android:style/Theme.Black" >
<activity
android:name=".ApiDemos"
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="com.example.apidemos.HelloWord"
android:label="@string/activity_hello_world" >
<intent-filter >
<action android:name="android.intent.action.MAIN"/>
<category android:name="COM_FISHTOSKY_CODE"/>
</intent-filter>
</activity>
</application>
新建helloword的activity,我们不需要编写任何代码,只需在其string.xml下添加
一行App/Activity/Hello World即可