zoukankan      html  css  js  c++  java
  • android ApiDemos学习1 主界面动态ListView显示

    0 Android提供了一个供开发者学习使用的示例程序。其界面如下。图中可以看到,应用列表应为ListView,看其源码发现,并非为简单的ListView,而是采用动态加载的方式。

                

    1 主界面代码如下:

    ApiDemos
      1 /*
    2 * Copyright (C) 2007 The Android Open Source Project
    3 *
    4 * Licensed under the Apache License, Version 2.0 (the "License");
    5 * you may not use this file except in compliance with the License.
    6 * You may obtain a copy of the License at
    7 *
    8 * http://www.apache.org/licenses/LICENSE-2.0
    9 *
    10 * Unless required by applicable law or agreed to in writing, software
    11 * distributed under the License is distributed on an "AS IS" BASIS,
    12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13 * See the License for the specific language governing permissions and
    14 * limitations under the License.
    15 */
    16
    17 package com.example.android.apis;
    18
    19 import android.app.ListActivity;
    20 import android.content.Intent;
    21 import android.content.pm.PackageManager;
    22 import android.content.pm.ResolveInfo;
    23 import android.os.Bundle;
    24 import android.view.View;
    25 import android.widget.ListView;
    26 import android.widget.SimpleAdapter;
    27
    28 import java.text.Collator;
    29 import java.util.ArrayList;
    30 import java.util.Collections;
    31 import java.util.Comparator;
    32 import java.util.HashMap;
    33 import java.util.List;
    34 import java.util.Map;
    35
    36 public class ApiDemos extends ListActivity {
    37
    38 @Override
    39 public void onCreate(Bundle savedInstanceState) {
    40 super.onCreate(savedInstanceState);
    41
    42 Intent intent = getIntent();
    43 String path = intent.getStringExtra("com.example.android.apis.Path");
    44
    45 if (path == null) {
    46 path = "";
    47 }
    48
    49 setListAdapter(new SimpleAdapter(this, getData(path),
    50 android.R.layout.simple_list_item_1, new String[] { "title" },
    51 new int[] { android.R.id.text1 }));
    52 getListView().setTextFilterEnabled(true);
    53 }
    54
    55 protected List getData(String prefix) {
    56 List<Map> myData = new ArrayList<Map>();
    57
    58 Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
    59 mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);
    60
    61 PackageManager pm = getPackageManager();
    62 List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);
    63
    64 if (null == list)
    65 return myData;
    66
    67 String[] prefixPath;
    68
    69 if (prefix.equals("")) {
    70 prefixPath = null;
    71 } else {
    72 prefixPath = prefix.split("/");
    73 }
    74
    75 int len = list.size();
    76
    77 Map<String, Boolean> entries = new HashMap<String, Boolean>();
    78
    79 for (int i = 0; i < len; i++) {
    80 ResolveInfo info = list.get(i);
    81 CharSequence labelSeq = info.loadLabel(pm);
    82 String label = labelSeq != null
    83 ? labelSeq.toString()
    84 : info.activityInfo.name;
    85
    86 if (prefix.length() == 0 || label.startsWith(prefix)) {
    87
    88 String[] labelPath = label.split("/");
    89
    90 String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];
    91
    92 if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
    93 addItem(myData, nextLabel, activityIntent(
    94 info.activityInfo.applicationInfo.packageName,
    95 info.activityInfo.name));
    96 } else {
    97 if (entries.get(nextLabel) == null) {
    98 addItem(myData, nextLabel, browseIntent(prefix.equals("") ? nextLabel : prefix + "/" + nextLabel));
    99 entries.put(nextLabel, true);
    100 }
    101 }
    102 }
    103 }
    104
    105 Collections.sort(myData, sDisplayNameComparator);
    106
    107 return myData;
    108 }
    109
    110 private final static Comparator<Map> sDisplayNameComparator = new Comparator<Map>() {
    111 private final Collator collator = Collator.getInstance();
    112
    113 public int compare(Map map1, Map map2) {
    114 return collator.compare(map1.get("title"), map2.get("title"));
    115 }
    116 };
    117
    118 protected Intent activityIntent(String pkg, String componentName) {
    119 Intent result = new Intent();
    120 result.setClassName(pkg, componentName);
    121 return result;
    122 }
    123
    124 protected Intent browseIntent(String path) {
    125 Intent result = new Intent();
    126 result.setClass(this, ApiDemos.class);
    127 result.putExtra("com.example.android.apis.Path", path);
    128 return result;
    129 }
    130
    131 protected void addItem(List<Map> data, String name, Intent intent) {
    132 Map<String, Object> temp = new HashMap<String, Object>();
    133 temp.put("title", name);
    134 temp.put("intent", intent);
    135 data.add(temp);
    136 }
    137
    138 @Override
    139 protected void onListItemClick(ListView l, View v, int position, long id) {
    140 Map map = (Map) l.getItemAtPosition(position);
    141
    142 Intent intent = (Intent) map.get("intent");
    143 startActivity(intent);
    144 }
    145
    146 }

     下面为部分配置文件代码:

    Manifest.xml
    <?xml version="1.0" encoding="utf-8"?>
    <!-- Copyright (C) 2007 The Android Open Source Project

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
    -->

    <!-- Declare the contents of this Android application. The namespace
    attribute brings in the Android platform namespace, and the package
    supplies a unique name for the application. When writing your
    own application, the package name must be changed from "com.example.*"
    to come from a domain that you own or have control over. -->
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.apis">

    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.SET_WALLPAPER" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.SEND_SMS" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <uses-permission android:name="android.permission.NFC" />

    <!-- For android.media.audiofx.Visualizer -->
    <uses-permission android:name="android.permission.RECORD_AUDIO" />

    <!-- We will request access to the camera, saying we require a camera
    of some sort but not one with autofocus capability. -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-feature android:name="android.hardware.camera" />
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />

    <application android:name="ApiDemosApplication"
    android:label="@string/activity_sample_code"
    android:icon="@drawable/app_sample_code" >

    <!-- This is how we can request a library but still allow the app
    to be installed if it doesn't exist. -->
    <uses-library android:name="com.example.will.never.exist" android:required="false" />

    <activity android:name="ApiDemos">
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    </activity>

    <!-- ************************************* -->
    <!-- APPLICATION PACKAGE SAMPLES -->
    <!-- ************************************* -->

    <!-- Activity Samples -->

    <activity android:name=".app.HelloWorld" android:label="@string/activity_hello_world">
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.SAMPLE_CODE" />
    </intent-filter>
    </activity>

    <activity android:name=".app.DialogActivity"
    android:label="@string/activity_dialog"
    android:theme="@android:style/Theme.Dialog">
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.SAMPLE_CODE" />
    </intent-filter>
    </activity>

    <activity android:name=".app.CustomDialogActivity"
    android:label="@string/activity_custom_dialog"
    android:theme="@style/Theme.CustomDialog">
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.SAMPLE_CODE" />
    </intent-filter>
    </activity>

    <activity android:name=".app.QuickContactsDemo"
    android:label="@string/quick_contacts_demo">
    <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.SAMPLE_CODE" />
    </intent-filter>
    </activity>

    </application>

    <instrumentation android:name=".app.LocalSampleInstrumentation"
    android:targetPackage="com.example.android.apis"
    android:label="Local Sample" />

    </manifest>



    2 分析

      其想法主要分为以下几步:

      1) 给想要显示在列表中的Activity分类

      2) 然后从xml中根据分类标签搜索出来

      3) 将结果加载到List<Map>中

      4) 据此list生成ListView并显示

      1) 想达到分类的效果,我们可以在Manifest.xml中对Activity做如下配置,稍后可根据category值进行过滤搜索。在自己的应用中,我们可以自定义category值。

            <activity android:name=".app.HelloWorld" android:label="@string/activity_hello_world">
    <intent-filter>
    <action android:name="android.intent.action.MAIN"/>
    <category android:name="android.intent.category.SAMPLE_CODE"/>
    </intent-filter>
    </activity>


      2) 根据category值查询出想显示的activity对应的ResolveInfo值列表。ResolveInfo对象包含Manifest.xml中对应Activity节点的所有信息,稍后可以根据这些信息对其进行加载。 

            Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
    mainIntent.addCategory(Intent.CATEGORY_SAMPLE_CODE);

    PackageManager pm = getPackageManager();
    List<ResolveInfo> list = pm.queryIntentActivities(mainIntent, 0);

      3) 根据查询出的activity的ResolveInfo list,生成List<Map>,其中Map包含title和intent 

            //10 得到父节点级别数组
    String[] prefixPath;

    if (prefix.equals("")) {
    prefixPath = null;
    } else {
    prefixPath = prefix.split("/");
    }

    int len = list.size();

    Map<String, Boolean> entries = new HashMap<String, Boolean>();


    //11 对过滤得到的ResolveInfo列表进行遍历
    for (int i = 0; i < len; i++) {

    //111 得到ResolveInfo对象
    ResolveInfo info = list.get(i);
    CharSequence labelSeq = info.loadLabel(pm);

    //112 根据ResolveInfo对象得到Activity对应的label信息,如App/Activity/Hello World
    String label = labelSeq != null
    ? labelSeq.toString()
    : info.activityInfo.name;

    //113 判断是否有子节点存在
    if (prefix.length() == 0 || label.startsWith(prefix)) {

    //114 得到字节点的层级数组,如{"App","Activity","Hello World"}
    String[] labelPath = label.split("/");

    //115 得到应显示层级的标签,如 App
    String nextLabel = prefixPath == null ? labelPath[0] : labelPath[prefixPath.length];

    //116 当前节点无子节点,且不为第一个级别,将对应Activity信息和标签信息组装成intent,添加至List<Map>
    if ((prefixPath != null ? prefixPath.length : 0) == labelPath.length - 1) {
    addItem(myData, nextLabel, activityIntent(
    info.activityInfo.applicationInfo.packageName,
    info.activityInfo.name));
    } else {//116 当前节点有子节点或为第一级节点
    //117 判断是否在父节点数组中
    if (entries.get(nextLabel) == null) {
    //118 将当前activity和节点路径信息一起组装成intent,添加至List<Map>
    addItem(myData, nextLabel, browseIntent(prefix.equals("") ? nextLabel : prefix + "/" + nextLabel));
    //119 将此节点路径加到父节点数组中
    entries.put(nextLabel, true);
    }
    }
    }
    }

      4) 根据List<Map>生成ListView  

            setListAdapter(new SimpleAdapter(this, getData(path),
    android.R.layout.simple_list_item_1, new String[] { "title" },
    new int[] { android.R.id.text1 }));
    getListView().setTextFilterEnabled(true);
  • 相关阅读:
    【linux系列】配置免密登陆
    【linux系列】centos安装vsftp
    【linux系列】cenos7安装jdk
    MySQL DATE_SUB()
    Java基本数据类型
    Gson使用中遇到的Date格式问题
    数组中存放对象之java中定义类数组存放类
    获取X天后的日期
    sql统计总和和各状态数
    HttpServletRequest获取URL?后面的内容
  • 原文地址:https://www.cnblogs.com/myparamita/p/2230777.html
Copyright © 2011-2022 走看看