Fragment的利用越来越多了,QQ、新浪微博,支付宝的主界面,都可以用Fragment来实现。
现在,我们就利用Fragment来实现QQ的主界面功能,先上图:
我们可以看到,在QQ主界面的下面,有一行tab,有四个选项,可以实现切换。
新建一个项目,起名为FragmentDemoDemo。创建或者打开activity_main.xml作为程序的主布局文件,加入如下代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<FrameLayout
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@drawable/tab_bg" >
<RelativeLayout
android:id="@+id/message_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical" >
<ImageView
android:id="@+id/message_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/message_unselected" />
<TextView
android:id="@+id/message_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="消息"
android:textColor="#82858b"/>
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/contacts_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical" >
<ImageView
android:id="@+id/contacts_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/contacts_unselected" />
<TextView
android:id="@+id/contacts_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="联系人"
android:textColor="#82858b"/>
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/news_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical" >
<ImageView
android:id="@+id/news_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/news_unselected" />
<TextView
android:id="@+id/news_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="动态"
android:textColor="#82858b"/>
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/setting_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:orientation="vertical" >
<ImageView
android:id="@+id/setting_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/setting_unselected" />
<TextView
android:id="@+id/setting_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="设置"
android:textColor="#82858b" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
这个主布局文件里面,由两部分组成。第一部分是FrameLayout,里面的内容,可以在后面动态添加。第二部分是FrameLayout下面的LinearLayout,这个LinearLayout就是类似TabHost的布局。这个LinearLayout被分成四份,每一份里面多有一个ImageView和一个TextVIew,分别用来显示图标和文字。
已经分成了四份,那我们现在就分别实现四个Fragment和它们的布局了。新建一个message_xml作为消息界面的布局,加入如下代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/message_selected"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="10dp"
android:text="这是消息界面"
android:textSize="20sp"/>
</LinearLayout>
</RelativeLayout>
这个布局比较简单,只是在中间显示一个图标和一些文字。
现在来创建这个布局相对应的Fragment。新建MessageFragment继承Fragment,加入如下代码:
package com.cfy.fragmentdemodemo;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class MessageFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View messageLayout = inflater.inflate(R.layout.message_layout, container, false);
return messageLayout;
}
}
后面三个是类似的。
新建contacts_xml作为联系人界面的布局,加入如下代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/contacts_selected"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="10dp"
android:text="这是联系人界面"
android:textSize="20sp"/>
</LinearLayout>
</RelativeLayout>
再新建ContactsFragment继承Fragment,加入如下代码:
package com.cfy.fragmentdemodemo;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ContactsFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View contactsLayout = inflater.inflate(R.layout.contacts_layout, container, false);
return contactsLayout;
}
}
新建news_layout.xml作为动态界面的布局,加入如下代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/news_selected"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="10dp"
android:text="这是动态界面"
android:textSize="20sp"/>
</LinearLayout>
</RelativeLayout>
新建NewsFragment继承Fragment,加入如下代码:
package com.cfy.fragmentdemodemo;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class NewsFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View newsLayout = inflater.inflate(R.layout.news_layout, container, false);
return newsLayout;
}
}
新建setting_layout.xml作为设置界面的布局,加入如下代码:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="@drawable/setting_selected"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="10dp"
android:text="这是设置界面"
android:textSize="20sp"/>
</LinearLayout>
</RelativeLayout>
新建SettingFragment继承Fragment,加入如下代码:
package com.cfy.fragmentdemodemo;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SettingFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View settingLayout = inflater.inflate(R.layout.setting_layout, container, false);
return settingLayout;
}
}
现在我们已经把四个Fragment都创建好了,以及它们所对应的布局文件。
接下来,我们新建或者打开MainActivity作为主Activity,加入如下代码:
package com.cfy.fragmentdemodemo;
import android.os.Bundle;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.graphics.Color;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
/*
* 项目的主Activity,所有的Fragment都嵌入到这里。
* @author cfy
*/
public class MainActivity extends Activity implements OnClickListener {
/*
* 定义消息、联系人、动态、设置的Fragment
*/
private MessageFragment messageFragment;
private ContactsFragment contactsFragment;
private NewsFragment newsFragment;
private SettingFragment settingFragment;
/*
* 定义消息、联系人、动态、设置的fragment的布局
*/
private View messageLayout;
private View contactsLayout;
private View newsLayout;
private View settingLayout;
/*
* 定义消息、联系人、动态、设置的tab的图标
*/
private ImageView messageImage;
private ImageView contactsImage;
private ImageView newsImage;
private ImageView settingImage;
/*
* 定义消息、联系人、动态、设置的tab的文本
*/
private TextView messageText;
private TextView contactsText;
private TextView newsText;
private TextView settingText;
/*
* 对Fragment进行管理
*/
private FragmentManager fragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
initViews(); //初始化界面,并设置四个tab的监听
fragmentManager = getFragmentManager();
setTabSelection(0); //第一次启动时开启第0个tab
}
/*
* 根据传入的index,来设置开启的tab页面
* @param index
* index代表对应的下标,0对应消息,1对应联系人,2对应动态,3对应设置
*/
private void setTabSelection(int index) {
// TODO Auto-generated method stub
//清理之前的所有状态
clearSelection();
//开启一个Fragment事务
FragmentTransaction transaction = fragmentManager.beginTransaction();
//隐藏所有的fragment,防止有多个界面显示在界面上
hideFragments(transaction);
switch(index){
case 0:
//当点击消息tab时,改变控件的图片和文字颜色
messageImage.setImageResource(R.drawable.message_selected);
messageText.setTextColor(Color.WHITE);
//如果messageFragment为空,则创建一个添加到界面上
if(messageFragment == null){
messageFragment = new MessageFragment();
transaction.add(R.id.content, messageFragment);
} else {
//如果messageFragment不为空,则直接将它显示出来
transaction.show(messageFragment);
}
break;
case 1:
//当点击联系人tab时,改变控件的图片和文字颜色
contactsImage.setImageResource(R.drawable.contacts_selected);
contactsText.setTextColor(Color.WHITE);
//如果contactsFragment为空,则创建一个添加到界面上
if(contactsFragment == null){
contactsFragment = new ContactsFragment();
transaction.add(R.id.content, contactsFragment);
} else {
//如果contactsFragment不为空,则直接将它显示出来
transaction.show(contactsFragment);
}
break;
case 2:
//当点击动态tab时,改变控件的图片和文字颜色
newsImage.setImageResource(R.drawable.news_selected);
newsText.setTextColor(Color.WHITE);
//如果newsFragment为空,则创建一个添加到界面上
if(newsFragment == null){
newsFragment = new NewsFragment();
transaction.add(R.id.content, newsFragment);
} else {
transaction.show(newsFragment);
}
break;
case 3:
default:
//当点击设置tab时,改变控件的图片和文字颜色
settingImage.setImageResource(R.drawable.setting_selected);
settingText.setTextColor(Color.WHITE);
//如果settingFragment为空,则创建一个添加到界面上
if(settingFragment == null){
settingFragment = new SettingFragment();
transaction.add(R.id.content, settingFragment);
} else {
transaction.show(settingFragment);
}
break;
}
transaction.commit();
}
/*
* 隐藏所有的fragment
* @param transaction
* 用于对fragment进行操作的事务
*/
private void hideFragments(FragmentTransaction transaction) {
// TODO Auto-generated method stub
if(messageFragment != null){
transaction.hide(messageFragment);
}
if(contactsFragment != null){
transaction.hide(contactsFragment);
}
if(newsFragment != null){
transaction.hide(newsFragment);
}
if(settingFragment != null){
transaction.hide(settingFragment);
}
}
/*
* 清理之前的所有状态
*/
private void clearSelection() {
// TODO Auto-generated method stub
messageImage.setImageResource(R.drawable.message_unselected);
messageText.setTextColor(Color.parseColor("#82858b"));
contactsImage.setImageResource(R.drawable.contacts_unselected);
contactsText.setTextColor(Color.parseColor("#82858b"));
newsImage.setImageResource(R.drawable.news_unselected);
newsText.setTextColor(Color.parseColor("#82858b"));
settingImage.setImageResource(R.drawable.setting_unselected);
settingText.setTextColor(Color.parseColor("#82858b"));
}
/*
* 初始化界面,并设置四个tab的监听
*/
private void initViews() {
// TODO Auto-generated method stub
messageLayout = findViewById(R.id.message_layout);
contactsLayout = findViewById(R.id.contacts_layout);
newsLayout = findViewById(R.id.news_layout);
settingLayout = findViewById(R.id.setting_layout);
messageImage = (ImageView) findViewById(R.id.message_image);
contactsImage = (ImageView) findViewById(R.id.contacts_image);
newsImage = (ImageView) findViewById(R.id.news_image);
settingImage = (ImageView) findViewById(R.id.setting_image);
messageText = (TextView) findViewById(R.id.message_text);
contactsText = (TextView) findViewById(R.id.contacts_text);
newsText = (TextView) findViewById(R.id.news_text);
settingText = (TextView) findViewById(R.id.setting_text);
messageLayout.setOnClickListener(this);
contactsLayout.setOnClickListener(this);
newsLayout.setOnClickListener(this);
settingLayout.setOnClickListener(this);
}
/*
* 点击四个tab时的监听
* @param v
* 四个控件的view
*/
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId()){
case R.id.message_layout:
//点击消息tab,选中第一个tab
setTabSelection(0);
break;
case R.id.contacts_layout:
//点击联系人tab,选中第二个tab
setTabSelection(1);
break;
case R.id.news_layout:
//点击动态tab,选中第三个tab
setTabSelection(2);
break;
case R.id.setting_layout:
//点击设置tab,选中第四个tab
setTabSelection(3);
break;
default:
break;
}
}
}
代码已经注释得很详细了,到此为主,程序已经写完了。
现在,我们已经使用Fragment编写出和TabHost一样的效果了。每个界面的具体逻辑就可以写在相应的Fragment中了,效果跟写在Activity中类似。