Android中利用FragmentActivity制作首页框架

和之前的两种制作首页框架的方式不同,之前不论是TabActivity还是ActivityGroup,内容页都是使用Activity进行承载的,但FragmentActivity是利用Activity和Fragment结合搭建的首页框架,内容部分使用的Fragment进行承载。本文就FragmentActivity的使用进行一下说明。

1.首先是MainActivity的内容

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "TabFragmentActivity";
    private FragmentTabHost tabHost; // 声明一个碎片标签栏对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Bundle bundle = new Bundle(); // 创建一个包裹对象
        bundle.putString("tag", TAG); // 往包裹中存入名叫tag的标记
        // 从布局文件中获取名叫tabhost的碎片标签栏
        tabHost = findViewById(android.R.id.tabhost);
        // 把实际的内容框架安装到碎片标签栏
        tabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
        // 往标签栏添加第一个标签,其中内容视图展示TabFirstFragment
        tabHost.addTab(getTabView(R.string.menu_first, R.drawable.tab_first_selector),
                TabFirstFragment.class, bundle);
        // 往标签栏添加第二个标签,其中内容视图展示TabSecondFragment
        tabHost.addTab(getTabView(R.string.menu_second, R.drawable.tab_second_selector),
                TabSecondFragment.class, bundle);
        // 往标签栏添加第三个标签,其中内容视图展示TabThirdFragment
        tabHost.addTab(getTabView(R.string.menu_third, R.drawable.tab_third_selector),
                TabThirdFragment.class, bundle);
        // 不显示各标签之间的分隔线
        tabHost.getTabWidget().setShowDividers(LinearLayout.SHOW_DIVIDER_NONE);
    }

    // 根据字符串和图标的资源编号,获得对应的标签规格
    private TabHost.TabSpec getTabView(int textId, int imgId) {
        // 根据资源编号获得字符串对象
        String text = getResources().getString(textId);
        // 根据资源编号获得图形对象
        Drawable drawable = getResources().getDrawable(imgId);
        // 设置图形的四周边界。这里必须设置图片大小,否则无法显示图标
        drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());
        // 根据布局文件item_tabbar.xml生成标签按钮对象
        View item_tabbar = getLayoutInflater().inflate(R.layout.item_tabbar, null);
        TextView tv_item = item_tabbar.findViewById(R.id.tv_item_tabbar);
        tv_item.setText(text);
        // 在文字上方显示标签的图标
        tv_item.setCompoundDrawables(null, drawable, null, null);
        // 生成并返回该标签按钮对应的标签规格
        return tabHost.newTabSpec(text).setIndicator(item_tabbar);
    }
}

2.接着是布局文件activity_main的内容

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- 这是实际的内容框架,内容页面都挂在这个框架布局下面。
        把FragmentLayout放在FragmentTabHost上面,标签栏就在页面底部;
        反之FragmentLayout在FragmentTabHost下面,标签栏就在页面顶部。 -->
    <FrameLayout
        android:id="@+id/realtabcontent"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    <!-- 碎片标签栏的id必须是@android:id/tabhost -->
    <androidx.fragment.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="50dp">

        <!-- 这是例行公事的选项内容,实际看不到 -->
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0" />
    </androidx.fragment.app.FragmentTabHost>
</LinearLayout>

3.在strings.xml中添加三个标签的文字信息

<string name="menu_first">首页</string>
<string name="menu_second">分类</string>
<string name="menu_third">购物车</string>

4.接着我们引入三个标签的状态列表文件

首先我们导入三个按钮的六张图片(三个普通状态,三个选中状态),接着编写如下代码

tab_first_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@mipmap/tab_first_pressed" />
    <item android:drawable="@mipmap/tab_first_normal" />
</selector>
tab_second_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@mipmap/tab_second_pressed" />
    <item android:drawable="@mipmap/tab_second_normal" />
</selector>
tab_third_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@mipmap/tab_third_pressed" />
    <item android:drawable="@mipmap/tab_third_normal" />
</selector>

这三个文件就是三个按钮的状态列表

5.此时我们开始创建三个Fragment,这三个Fragment就是之后内容的承载者。

TabFirstFragment.java
public class TabFirstFragment extends Fragment {
    private static final String TAG = "TabFirstFragment";
    protected View mView; // 声明一个视图对象
    protected Context mContext; // 声明一个上下文对象

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mContext = getActivity(); // 获取活动页面的上下文
        // 根据布局文件fragment_tab_first.xml生成视图对象
        mView = inflater.inflate(R.layout.fragment_tab_first, container, false);
        // 根据碎片标签栏传来的参数拼接文本字符串
        String desc = String.format("我是%s页面,来自%s",
                "首页", getArguments().getString("tag"));
        TextView tv_first = mView.findViewById(R.id.tv_first);
        tv_first.setText(desc);

