目录

Android开发之实用FragmentLayout+fragment实现新浪微博的四个主页面

目录

在使用之前如果还没用过fragment的同学可以先了解下fragment的相关知识

1、Fragment:

Fragment可以做为Activity的一个界面的一个组成部分,Activity的界面可以完全由不同的Fragment组成,注意的是Fragment拥有自己的生命周期和接收、处理用户的事件,这样就不必在Activity写一堆控件的事件处理的代码了。更为重要的是,你可以动态的添加、替换和移除某个Fragment。当然,你可以把fragment当成普通的控件一样放在activity的xml布局文件中。

Fragment必须是依存与Activity而存在的,因此Activity的生命周期会直接影响到Fragment的生命周期。官网这张图很好的说明了两者生命周期的关系:

http://img.blog.csdn.net/20140719225005356?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbG1qNjIzNTY1Nzkx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast

可以看到Fragment比Activity多了几个额外的生命周期回调方法: onAttach(Activity) 当Fragment与Activity发生关联时调用。 onCreateView(LayoutInflater, ViewGroup,Bundle) 创建该Fragment的视图 onActivityCreated(Bundle) 当Activity的onCreate方法返回时调用 onDestoryView() 与onCreateView想对应,当该Fragment的视图被移除时调用 onDetach() 与onAttach相对应,当Fragment与Activity关联被取消时调用

注意:除了onCreateView,其他的所有方法如果你重写了,必须调用父类对于该方法的实现,

参考自:http://blog.csdn.net/lmj623565791/article/details/37970961/

http://www.cnblogs.com/shaweng/p/3918985.html

FragmentManager:你可以把FragmentManager想象成管理一系列的fragment的隐藏展示的一个类

接下来我们就来实现四个页面

最终效果:

webkit-fake-url://c20d3021-c75d-4ef7-bd66-6ed183b9bcaa/image.tiff

第一步:布局MainActivity的布局文件

首先,我们在main_activity.xml中使用fragmentlayout来动态的装载我们要动态切换的四个fragment

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="guanaj.com.weibo.MainActivity">

    <FrameLayout
        android:id="@+id/root_fragment_layout"
        android:layout_width="match_parent"
        android:layout_weight="1"
        android:layout_height="match_parent" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#cccccc" />

    <RadioGroup
        android:id="@+id/radiogroup"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingBottom="10dp"
        android:paddingTop="10dp">

        <RadioButton
            android:id="@+id/radiobutton_home"
            style="@style/main_radiobutton_stype"
            android:checked="true"
            android:drawableTop="@drawable/rb_select_home"
            android:text="主页" />

        <RadioButton
            android:id="@+id/radiobutton_message"
            style="@style/main_radiobutton_stype"
            android:drawableTop="@drawable/rb_select_message"
            android:text="消息" />

        <RadioButton
            android:id="@+id/radiobutton_post"

            style="@style/main_radiobutton_stype"
            android:text="发布" />

        <RadioButton
            android:id="@+id/radiobutton_discover"
            style="@style/main_radiobutton_stype"

            android:drawableTop="@drawable/rb_select_discover"
            android:text="发现" />

        <RadioButton
            android:id="@+id/radiobutton_profile"
            style="@style/main_radiobutton_stype"

            android:drawableTop="@drawable/rb_select_profile"
            android:text="我" />

    </RadioGroup>
</LinearLayout>

可以看到,底部我就先用RadioGroup+RadioButton实现,中间用一个View来实现一个灰色的分割线

底部按钮的样式为了统一管理,我们可以把他公共的样式抽取出来放到res/values/styles.xml文件中

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="main_radiobutton_stype">
        <item name="android:gravity">center</item>
        <item name="android:button">@null</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_weight">1</item>
        <item name="android:layout_height">wrap_content</item>
    </style>

</resources>

底部按钮的选中和不选中状态我们可以是用select选择器来实现,代码分别如下

rb_select_home.xml

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/tabbar_home_selected" android:state_checked="true"/>
    <item android:drawable="@drawable/tabbar_home" android:state_checked="false"/>
</selector>

state_checked=‘true’表示被选中时显示的图片,其余三个类似

好的,布局文件准备好了,接下来我们要来准备四个fragment

第二步:实现四个Fragment

1、HomeFragment.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package guanaj.com.weibo.pager;

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import guanaj.com.weibo.R;

/**
 * Created by guanaj on 2017/2/14.
 */

public class HomeFragment extends Fragment {

    public Activity mActivity;
    public LayoutInflater mInflater;

