Android Fragment应用实战(音乐播放器界面)

来源:互联网 发布:考试管理系统数据库 编辑:程序博客网 时间:2024/06/04 18:56

当下很多手机应用都会有一个非常类似的功能,即屏幕的下方显示一行Tab标签选项,点击不同的标签就可以切换到不同的界面,如以下几个应用所示:

\\\\

以上底部这四个标签,每一个分别对应一个Fragment,这种底部标签式的布局策略真的非常常见,那么话说回来,这种效果到底是如何的呢?熟悉Android的朋友一定都会知道,很简单嘛,使用TabHost就OK了!但是殊不知,TabHost并非是那么的简单,它的可扩展性非常的差,不能随意地定制Tab项显示的内容,而且运行还要依赖于ActivityGroup。ActivityGroup原本主要是用于为每一个TabHost的子项管理一个单独的Activity,但目前已经被废弃了。为什么呢?当然就是因为Fragment的出现了!

下面就开始真正的编程吧!

打开或者新建一个xml文件作为程序的主布局文件,这里直接采用activity_main.xml作为程序的主布局文件,在里面加入如下代码:

 

?
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
<linearlayout android:layout_height="match_parent"android:layout_width="match_parent"android:orientation="vertical"tools:context=".MainActivity"xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools">
 
    <framelayout android:id="@+id/Content"android:layout_height="0dp"android:layout_weight="1"android:layout_width="match_parent">
 
        <relativelayout android:background="#eee"android:layout_height="match_parent"android:layout_width="match_parent">
 
             
             
        </android.support.v4.view.viewpager></relativelayout>
    </framelayout>
 
    <linearlayout android:background="#ffffff"android:layout_height="60dp"android:layout_width="match_parent">
 
         
        <relativelayout android:id="@+id/discover_layout"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp">
 
             
            <linearlayout android:layout_centervertical="true"android:layout_height="wrap_content"android:layout_width="match_parent"android:orientation="vertical">
 
                <imageview android:id="@+id/discover_image"android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:src="@drawable/ic_launcher">
 
                <textview android:id="@+id/discover_text"android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="发现音乐"android:textcolor="#82858b">
            </textview></imageview></linearlayout>
        </relativelayout>
 
        <relativelayout android:id="@+id/my_layout"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp">
 
            <linearlayout android:layout_centervertical="true"android:layout_height="wrap_content"android:layout_width="match_parent"android:orientation="vertical">
 
                <imageview android:id="@+id/my_image"android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:src="@drawable/ic_launcher">
 
                <textview android:id="@+id/my_text"android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="我的音乐"android:textcolor="#82858b">
            </textview></imageview></linearlayout>
        </relativelayout>
 
        <relativelayout android:id="@+id/friends_layout"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp">
 
            <linearlayout android:layout_centervertical="true"android:layout_height="wrap_content"android:layout_width="match_parent"android:orientation="vertical">
 
                <imageview android:id="@+id/friends_image"android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:src="@drawable/ic_launcher">
 
                <textview android:id="@+id/friends_text"android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="朋友"android:textcolor="#82858b">
            </textview></imageview></linearlayout>
        </relativelayout>
 
        <relativelayout android:id="@+id/account_layout"android:layout_height="match_parent"android:layout_weight="1"android:layout_width="0dp">
 
            <linearlayout android:layout_centervertical="true"android:layout_height="wrap_content"android:layout_width="match_parent"android:orientation="vertical">
 
                <imageview android:id="@+id/account_image"android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:src="@drawable/ic_launcher">
 
                <textview android:id="@+id/account_text"android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="账号"android:textcolor="#82858b">
            </textview></imageview></linearlayout>
        </relativelayout>
    </linearlayout>
 
</linearlayout>

