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]);
    }
}

效果

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中的动物世界选项,将会看到如下效果。
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>

效果

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>

效果

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,它的作用很大,具体介绍请关注后续的文章。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容