    @Override
    public void onAttach(Context context) {

        super.onAttach(context);

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //activity创建时回掉,在这里获去依赖的activity对象
        mActivity = getActivity();

    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        mInflater = inflater;//用来将xml文件实例化成View的类实例
        //在HomeFragment的xml文件渲染成view。
        View rootView = mInflater.inflate(R.layout.fragment_home,null);
        //返回的View即为fragment要显示的View
        return rootView;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //fragment依赖的activity创建完成时回掉,一般在这里做fragment页面数据的初始化
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onDetach() {

        super.onDetach();
    }

}

2、HomeFragment的布局文件为

R.layout.fragment_home

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    /**
    * Created by guanaj on .
    */
    <TextView
        android:text="主页"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

2、MessageFragment.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package guanaj.com.weibo.pager;

import android.app.Activity;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import guanaj.com.weibo.R;

/**
 * Created by guanaj on 2017/2/14.
 */

public class MessageFragment extends Fragment {

    public Activity mActivity;
    public LayoutInflater mInflater;

    @Override
    public void onAttach(Context context) {

        super.onAttach(context);

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //activity创建时回掉,在这里获去依赖的activity对象
        mActivity = getActivity();

    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        mInflater = inflater;//用来将xml文件实例化成View的类实例
        //在HomeFragment的xml文件渲染成view。
        View rootView = mInflater.inflate(R.layout.fragment_message,null);

        //返回的View即为fragment要显示的View
        return rootView;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //fragment依赖的activity创建完成时回掉,一般在这里做fragment页面数据的初始化
    }

    @Override
    public void onStart() {
        super.onStart();
    }

    @Override
    public void onResume() {
        super.onResume();
    }

    @Override
    public void onPause() {
        super.onPause();
    }

    @Override
    public void onStop() {
        super.onStop();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void onDetach() {

        super.onDetach();
    }

}

2、MessageFragment的布局文件

R.layout.fragment_message

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    /**
    * Created by guanaj on .
    */
    <TextView
        android:text="消息"
        android:layout_gravity="center"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

其余两个类似

第三步:在MainActivity中动态的根据底部按钮的选中状态切换要显示的fragment

MainActivity.java的代码为:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package guanaj.com.weibo;

import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.FrameLayout;
import android.widget.RadioGroup;
import java.util.ArrayList;
import guanaj.com.weibo.pager.DiscoverFragment;
import guanaj.com.weibo.pager.HomeFragment;
import guanaj.com.weibo.pager.MessageFragment;
import guanaj.com.weibo.pager.ProfileFragment;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    private ArrayList<Fragment> fragmentList = new ArrayList<>();

    private RadioGroup radioGroup;
    private FragmentManager fragmentManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
        initEvent();
        initData();

    }
    private void initViews() {
        //1、获取main_activity中的控件的实例化对象
        radioGroup = (RadioGroup) findViewById(R.id.radiogroup);
        //2、获取FragmentManager
        /*注意倒入的fragmentManager,如果你的fragment是android.support.v4.app包中的,
        你倒入的fragmentManager也要试v4v 包的,
        我这里的fragment是import android.app.Fragment; 所以我导入的fragmentManager也是android.app包下面的
        * */
        /*如果是v4包的要用this.getSupportFragmentManager();*/
        fragmentManager = this.getFragmentManager();

    }

    private void initEvent() {
        radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId) {
                    case R.id.radiobutton_home: {
                        setCurrentFragment(0);
                        break;
                    }
                    case R.id.radiobutton_message: {
                        setCurrentFragment(1);
                        break;
                    }
                    case R.id.radiobutton_discover: {
                        setCurrentFragment(2);
                        break;
                    }
                    case R.id.radiobutton_profile: {
                        setCurrentFragment(3);
                        break;
                    }
                    case R.id.radiobutton_post:{

                        break;
                    }
                    default: {

                    }

                }
//
            }
        });

    }

    private void initData() {
        /*3、数据的准备*/
        HomeFragment homeFragment = new HomeFragment();
        fragmentList.add(homeFragment);
        MessageFragment messageFragment = new MessageFragment();
        fragmentList.add(messageFragment);
        DiscoverFragment discoverFragment = new DiscoverFragment();
        fragmentList.add(discoverFragment);
        ProfileFragment profileFragment = new ProfileFragment();
        fragmentList.add(profileFragment);
        //默认显示第1个也就是fragmentList.get(0)
        setCurrentFragment(0);

    }

    /**
     * 显示fragment
     * @param index
     */
    private void setCurrentFragment(int index){
        //3 通过fragmentmanager获取fragment的事务管理对象
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        //4获取要显示的fragment
        Fragment fragment = fragmentList.get(index);
        //5、将要显示的fragment放入FragmentLayout中
        fragmentTransaction.replace(R.id.root_fragment_layout, fragment);
        //6、提交事务,确定显示
        fragmentTransaction.commit();
    }

}