大家看这代码比较难以理解,但其实主要就分为两部分。第一个部分就是FrameLayout,这里只是给FrameLayout的id设置为Content,并没有在里面添加任何具体的内容,因为具体的内容是要在后面动态进行添加的。第二个部分就是FrameLayout下面的LinearLayout,这个LinearLayout中包含的就是整个类似于TabHost的布局。可以看到,我们将这个LinearLayout又等分成了四份,每一份中都会显示一个ImageView和一个TextView。ImageView用于显示当前Tab的图标,TextView用于显示当前Tab的标题,这个效果就会和QQ非常得类似。

 

\

那么接下来我们要开始实现Fragment和它们的布局了,新建一个discover_music_fragment.xml作为第一个“发现音乐”的界面,代码如下所示:

 

?
1
2
3
4
5
6
7
8
9
10
11
<!--?xml version="1.0"encoding="utf-8"?-->
<relativelayout android:layout_height="match_parent"android:layout_width="match_parent"xmlns:android="http://schemas.android.com/apk/res/android">
 
    <linearlayout android:layout_centerinparent="true"android:layout_height="wrap_content"android:layout_width="wrap_content"android:orientation="vertical">
 
        <imageview android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:src="@drawable/ic_launcher">
 
        <textview android:layout_gravity="center_horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:padding="10dp"android:text="这是发现音乐界面"android:textsize="20sp">
    </textview></imageview></linearlayout>
 
</relativelayout>

 

这个布局就是在屏幕的正中央显示一个消息图标以及一段文字。

\

然后,我们要去创建对应这个布局的Fragment,新建一个DiscoverMusicFragment继承自Fragment,代码如下所示

 

?
1
2
3
4
5
6
7
8
9
10
11
public class DiscoverMusicFragment extendsFragment {
 
    @Override
    publicView onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View discover_music_fragment = inflater.inflate(
                R.layout.discover_music_fragment, container,false);
        returndiscover_music_fragment;
    }
 
}

后面的都和这个一样,就不一一展示。

这样我们把每一个Fragment以及它们对应的布局文件都创建好了,接下来我们开始写MainActivity里面的内容,代码如下所示:

 

 

?
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
public class MainActivity extendsActivityimplementsOnClickListener {
    /**
     * 用于展示‘发现音乐’的Fragment
     */
    privateDiscoverMusicFragment discoverMusicFragment;
    /**
     * 用于展示‘我的音乐’的Fragment
     */
    privateMyMusicFragment myMusicFragment;
    /**
     * 用于展示‘朋友’的Fragment
     */
    privateFriendsFragment friendsFragment;
    /**
     * 用于展示‘账号’的Fragment
     */
    privateAccountFragment accountFragment;
    /**
     * ‘发现音乐’布局
     */
    privateView discover_music_layout;
    /**
     * ‘我的音乐’布局
     */
    privateView my_music_layout;
    /**
     * ‘朋友’布局
     */
    privateView friends_layout;
    /**
     * ‘账号’布局
     */
    privateView account_layout;
    /**
     * 在Tab布局上显示‘发现音乐’图标的控件
     */
    privateImageView discover_music_image;
    /**
     * 在Tab布局上显示‘我的音乐’图标的控件
     */
    privateImageView my_music_image;
    /**
     * 在Tab布局上显示‘朋友’图标的控件
     */
    privateImageView friends_image;
    /**
     * 在Tab布局上显示‘账号’图标的控件
     */
    privateImageView account_image;
    /**
     * 在Tab布局上显示‘发现音乐’标题的控件
     */
    privateTextView discover_music_text;
    /**
     * 在Tab布局上显示‘我的音乐’标题的控件
     */
    privateTextView my_music_text;
    /**
     * 在Tab布局上显示‘朋友’标题的控件
     */
    privateTextView friends_text;
    /**
     * 在Tab布局上显示‘账号’标题的控件
     */
    privateTextView account_text;
    /**
     * 用于对Fragment进行管理
     */
    privateFragmentManager fragmentManager;
 
