Activity子类详解

前言

往者不可谏,来者犹可追。

建立自己的Activity需要继承Activity基类。当然,在不同的场景下,你也可以继承Activity的子类来简化开发。例如,如果应用程序界面只包括列表,则可以让应用程序继承ListActivity;如果应用程序界面需要实现标签页效果,则可以让应用程序继承TabActivity。下面我来介绍一下几个Activity的子类结合的例子。

LauncherActivity

LauncherActivity继承了ListActivity,因此它本质上也是一个开发列表界面的Activity,但它开发出来的列表界面与普通列表界面有所不同。它开发出来的列表界面中的每个列表项都对应于一个Intent,因此当用户单击不同的列表项时,应用程序会自动启动相应的Activity。
与使用普通ListActivity不同的是,继承LauncherActivity时通常应该重写Intent intentForPosition(int position)方法,该方法根据不同列表项返回不同的Intent(用于启动不同的Activity)。

MainActivity.java

public class MainActivity extends LauncherActivity {

    //定义两个Activity的名称
    String []names = {"设置程序参数","动物世界"};
    //定义两个Activity对应的实现类
    Class<?>[] clazz = {PreferenceActivityTest.class
            ,ExpandableListActivityTest.class};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, names);

        setListAdapter(adapter);
    }

    @Override
    protected Intent intentForPosition(int position) {

        return new Intent(MainActivity.this, clazz[position]);
    }
}

效果

Activity子类详解
Screenshot_20171101-093217.png
下面我们来继续完善这个程序,当你点击不同的列表项,跳转到不同的Activity。

ExpandableListAcitviy

ExpandableListAcitviy的用法与ExpandableListView的用法基本相似,只要为该Activity传入一个ExpandableListAdapter对象即可,接下来ExpandableListAcitviy将会生成一个显示可展开列表的窗口。

ExpandableListAcitviyTest.java

public class ExpandableListActivityTest extends android.app.ExpandableListActivity {

    String[] armTypes = { "企鹅", "熊猫", "老虎" };
    String[][] arms = { { "白企鹅", "黑企鹅", "小企鹅" }, { "大熊猫", "母熊猫", "小熊猫" }, { "打老虎", "母老虎", "小老虎" } };

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        ExpandableListAdapter adapter = new BaseExpandableListAdapter() {

            private TextView getTextView() {
                AbsListView.LayoutParams lp = new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 64);
                TextView textView = new TextView(ExpandableListActivityTest.this);
                textView.setLayoutParams(lp);
                textView.setGravity(Gravity.CENTER_VERTICAL | Gravity.LEFT);
                textView.setPadding(36, 0, 0, 0);
                textView.setTextSize(20);
                return textView;
            }

            @Override
            public boolean isChildSelectable(int groupPosition, int childPosition) {

                return true;
            }

            @Override
            public boolean hasStableIds() {
                return true;
            }

            // 该方法决定每个组选项的外观
            @Override
            public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

                LinearLayout ll = new LinearLayout(ExpandableListActivityTest.this);
                ll.setOrientation(LinearLayout.HORIZONTAL);
                ImageView logo = new ImageView(ExpandableListActivityTest.this);
                logo.setImageResource(R.drawable.ic_launcher);
                ll.addView(logo);
                TextView textView = getTextView();
                textView.setText(getGroup(groupPosition).toString());
                ll.addView(textView);
                return ll;
            }

            @Override
            public long getGroupId(int groupPosition) {
                return groupPosition;
            }

            @Override
            public int getGroupCount() {
                return armTypes.length;
            }

            @Override
            public Object getGroup(int groupPosition) {
                return armTypes[groupPosition];
            }

            @Override
            public int getChildrenCount(int groupPosition) {
                return arms[groupPosition].length;
            }

            // 该方法决定每个子选项的外观
            @Override
            public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView,
                    ViewGroup parent) {
                TextView textView = getTextView();
                textView.setText(getChild(groupPosition, childPosition).toString());
                return textView;
            }

            @Override
            public long getChildId(int groupPosition, int childPosition) {
                return childPosition;
            }

            @Override
            public Object getChild(int groupPosition, int childPosition) {
                return arms[groupPosition][childPosition];
            }
        };

        setListAdapter(adapter);
    }
}

效果

点击MainActivity中的动物世界选项,将会看到如下效果。
Activity子类详解
Screenshot_20171101-093757.png

PreferenceActivity结合PreferenceFragment的使用

PreferenceActivity是一个非常有用的基类,当我们开发一个Android应用程序时,不可避免地需要进行选项设置,这些选项设置会以参数的形式保存,习惯上我们会用Preferences进行保存。
为了创建一个PreferenceActivity,需要先创建一个对应的界面布局。从Android3.0开始,Android不再推荐直接让PreferenceActivity加载选项设置的布局文件,而是建议将PreferenceActivity与PreferenceFragment结合使用,其中PreferenceActivity只负责加载选项设置列表的布局文件,PreferenceFragment才负责加载选项设置的布局文件。

PreferenceActivityTest.java