        return mView;
    }

}
TabSecondFragment.java
public class TabSecondFragment extends Fragment {
    private static final String TAG = "TabSecondFragment";
    protected View mView; // 声明一个视图对象
    protected Context mContext; // 声明一个上下文对象

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mContext = getActivity(); // 获取活动页面的上下文
        // 根据布局文件fragment_tab_second.xml生成视图对象
        mView = inflater.inflate(R.layout.fragment_tab_second, container, false);
        // 根据碎片标签栏传来的参数拼接文本字符串
        String desc = String.format("我是%s页面,来自%s",
                "分类", getArguments().getString("tag"));
        TextView tv_second = mView.findViewById(R.id.tv_second);
        tv_second.setText(desc);

        return mView;
    }

}
TabThirdFragment.java
public class TabThirdFragment extends Fragment {
    private static final String TAG = "TabThirdFragment";
    protected View mView; // 声明一个视图对象
    protected Context mContext; // 声明一个上下文对象

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mContext = getActivity(); // 获取活动页面的上下文
        // 根据布局文件fragment_tab_third.xml生成视图对象
        mView = inflater.inflate(R.layout.fragment_tab_third, container, false);
        // 根据碎片标签栏传来的参数拼接文本字符串
        String desc = String.format("我是%s页面,来自%s",
                "购物车", getArguments().getString("tag"));
        TextView tv_third = mView.findViewById(R.id.tv_third);
        tv_third.setText(desc);

        return mView;
    }

}

6.接着我们引入三个Fragment的布局文件

fragment_tab_first.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical"
    android:padding="10dp">

    <TextView
        android:id="@+id/tv_first"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="bottom|center"
        android:textColor="#000000"
        android:textSize="17sp" />

</LinearLayout>
fragment_tab_second.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical"
    android:padding="10dp">

    <TextView
        android:id="@+id/tv_second"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="bottom|center"
        android:textColor="#000000"
        android:textSize="17sp" />

</LinearLayout>
fragment_tab_third.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:orientation="vertical"
    android:padding="10dp">

    <TextView
        android:id="@+id/tv_third"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="bottom|center"
        android:textColor="#000000"
        android:textSize="17sp" />

</LinearLayout>

此时Fragment引入完成

7.我们还缺少一个标签栏的布局,即下方按钮的布局,我们添加上

item_tabbar.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv_item_tabbar"
        style="@style/TabButton" />

</LinearLayout>

8.itme_tabbar.xml中需要一个样式,我们在styles.xml中添加如下代码

<style name="TabButton">
    <item name="android:layout_width">match_parent</item>
    <item name="android:layout_height">match_parent</item>
    <item name="android:padding">5dp</item>
    <item name="android:layout_gravity">center</item>
    <item name="android:gravity">center</item>
    <item name="android:background">@drawable/tab_bg_selector</item>
    <item name="android:textSize">12sp</item>
    <item name="android:textStyle">normal</item>
    <item name="android:textColor">@drawable/tab_text_selector</item>
</style>

9.TabButton样式中的tab_text_selector.xml和tab_bg_selector.xml资源我们添加一下

tab_text_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:color="#0084e8" />
    <item android:color="#7597b3" />
</selector>

tab_bg_selector.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@mipmap/tab_bg_selected" />
    <item android:drawable="@mipmap/tab_bg_normal" />
</selector>

这里用到两张背景图片,我们添加一下

到这里我们就完成了首页的搭建工作。

我们的重点自然是第一步和第二步中的内容。大致说明一下我们这个结构的主体步骤。

  1. 首先我们要有一个布局,这个布局一块是一个FrameLayout,我们可以随意定义id;其次是一个FragmentTabHost,这个控件需要完全按照我们第2步中的布局编写。
  2. 接着就是Activity中的代码,我们通过如下代码获取到FragmentTabHost对象

    FragmentTabHost tabHost = findViewById(android.R.id.tabhost);
     
  3.  接着是getTabView方法的编写,第一个参数按钮文字的id,第二个参数是按钮的图片,然后通过方法中代码组装成一个TabSpec对象。这个方法的核心其实是
    tabHost.newTabSpec(text).setIndicator(item_tabbar) 
    text是对应按钮的文字内容,item_tabbar就是我们引入按钮布局生成的View。而我们传入getTabView的参数都是为了生成这个View。

  4. 接着是调用tabHost.addTab方法,该方法第一个参数是上一步生成的TabSpec对象,第二个参数是Fragment的class对象,第三个参数是传入Fragment的Buddle

  5. 最后调用tabHost.getTabWidget().setShowDividers(LinearLayout.SHOW_DIVIDER_NONE);是为了不显示分割线。

猜你喜欢

转载自blog.csdn.net/weixin_38322371/article/details/114080648