    /**
     * ‘我的音乐’界面‘下载音乐’
     */
    @Override
    protectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        // 初始化布局元素
        initViews();
        fragmentManager = getFragmentManager();
        // 第一次启动时选中第0个tab
        setTabSelection(0);
    }
 
 
    privatevoidinitViews() {
        // 四个布局
        discover_music_layout = findViewById(R.id.discover_layout);
        my_music_layout = findViewById(R.id.my_layout);
        friends_layout = findViewById(R.id.friends_layout);
        account_layout = findViewById(R.id.account_layout);
 
        // 四个图片
        discover_music_image = (ImageView) findViewById(R.id.discover_image);
        my_music_image = (ImageView) findViewById(R.id.my_image);
        friends_image = (ImageView) findViewById(R.id.friends_image);
        account_image = (ImageView) findViewById(R.id.account_image);
 
        // 四个标题
        discover_music_text = (TextView) findViewById(R.id.discover_text);
        my_music_text = (TextView) findViewById(R.id.my_text);
        friends_text = (TextView) findViewById(R.id.friends_text);
        account_text = (TextView) findViewById(R.id.account_text);
        // 设置监听事件
        discover_music_layout.setOnClickListener(this);
        my_music_layout.setOnClickListener(this);
        friends_layout.setOnClickListener(this);
        account_layout.setOnClickListener(this);
    }
 
    @Override
    publicvoidonClick(View v) {
        switch(v.getId()) {
        caseR.id.discover_layout:
            // 当点击了‘发现音乐’tab时,选中第1个tab
            setTabSelection(0);
            break;
        caseR.id.my_layout:
            // 当点击了‘我的音乐’tab时,选中第2个tab
            setTabSelection(1);
            break;
        caseR.id.friends_layout:
            // 当点击了‘朋友’tab时,选中第3个tab
            setTabSelection(2);
            break;
        caseR.id.account_layout:
            // 当点击了‘账号’tab时,选中第4个tab
            setTabSelection(3);
            break;
        default:
            break;
             
        }
 
    }
     
 
    /**
     * 根据传入的index参数来设置选中的tab页。
     *
     * @param index
     *            每个tab页对应的下标。0表示发现音乐,1表示我的音乐,2表示朋友,3表示账号。
     */
    privatevoidsetTabSelection(intindex) {
        // 每次选中之前要清除掉上次选中的状态
        clearSelection();
        // 开启一个Fragment事务
        FragmentTransaction fragmentTransaction = fragmentManager
                .beginTransaction();
        // 先隐藏掉所有的Fragment,以防止有多个Fragment显示在界面上的情况
        HideFragments(fragmentTransaction);
        switch(index) {
        case0:// 当点击了‘发现音乐’时,改变文字的颜色
            discover_music_text.setTextColor(Color.BLUE);
            if(discoverMusicFragment ==null) {
                // 如果discoverMusicFragment为空,则创建一个并添加到界面上
                discoverMusicFragment =newDiscoverMusicFragment();
                fragmentTransaction.add(R.id.Content, discoverMusicFragment);
            }else{
                // 如果discoverMusicFragment不为空,则将其显示出来
                fragmentTransaction.show(discoverMusicFragment);
            }
            break;
        case1:// 当点击了‘我的音乐’时,改变文字的颜色
            my_music_text.setTextColor(Color.BLUE);
            if(myMusicFragment ==null) {
                // 如果myMusicFragment为空,则创建一个并添加到界面上
                myMusicFragment =newMyMusicFragment();
                fragmentTransaction.add(R.id.Content, myMusicFragment);
            }else{
                // 如果myMusicFragment不为空,则将其显示出来
                fragmentTransaction.show(myMusicFragment);
            }
            break;
        case2:// 当点击了‘朋友’时,改变文字的颜色
            friends_text.setTextColor(Color.BLUE);
            if(friendsFragment ==null) {
                // 如果friendsFragment为空,则创建一个并添加到界面上
                friendsFragment =newFriendsFragment();
                fragmentTransaction.add(R.id.Content, friendsFragment);
            }else{
                // 如果friendsFragment不为空,则将其显示出来
                fragmentTransaction.show(friendsFragment);
            }
            break;
        case3:// 当点击了‘账号’时,改变文字的颜色
            account_text.setTextColor(Color.BLUE);
            if(accountFragment ==null) {
                // 如果accountFragment为空,则创建一个并添加到界面上
                accountFragment =newAccountFragment();
                fragmentTransaction.add(R.id.Content, accountFragment);
            }else{
                // 如果accountFragment不为空,则将其显示出来
                fragmentTransaction.show(accountFragment);
            }
            break;
        default:
            break;
        }
        fragmentTransaction.commit();
    }
 
    /**
     * 将所有的Fragment都设置为隐藏状态
     *
     * @param fragmentTransaction
     *            用于对Fragment执行操作的事务
     */
    privatevoidHideFragments(FragmentTransaction fragmentTransaction) {
        if(discoverMusicFragment !=null) {
            fragmentTransaction.hide(discoverMusicFragment);
        }
        if(myMusicFragment !=null) {
            fragmentTransaction.hide(myMusicFragment);
        }
        if(friendsFragment !=null) {
            fragmentTransaction.hide(friendsFragment);
        }
        if(accountFragment !=null) {
            fragmentTransaction.hide(accountFragment);
        }
    }
 
    /**
     * 清除掉所有选中状态
     */
    privatevoidclearSelection() {
        discover_music_text.setTextColor(Color.parseColor("#82858b"));
        my_music_text.setTextColor(Color.parseColor("#82858b"));
        friends_text.setTextColor(Color.parseColor("#82858b"));
        account_text.setTextColor(Color.parseColor("#82858b"));
    }
 
    @Override
    publicbooleanonCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        returntrue;
    }
 
}