public class PreferenceActivityTest extends PreferenceActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 该方法用于为该界面设置一个标题按钮
        if (hasHeaders()) {
            Button button = new Button(this);
            button.setText("设置操作");
            // 将该按钮添加到该界面上
            setListFooter(button);
        }

    }

    // 重写该方法,负责加载界面布局文件
    @Override
    public void onBuildHeaders(List<Header> target) {

        // 加载选项设置列表的布局文件
        loadHeadersFromResource(R.layout.preference_header, target);

    }

    // 重写该方法,验证各PreferenceFragment是否有效
    @Override
    protected boolean isValidFragment(String fragmentName) {
        return true;
    }

    public static class Prefs1Fragment extends PreferenceFragment {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.layout.preference);
        }

    }

    public static class Prefs2Fragment extends PreferenceFragment {

        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.layout.display_prefs);
            //获取传入该Fragment的参数
            String website = getArguments().getString("website");
            Toast.makeText(getActivity(), website, Toast.LENGTH_SHORT).show();
        }
    }
}

preference_header.xml

<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >

    <!-- 指定启动PreferenceFragment的列表项 -->

    <header
        android:fragment="com.张敦锋.activitydemo.PreferenceActivityTest$Prefs1Fragment"
        android:icon="@drawable/ic_launcher"
        android:summary="设置应用的相关选项"
        android:title="程序选项设置" />
    <!-- 指定启动preferenceFragment的列表 -->

    <header
        android:fragment="com.张敦锋.activitydemo.PreferenceActivityTest$Prefs2Fragment"
        android:icon="@drawable/ic_launcher"
        android:summary="设置显示界面的相关选项"
        android:title="界面选项设置" >

        <!-- 使用extra可向Activity传入额外数据 -->

        <extra
            android:name="website"
            android:value="www.baidu.com" />
    </header>
    <!-- 使用Intent启动指定Activity的列表项 -->

    <header
        android:icon="@drawable/ic_launcher"
        android:summary="使用Intent启动某个Activity"
        android:title="使用Intent" >
        <intent android:action="android.intent.action.VIEW"
            android:data="http://www.baidu.com"/>
    </header>
</preference-headers>

效果

Activity子类详解
Screenshot_20171101-103919.png

display_prefs.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory android:title="背景灯光组" >
        <!-- 通过列表框选择灯光强度 -->
        <ListPreference
            android:dialogTitle="请选择灯光强度"
            android:entries="@array/light_strength_list"
            android:entryValues="@array/light_value_list"
            android:key="light"
            android:summary="请选择灯光强度"
            android:title="灯光强度" >
        </ListPreference>
    </PreferenceCategory>

    <PreferenceCategory android:title="文字显示组" >
    <!-- 通过SwitchPreference设置是否自动滚屏 -->
    <SwitchPreference
            android:defaultValue="true"
            android:key="autoScroll"
            android:summaryOn="自动滚屏:开启"
            android:summaryOff="自动滚屏:关闭"
            android:title="自动滚屏" />
    </PreferenceCategory>
</PreferenceScreen>

效果

Activity子类详解
Screenshot_20171101-104042.png

preference.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 设置系统铃声 -->
    <RingtonePreference
        android:ringtoneType="all"
        android:title="设置铃声"
        android:summary="选择铃声"
        android:showDefault="true"
        android:key="ring_key"
        android:showSilent="true"
        />
    <!-- 通过输入框填写用户名 -->
    <EditTextPreference
        android:key="name"
        android:title="填写用户名"
        android:summary="填写您的用户名"
        android:dialogTitle="您所使用的用户名为:"/>
    <!-- 通过列表框选择性别 -->
    <ListPreference
        android:key="gender"
        android:title="性别"
        android:summary="选择您的性别"
        android:dialogTitle="ListPreference"
        android:entries="@array/gender_name_list"
        android:entryValues="@array/gender_value_list"/>
    />
    <PreferenceCategory android:title="系统功能设置组">
        <CheckBoxPreference
            android:key="autoSave"
            android:title="自动保存进度"
            android:summaryOn="自动保存:开启"
            android:summaryOff="自动保存:关闭"
            android:defaultValue="true"/>
    </PreferenceCategory>
</PreferenceScreen>
目前为止,该应用程序有三个Activity类,但这三个Activity还不能使用,必须在AndroidManifest.xml清单文件中配置Activity才行。
  <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            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.张敦锋.activitydemo.ExpandableListActivityTest"
            android:label="动物世界" >
        </activity>
        <activity
            android:name="com.张敦锋.activitydemo.PreferenceActivityTest"
            android:label="设置程序参数" >
        </activity>
    </application>
配置Activity时通常指定如下几个属性。
  • name:指定该Activity的实现类的类名。
  • icon:指定该Activity对应的图标。
  • label:指定该Activity的标签。
  • exported:指定该Activity是否允许被其他应用调用。
  • launchMode:指定该Activity的加载模式,该属性支持standard、singleTop、singleTask和singleInstance这4种加载模式。
上面的程序运行并设置相应的程序参数,系统将会在/data/data/zdf.halo/shared_prefs/路径下生成一个xml文件,里面保存了你设置的参数信息。这里直接使用PreferenceActivity,我们完全不用去考虑Preference的读写,它会为我们处理一切。还有另一种方法,SharedPreference,它的作用很大,具体介绍请关注后续的文章。
上一篇:UI组件-实用组件


下一篇:Activity的生命周期