代码看不懂的大家可以参照上面的注释。

 

 

下面我再带大家简单梳理一遍。在onCreate()方法中先是调用了initViews()来获取每个控件的实例,并给相应的控件设置好点击事件,然后调用setTabSelection()方法设置默认的选中项,这里传入的0说明默认选中第1个Tab项。

那么setTabSelection()方法中又是如何处理的呢?可以看到,首先第一步是调用clearSelection()方法来清理掉之前的选中状态,然后开启一个Fragment事务,并隐藏掉所有的Fragment,以防止有多个Fragment显示在界面上。接下来根据传入的index参数判断出选中的是哪一个Tab项,并改变该Tab项的图标和文字颜色,然后将相应的Fragment添加到界面上。这里注意一个细节,我们添加Fragment的时候并没有使用replace()方法,而是会先判断一下该Fragment是否为空,如果是空的则调用add()方法添加一个进来,如果不是空的则直接调用show()方法显示出来即可。那么为什么没有使用replace()方法呢?这是因为replace()方法会将被替换掉的那个Fragment彻底地移除掉,该Fragment的生命周期就结束了。当再次点击刚才那个Tab项的时候,就会让该Fragment的生命周期重新开始,onCreate()、onCreateView()等方法都会重新执行一遍。这显然不是我们想要的,也和ActivityGroup的工作原理不符,因此最好的解决方案就是使用hide()和show()方法来隐藏和显示Fragment,这就不会让Fragment的生命周期重走一遍了。

设置完默认选中项后,我们当然还可以通过点击Tab项来自由地切换界面,这就会进入到onClick()方法中。onClick()方法中的逻辑判断非常简单,当点击了消息标签时就会选中第1个tab项,点击联系人标签时就会选中第2个tab项,点击动态标签时就会选中第3个tab项,点击设置标签时就会选中第4个tab项。都是通过调用setTabSelection()方法来完成的,只是传入了不同的参数。

好了,这样我们就将全部的代码都编写完成了。

大家赶紧去试一下吧!

还有一点,这个效果在横屏的时候也可以的哦!

好了,今天的讲解到此结束,有疑问的朋友请在下面留言!谢谢!



0 0
原创粉丝点击