Android应用经典主界面框架之一:仿QQ (使用Fragment, 附源码)

最近反复研究日常经典必用的几个android app,从主界面带来的交互方式入手进行分析,我将其大致分为三类。今天记录第一种方式,即主界面下面有几个tab页,最上端是标题栏,tab页和tab页之间不是通过滑动切换的,而是通过点击切换tab页。早期这种架构一直是使用tabhost+activitygroup来使用,随着fragment的出现及google官方也大力推荐使用fragment,后者大有代替前者之势。本文也使用fragment进行搭建,标题中的“经典”指这种交互经典,非本文的代码框架结构,欢迎大家提出指出不足,帮助完善。文中的fragment部分参考了郭神的博文( 链接1 链接2 链接3 ),代码也是在郭神代码基础上加入了自己对框架的理解。

再次重申下这种主界面交互的特点:1,多个tab,不能滑动切换只能点击切换;2,上有标题栏。这种模式也是目前app中使用最多的。如qq、百度云盘、招商银行、微博、支付宝。几个月前支付宝还是能滑动切换的,后来取消了。视图如下:

               

            

下面本文从底部控制栏、顶部控制栏及中间的内容显示载体fragment三部分叙述。

一、底部控制栏

底部控制栏里每个控件都不是单一基础控件,上面是图片、下面是文字,右上角是红点,当有更新时红点显示,否则隐藏。另外像qq的右上角还能显示未读消息的个数,我的参考链接里是通过大量的layout一点一点搭出来的,这样的好处是方便控制比较直观,另外是可以利用Linearlayout里的layout_weight这个属性,让底部的这些item均匀分布,缺点是代码上有很多重复,维护起来不方便。既然是整理app的通用模板框架,因此我将每个item视为一个对象,然后将其放在底部就ok了。本代码里只封装了上面是图片下面是文字,右上角的红点么有封装进来。

ImageText.java就作了这样一件事:

  1. <span style="font-family: Comic Sans MS; font-size: 18px;">package org.yanzi.ui; 
  2.  
  3. import org.yanzi.constant.Constant; 
  4.  
  5. import android.content.Context; 
  6. import android.graphics.Color; 
  7. import android.util.AttributeSet; 
  8. import android.view.LayoutInflater; 
  9. import android.view.MotionEvent; 
  10. import android.view.View; 
  11. import android.view.ViewGroup; 
  12. import android.widget.ImageView; 
  13. import android.widget.LinearLayout; 
  14. import android.widget.TextView; 
  15.  
  16. import com.example.fragmentproject.R; 
  17.  
  18.  
  19. public class ImageText extends LinearLayout{ 
  20.     private Context mContext = null
  21.     private ImageView mImageView = null
  22.     private TextView mTextView = null
  23.     private final static int DEFAULT_IMAGE_WIDTH = 64
  24.     private final static int DEFAULT_IMAGE_HEIGHT = 64
  25.     private int CHECKED_COLOR = Color.rgb(29, 118, 199); //选中蓝色 
  26.     private int UNCHECKED_COLOR = Color.GRAY;   //自然灰色 
  27.     public ImageText(Context context) { 
  28.         super(context); 
  29.         // TODO Auto-generated constructor stub 
  30.         mContext = context; 
  31.     } 
  32.  
  33.     public ImageText(Context context, AttributeSet attrs) { 
  34.         super(context, attrs); 
  35.         // TODO Auto-generated constructor stub 
  36.         mContext = context; 
  37.         LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
  38.         View parentView = inflater.inflate(R.layout.image_text_layout, this, true); 
  39.         mImageView = (ImageView)findViewById(R.id.image_iamge_text); 
  40.         mTextView = (TextView)findViewById(R.id.text_iamge_text); 
  41.     } 
  42.     public void setImage(int id){ 
  43.         if(mImageView != null){ 
  44.             mImageView.setImageResource(id); 
  45.             setImageSize(DEFAULT_IMAGE_WIDTH, DEFAULT_IMAGE_HEIGHT); 
  46.         } 
  47.     } 
  48.  
  49.     public void setText(String s){ 
  50.         if(mTextView != null){ 
  51.             mTextView.setText(s); 
  52.             mTextView.setTextColor(UNCHECKED_COLOR); 
  53.         } 
  54.     } 
  55.  
  56.     @Override 
  57.     public boolean onInterceptTouchEvent(MotionEvent ev) { 
  58.         // TODO Auto-generated method stub 
  59.         return true
  60.     } 
  61.     private void setImageSize(int w, int h){ 
  62.         if(mImageView != null){ 
  63.             ViewGroup.LayoutParams params = mImageView.getLayoutParams(); 
  64.             params.width = w; 
  65.             params.height = h; 
  66.             mImageView.setLayoutParams(params); 
  67.         } 
  68.     } 
  69.     public void setChecked(int itemID){ 
  70.         if(mTextView != null){ 
  71.             mTextView.setTextColor(CHECKED_COLOR); 
  72.         } 
  73.         int checkDrawableId = -1
  74.         switch (itemID){ 
  75.         case Constant.BTN_FLAG_MESSAGE: 
  76.             checkDrawableId = R.drawable.message_selected; 
  77.             break
  78.         case Constant.BTN_FLAG_CONTACTS: 
  79.             checkDrawableId = R.drawable.contacts_selected; 
  80.             break
  81.         case Constant.BTN_FLAG_NEWS: 
  82.             checkDrawableId = R.drawable.news_selected; 
  83.             break
  84.         case Constant.BTN_FLAG_SETTING: 
  85.             checkDrawableId = R.drawable.setting_selected; 
  86.             break
  87.         default:break
  88.         } 
  89.         if(mImageView != null){ 
  90.             mImageView.setImageResource(checkDrawableId); 
  91.         } 
  92.     } 
  93.  
  94.  
  95.      
  96.  
  97.  
  98. </span> 
<span style="font-family:Comic Sans MS;font-size:18px;">package org.yanzi.ui;

import org.yanzi.constant.Constant;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.example.fragmentproject.R;


public class ImageText extends LinearLayout{
	private Context mContext = null;
	private ImageView mImageView = null;
	private TextView mTextView = null;
	private final static int DEFAULT_IMAGE_WIDTH = 64;
	private final static int DEFAULT_IMAGE_HEIGHT = 64;
	private int CHECKED_COLOR = Color.rgb(29, 118, 199); //选中蓝色
	private int UNCHECKED_COLOR = Color.GRAY;   //自然灰色
	public ImageText(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
		mContext = context;
	}

	public ImageText(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
		mContext = context;
		LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View parentView = inflater.inflate(R.layout.image_text_layout, this, true);
		mImageView = (ImageView)findViewById(R.id.image_iamge_text);
		mTextView = (TextView)findViewById(R.id.text_iamge_text);
	}
	public void setImage(int id){
		if(mImageView != null){
			mImageView.setImageResource(id);
			setImageSize(DEFAULT_IMAGE_WIDTH, DEFAULT_IMAGE_HEIGHT);
		}
	}

	public void setText(String s){
		if(mTextView != null){
			mTextView.setText(s);
			mTextView.setTextColor(UNCHECKED_COLOR);
		}
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		return true;
	}
	private void setImageSize(int w, int h){
		if(mImageView != null){
			ViewGroup.LayoutParams params = mImageView.getLayoutParams();
			params.width = w;
			params.height = h;
			mImageView.setLayoutParams(params);
		}
	}
	public void setChecked(int itemID){
		if(mTextView != null){
			mTextView.setTextColor(CHECKED_COLOR);
		}
		int checkDrawableId = -1;
		switch (itemID){
		case Constant.BTN_FLAG_MESSAGE:
			checkDrawableId = R.drawable.message_selected;
			break;
		case Constant.BTN_FLAG_CONTACTS:
			checkDrawableId = R.drawable.contacts_selected;
			break;
		case Constant.BTN_FLAG_NEWS:
			checkDrawableId = R.drawable.news_selected;
			break;
		case Constant.BTN_FLAG_SETTING:
			checkDrawableId = R.drawable.setting_selected;
			break;
		default:break;
		}
		if(mImageView != null){
			mImageView.setImageResource(checkDrawableId);
		}
	}


	


}
</span>

对应的布局:

  1. <span style="font-family: Comic Sans MS; font-size: 18px;"><?xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="match_parent" 
  4.     android:layout_height="match_parent" 
  5.     android:orientation="vertical" > 
  6.  
  7.     <ImageView 
  8.         android:id="@+id/image_iamge_text" 
  9.         android:layout_width="wrap_content" 
  10.         android:layout_height="wrap_content" 
  11.         android:layout_gravity="center_horizontal" /> 
  12.  
  13.     <TextView 
  14.         android:id="@+id/text_iamge_text" 
  15.         android:layout_width="wrap_content" 
  16.         android:layout_height="wrap_content" 
  17.         android:layout_gravity="center_horizontal" /> 
  18.  
  19. </LinearLayout></span> 
<span style="font-family:Comic Sans MS;font-size:18px;"><?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" >

    <ImageView
        android:id="@+id/image_iamge_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

    <TextView
        android:id="@+id/text_iamge_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />

</LinearLayout></span>

代码里用到了Constant.java,这里面放的都是常量:

  1. <span style="font-family: Comic Sans MS; font-size: 18px;">package org.yanzi.constant; 
  2.  
  3. public class Constant { 
  4.     //Btn的标识 
  5.     public static final int BTN_FLAG_MESSAGE = 0x01
  6.     public static final int BTN_FLAG_CONTACTS = 0x01 << 1
  7.     public static final int BTN_FLAG_NEWS = 0x01 << 2
  8.     public static final int BTN_FLAG_SETTING = 0x01 << 3
  9.      
  10.     //Fragment的标识 
  11.     public static final String FRAGMENT_FLAG_MESSAGE = "消息";  
  12.     public static final String FRAGMENT_FLAG_CONTACTS = "联系人";  
  13.     public static final String FRAGMENT_FLAG_NEWS = "新闻";  
  14.     public static final String FRAGMENT_FLAG_SETTING = "设置";  
  15.     public static final String FRAGMENT_FLAG_SIMPLE = "simple";  
  16.      
  17.      
  18. </span> 
<span style="font-family:Comic Sans MS;font-size:18px;">package org.yanzi.constant;

public class Constant {
	//Btn的标识
	public static final int BTN_FLAG_MESSAGE = 0x01;
	public static final int BTN_FLAG_CONTACTS = 0x01 << 1;
	public static final int BTN_FLAG_NEWS = 0x01 << 2;
	public static final int BTN_FLAG_SETTING = 0x01 << 3;
	
	//Fragment的标识
	public static final String FRAGMENT_FLAG_MESSAGE = "消息"; 
	public static final String FRAGMENT_FLAG_CONTACTS = "联系人"; 
	public static final String FRAGMENT_FLAG_NEWS = "新闻"; 
	public static final String FRAGMENT_FLAG_SETTING = "设置"; 
	public static final String FRAGMENT_FLAG_SIMPLE = "simple"; 
	
	
}
</span>
第一排是复合Button的标识,下面的string类型的是将来创建fragment的标识。

完成了ImageText之后,下面就是将4个这样的控件放到一个布局里。为了控制方便,我们将底部栏抽象为一个对象BottomControlPanel.java,这样在维护底部栏相关内容时直接找他就行了。BottomControlPanel继承自RelativeLayout,先来看它的布局:

bottom_panel_layout.xml

  1. <span style="font-family: Comic Sans MS; font-size: 18px;"><?xml version="1.0" encoding="utf-8"?> 
  2. <org.yanzi.ui.BottomControlPanel xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="match_parent" 
  4.     android:layout_height="60dp" 
  5.     android:layout_alignParentBottom="true" 
  6.     android:gravity="center_vertical" 
  7.     android:paddingLeft="20dp" 
  8.     android:paddingRight="20dp" > 
  9.  
  10.     <org.yanzi.ui.ImageText 
  11.         android:id="@+id/btn_message" 
  12.         android:layout_width="wrap_content" 
  13.         android:layout_height="wrap_content" 
  14.         android:layout_alignParentLeft="true" /> 
  15.  
  16.     <org.yanzi.ui.ImageText 
  17.         android:id="@+id/btn_contacts" 
  18.         android:layout_width="wrap_content" 
  19.         android:layout_height="wrap_content" 
  20.         android:layout_toRightOf="@id/btn_message" /> 
  21.  
  22.     <org.yanzi.ui.ImageText 
  23.         android:id="@+id/btn_news" 
  24.         android:layout_width="wrap_content" 
  25.         android:layout_height="wrap_content" 
  26.         android:layout_toRightOf="@id/btn_contacts" /> 
  27.  
  28.     <org.yanzi.ui.ImageText 
  29.         android:id="@+id/btn_setting" 
  30.         android:layout_width="wrap_content" 
  31.         android:layout_height="wrap_content" 
  32.         android:layout_alignParentRight="true" /> 
  33.  
  34. </org.yanzi.ui.BottomControlPanel></span> 
<span style="font-family:Comic Sans MS;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<org.yanzi.ui.BottomControlPanel xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="60dp"
    android:layout_alignParentBottom="true"
    android:gravity="center_vertical"
    android:paddingLeft="20dp"
    android:paddingRight="20dp" >

    <org.yanzi.ui.ImageText
        android:id="@+id/btn_message"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true" />

    <org.yanzi.ui.ImageText
        android:id="@+id/btn_contacts"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/btn_message" />

    <org.yanzi.ui.ImageText
        android:id="@+id/btn_news"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/btn_contacts" />

    <org.yanzi.ui.ImageText
        android:id="@+id/btn_setting"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true" />

</org.yanzi.ui.BottomControlPanel></span>
对应的java文件:

BottomControlPanel.java

  1. <span style="font-family: Comic Sans MS; font-size: 18px;">package org.yanzi.ui; 
  2.  
  3. import java.util.ArrayList; 
  4. import java.util.List; 
  5.  
  6. import org.yanzi.constant.Constant; 
  7.  
  8. import android.content.Context; 
  9. import android.graphics.Color; 
  10. import android.util.AttributeSet; 
  11. import android.util.Log; 
  12. import android.view.View; 
  13. import android.widget.RelativeLayout; 
  14.  
  15. import com.example.fragmentproject.R; 
  16.  
  17. public class BottomControlPanel extends RelativeLayout implements View.OnClickListener { 
  18.     private Context mContext; 
  19.     private ImageText mMsgBtn = null
  20.     private ImageText mContactsBtn = null
  21.     private ImageText mNewsBtn = null
  22.     private ImageText mSettingBtn = null
  23.     private int DEFALUT_BACKGROUND_COLOR = Color.rgb(243, 243, 243); //Color.rgb(192, 192, 192) 
  24.     private BottomPanelCallback mBottomCallback = null
  25.     private List<ImageText> viewList = new ArrayList<ImageText>(); 
  26.  
  27.     public interface BottomPanelCallback{ 
  28.         public void onBottomPanelClick(int itemId); 
  29.     } 
  30.     public BottomControlPanel(Context context, AttributeSet attrs) { 
  31.         super(context, attrs); 
  32.         // TODO Auto-generated constructor stub 
  33.     } 
  34.     @Override 
  35.     protected void onFinishInflate() { 
  36.         // TODO Auto-generated method stub 
  37.         mMsgBtn = (ImageText)findViewById(R.id.btn_message); 
  38.         mContactsBtn = (ImageText)findViewById(R.id.btn_contacts); 
  39.         mNewsBtn = (ImageText)findViewById(R.id.btn_news); 
  40.         mSettingBtn = (ImageText)findViewById(R.id.btn_setting); 
  41.         setBackgroundColor(DEFALUT_BACKGROUND_COLOR); 
  42.         viewList.add(mMsgBtn); 
  43.         viewList.add(mContactsBtn); 
  44.         viewList.add(mNewsBtn); 
  45.         viewList.add(mSettingBtn); 
  46.  
  47.     } 
  48.     public void initBottomPanel(){ 
  49.         if(mMsgBtn != null){ 
  50.             mMsgBtn.setImage(R.drawable.message_unselected); 
  51.             mMsgBtn.setText("消息"); 
  52.         } 
  53.         if(mContactsBtn != null){ 
  54.             mContactsBtn.setImage(R.drawable.contacts_unselected); 
  55.             mContactsBtn.setText("联系人"); 
  56.         } 
  57.         if(mNewsBtn != null){ 
  58.             mNewsBtn.setImage(R.drawable.news_unselected); 
  59.             mNewsBtn.setText("新闻"); 
  60.         } 
  61.         if(mSettingBtn != null){ 
  62.             mSettingBtn.setImage(R.drawable.setting_unselected); 
  63.             mSettingBtn.setText("设置"); 
  64.         } 
  65.         setBtnListener(); 
  66.  
  67.     } 
  68.     private void setBtnListener(){ 
  69.         int num = this.getChildCount(); 
  70.         for(int i = 0; i < num; i++){ 
  71.             View v = getChildAt(i); 
  72.             if(v != null){ 
  73.                 v.setOnClickListener(this); 
  74.             } 
  75.         } 
  76.     } 
  77.     public void setBottomCallback(BottomPanelCallback bottomCallback){ 
  78.         mBottomCallback = bottomCallback; 
  79.     } 
  80.     @Override 
  81.     public void onClick(View v) { 
  82.         // TODO Auto-generated method stub 
  83.         initBottomPanel(); 
  84.         int index = -1
  85.         switch(v.getId()){ 
  86.         case R.id.btn_message: 
  87.             index = Constant.BTN_FLAG_MESSAGE; 
  88.             mMsgBtn.setChecked(Constant.BTN_FLAG_MESSAGE); 
  89.             break
  90.         case R.id.btn_contacts: 
  91.             index = Constant.BTN_FLAG_CONTACTS; 
  92.             mContactsBtn.setChecked(Constant.BTN_FLAG_CONTACTS); 
  93.             break
  94.         case R.id.btn_news: 
  95.             index = Constant.BTN_FLAG_NEWS; 
  96.             mNewsBtn.setChecked(Constant.BTN_FLAG_NEWS); 
  97.             break
  98.         case R.id.btn_setting: 
  99.             index = Constant.BTN_FLAG_SETTING; 
  100.             mSettingBtn.setChecked(Constant.BTN_FLAG_SETTING); 
  101.             break
  102.         default:break
  103.         } 
  104.         if(mBottomCallback != null){ 
  105.             mBottomCallback.onBottomPanelClick(index); 
  106.         } 
  107.     } 
  108.     public void defaultBtnChecked(){ 
  109.         if(mMsgBtn != null){ 
  110.             mMsgBtn.setChecked(Constant.BTN_FLAG_MESSAGE); 
  111.         } 
  112.     } 
  113.     @Override 
  114.     protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 
  115.         // TODO Auto-generated method stub 
  116.         super.onLayout(changed, left, top, right, bottom); 
  117.         layoutItems(left, top, right, bottom); 
  118.     } 
  119.     /**最左边和最右边的view由母布局的padding进行控制位置。这里需对第2、3个view的位置重新设置
  120.      * @param left
  121.      * @param top
  122.      * @param right
  123.      * @param bottom
  124.      */ 
  125.     private void layoutItems(int left, int top, int right, int bottom){ 
  126.         int n = getChildCount(); 
  127.         if(n == 0){ 
  128.             return
  129.         } 
  130.         int paddingLeft = getPaddingLeft(); 
  131.         int paddingRight = getPaddingRight(); 
  132.         Log.i("yanguoqi", "paddingLeft = " + paddingLeft + " paddingRight = " + paddingRight); 
  133.         int width = right - left; 
  134.         int height = bottom - top; 
  135.         Log.i("yanguoqi", "width = " + width + " height = " + height); 
  136.         int allViewWidth = 0
  137.         for(int i = 0; i< n; i++){ 
  138.             View v = getChildAt(i); 
  139.             Log.i("yanguoqi", "v.getWidth() = " + v.getWidth()); 
  140.             allViewWidth += v.getWidth(); 
  141.         } 
  142.         int blankWidth = (width - allViewWidth - paddingLeft - paddingRight) / (n - 1); 
  143.         Log.i("yanguoqi", "blankV = " + blankWidth ); 
  144.  
  145.         LayoutParams params1 = (LayoutParams) viewList.get(1).getLayoutParams(); 
  146.         params1.leftMargin = blankWidth; 
  147.         viewList.get(1).setLayoutParams(params1); 
  148.  
  149.         LayoutParams params2 = (LayoutParams) viewList.get(2).getLayoutParams(); 
  150.         params2.leftMargin = blankWidth; 
  151.         viewList.get(2).setLayoutParams(params2); 
  152.     } 
  153.  
  154.  
  155.  
  156. </span> 
<span style="font-family:Comic Sans MS;font-size:18px;">package org.yanzi.ui;

import java.util.ArrayList;
import java.util.List;

import org.yanzi.constant.Constant;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout;

import com.example.fragmentproject.R;

public class BottomControlPanel extends RelativeLayout implements View.OnClickListener {
	private Context mContext;
	private ImageText mMsgBtn = null;
	private ImageText mContactsBtn = null;
	private ImageText mNewsBtn = null;
	private ImageText mSettingBtn = null;
	private int DEFALUT_BACKGROUND_COLOR = Color.rgb(243, 243, 243); //Color.rgb(192, 192, 192)
	private BottomPanelCallback mBottomCallback = null;
	private List<ImageText> viewList = new ArrayList<ImageText>();

	public interface BottomPanelCallback{
		public void onBottomPanelClick(int itemId);
	}
	public BottomControlPanel(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}
	@Override
	protected void onFinishInflate() {
		// TODO Auto-generated method stub
		mMsgBtn = (ImageText)findViewById(R.id.btn_message);
		mContactsBtn = (ImageText)findViewById(R.id.btn_contacts);
		mNewsBtn = (ImageText)findViewById(R.id.btn_news);
		mSettingBtn = (ImageText)findViewById(R.id.btn_setting);
		setBackgroundColor(DEFALUT_BACKGROUND_COLOR);
		viewList.add(mMsgBtn);
		viewList.add(mContactsBtn);
		viewList.add(mNewsBtn);
		viewList.add(mSettingBtn);

	}
	public void initBottomPanel(){
		if(mMsgBtn != null){
			mMsgBtn.setImage(R.drawable.message_unselected);
			mMsgBtn.setText("消息");
		}
		if(mContactsBtn != null){
			mContactsBtn.setImage(R.drawable.contacts_unselected);
			mContactsBtn.setText("联系人");
		}
		if(mNewsBtn != null){
			mNewsBtn.setImage(R.drawable.news_unselected);
			mNewsBtn.setText("新闻");
		}
		if(mSettingBtn != null){
			mSettingBtn.setImage(R.drawable.setting_unselected);
			mSettingBtn.setText("设置");
		}
		setBtnListener();

	}
	private void setBtnListener(){
		int num = this.getChildCount();
		for(int i = 0; i < num; i++){
			View v = getChildAt(i);
			if(v != null){
				v.setOnClickListener(this);
			}
		}
	}
	public void setBottomCallback(BottomPanelCallback bottomCallback){
		mBottomCallback = bottomCallback;
	}
	@Override
	public void onClick(View v) {
		// TODO Auto-generated method stub
		initBottomPanel();
		int index = -1;
		switch(v.getId()){
		case R.id.btn_message:
			index = Constant.BTN_FLAG_MESSAGE;
			mMsgBtn.setChecked(Constant.BTN_FLAG_MESSAGE);
			break;
		case R.id.btn_contacts:
			index = Constant.BTN_FLAG_CONTACTS;
			mContactsBtn.setChecked(Constant.BTN_FLAG_CONTACTS);
			break;
		case R.id.btn_news:
			index = Constant.BTN_FLAG_NEWS;
			mNewsBtn.setChecked(Constant.BTN_FLAG_NEWS);
			break;
		case R.id.btn_setting:
			index = Constant.BTN_FLAG_SETTING;
			mSettingBtn.setChecked(Constant.BTN_FLAG_SETTING);
			break;
		default:break;
		}
		if(mBottomCallback != null){
			mBottomCallback.onBottomPanelClick(index);
		}
	}
	public void defaultBtnChecked(){
		if(mMsgBtn != null){
			mMsgBtn.setChecked(Constant.BTN_FLAG_MESSAGE);
		}
	}
	@Override
	protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
		// TODO Auto-generated method stub
		super.onLayout(changed, left, top, right, bottom);
		layoutItems(left, top, right, bottom);
	}
	/**最左边和最右边的view由母布局的padding进行控制位置。这里需对第2、3个view的位置重新设置
	 * @param left
	 * @param top
	 * @param right
	 * @param bottom
	 */
	private void layoutItems(int left, int top, int right, int bottom){
		int n = getChildCount();
		if(n == 0){
			return;
		}
		int paddingLeft = getPaddingLeft();
		int paddingRight = getPaddingRight();
		Log.i("yanguoqi", "paddingLeft = " + paddingLeft + " paddingRight = " + paddingRight);
		int width = right - left;
		int height = bottom - top;
		Log.i("yanguoqi", "width = " + width + " height = " + height);
		int allViewWidth = 0;
		for(int i = 0; i< n; i++){
			View v = getChildAt(i);
			Log.i("yanguoqi", "v.getWidth() = " + v.getWidth());
			allViewWidth += v.getWidth();
		}
		int blankWidth = (width - allViewWidth - paddingLeft - paddingRight) / (n - 1);
		Log.i("yanguoqi", "blankV = " + blankWidth );

		LayoutParams params1 = (LayoutParams) viewList.get(1).getLayoutParams();
		params1.leftMargin = blankWidth;
		viewList.get(1).setLayoutParams(params1);

		LayoutParams params2 = (LayoutParams) viewList.get(2).getLayoutParams();
		params2.leftMargin = blankWidth;
		viewList.get(2).setLayoutParams(params2);
	}



}
</span>
在onFinishInflate()函数里实例化里面的子元素,在initBottomPanel()里设置每个孩子的图片和文字、监听.onLayout()里对中间的2个孩子的位置进行调整,使其均匀分布,见我的前文。这个BottomControlPanel实现了View.OnClickListener接口,在onClick()里通过id来判断用户点击了哪一个孩子。判断出来后需要做两件事,一是对这个被点击的对象进行处理,如字体颜色、图片资源的变化,右上角小红点的隐藏等等。另一方面,BottomControlPanel要告诉将来它的主人,也就是Activity到底是点了哪个,通知Activity去切换fragment。可以看到,activity类似个总控中心,BottomControlPanel管理属于它的ImageText,同时上报Activity。Activity知道消息后再切换fragment,每个fragment都有自己的事务逻辑。

这里定义了

public interface BottomPanelCallback{
public void onBottomPanelClick(int itemId);
}这个接口,通过传递Id来通知Activity。defaultBtnChecked()函数是apk初次打开后,默认切换到第一个消息fragment上。

这里有个地方需要注意,就是虽然ImageText和BottomControlPanel都是自定义控件,但两者在方式上是有区别的。在ImageText的构造函数里通过inflater将布局加载进来,它对应的布局是个普通的布局。而BottomControlPanel对应的布局文件里,直接使用了定义的BottomControlPanel,在onFinishInflate函数里实例化孩子View。前者是inflate之后实例化的。在使用ImageText到一个新的母布局时是通过<org.yanzi.ui.ImageText />这种方式进行的,那么使用BottomControlPanel有何区别,请见下文介绍Activity的布局时。

二、顶部控制栏

有了底部控制栏,顶部控制栏就可以如法炮制了。这里先交代几句,虽然Android3.0 后Google推出的有ActionBar来做顶部导航栏,参见郭神的这篇博文。但我发现,本文最前面贴图的几款应用应该都没有使用ActionBar,因为它不够灵活。ActionBar使用起来什么样,大家看看微信就知道了,那个的顶部控制栏就是ActionBar做的,这个应该没跑。

通过观察,顶部控制栏除了标题居中外,在右上角通常会再放一个按钮。不是ImageView就是TextView,这里我为了方便放的是两个TextView,右侧的按钮效果可以再TextView上弄个背景来实现。

HeadControlPanel.java

  1. <span style="font-family: Comic Sans MS; font-size: 18px;">package org.yanzi.ui; 
  2.  
  3. import org.yanzi.constant.Constant; 
  4.  
  5. import com.example.fragmentproject.R; 
  6.  
  7. import android.content.Context; 
  8. import android.graphics.Color; 
  9. import android.util.AttributeSet; 
  10. import android.widget.RelativeLayout; 
  11. import android.widget.TextView; 
  12.  
  13. public class HeadControlPanel extends RelativeLayout { 
  14.  
  15.     private Context mContext; 
  16.     private TextView mMidleTitle; 
  17.     private TextView mRightTitle; 
  18.     private static final float middle_title_size = 20f;  
  19.     private static final float right_title_size = 17f;  
  20.     private static final int default_background_color = Color.rgb(23, 124, 202); 
  21.      
  22.     public HeadControlPanel(Context context, AttributeSet attrs) { 
  23.         super(context, attrs); 
  24.         // TODO Auto-generated constructor stub 
  25.     } 
  26.  
  27.     @Override 
  28.     protected void onFinishInflate() { 
  29.         // TODO Auto-generated method stub 
  30.         mMidleTitle = (TextView)findViewById(R.id.midle_title); 
  31.         mRightTitle = (TextView)findViewById(R.id.right_title); 
  32.         setBackgroundColor(default_background_color); 
  33.     } 
  34.     public void initHeadPanel(){ 
  35.          
  36.         if(mMidleTitle != null){ 
  37.             setMiddleTitle(Constant.FRAGMENT_FLAG_MESSAGE); 
  38.         } 
  39.     } 
  40.     public void setMiddleTitle(String s){ 
  41.         mMidleTitle.setText(s); 
  42.         mMidleTitle.setTextSize(middle_title_size); 
  43.     } 
  44.      
  45.  
  46. </span> 
<span style="font-family:Comic Sans MS;font-size:18px;">package org.yanzi.ui;

import org.yanzi.constant.Constant;

import com.example.fragmentproject.R;

import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class HeadControlPanel extends RelativeLayout {

	private Context mContext;
	private TextView mMidleTitle;
	private TextView mRightTitle;
	private static final float middle_title_size = 20f; 
	private static final float right_title_size = 17f; 
	private static final int default_background_color = Color.rgb(23, 124, 202);
	
	public HeadControlPanel(Context context, AttributeSet attrs) {
		super(context, attrs);
		// TODO Auto-generated constructor stub
	}

	@Override
	protected void onFinishInflate() {
		// TODO Auto-generated method stub
		mMidleTitle = (TextView)findViewById(R.id.midle_title);
		mRightTitle = (TextView)findViewById(R.id.right_title);
		setBackgroundColor(default_background_color);
	}
	public void initHeadPanel(){
		
		if(mMidleTitle != null){
			setMiddleTitle(Constant.FRAGMENT_FLAG_MESSAGE);
		}
	}
	public void setMiddleTitle(String s){
		mMidleTitle.setText(s);
		mMidleTitle.setTextSize(middle_title_size);
	}
	

}
</span>

布局文件head_panel_layout.xml

  1. <span style="font-family: Comic Sans MS; font-size: 18px;"><?xml version="1.0" encoding="utf-8"?> 
  2. <org.yanzi.ui.HeadControlPanel xmlns:android="http://schemas.android.com/apk/res/android" 
  3.     android:layout_width="match_parent" 
  4.     android:layout_height="50dp" 
  5.     android:layout_alignParentTop="true"> 
  6.     <TextView  
  7.         android:id="@+id/midle_title" 
  8.         android:layout_width="wrap_content" 
  9.         android:layout_height="wrap_content" 
  10.         android:layout_centerInParent="true" 
  11.         android:textColor="@android:color/white"/> 
  12.     <TextView  
  13.          android:id="@+id/right_title" 
  14.         android:layout_width="wrap_content" 
  15.         android:layout_height="wrap_content" 
  16.         android:layout_alignParentRight="true" 
  17.         android:textColor="@android:color/white"/> 
  18.          
  19. </org.yanzi.ui.HeadControlPanel> 
  20. </span> 
<span style="font-family:Comic Sans MS;font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<org.yanzi.ui.HeadControlPanel xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:layout_alignParentTop="true">
    <TextView 
        android:id="@+id/midle_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:textColor="@android:color/white"/>
    <TextView 
         android:id="@+id/right_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:textColor="@android:color/white"/>
        
</org.yanzi.ui.HeadControlPanel>
</span>

三、总控中心Activity和Fragment

先交代下Fragment的使用大致分两种,一种是将Fragment作为一个View写死在布局中,布局里使用android:name来告诉它对应的是哪个实体Fragment。这种添加fragment的方式不能delete和replace掉。另一种是通过获得activity的fragmentmanager和fragmentTransaction和进行动态的添加。这种方式更加灵活,一般使用此种方法。

先看Activity的布局activity_main.xml:

  1. <span style="font-family: Comic Sans MS; font-size: 18px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  2.     xmlns:tools="http://schemas.android.com/tools" 
  3.     android:id="@+id/root_layout" 
  4.     android:layout_width="match_parent" 
  5.     android:layout_height="match_parent" 
  6.     tools:context="org.yanzi.fragmentproject.MainActivity" > 
  7.  
  8.     <include 
  9.         android:id="@+id/bottom_layout" 
  10.         layout="@layout/bottom_panel_layout" /> 
  11.  
  12.     <View 
  13.         android:layout_width="match_parent" 
  14.         android:layout_height="1dip" 
  15.         android:layout_above="@id/bottom_layout" 
  16.         android:background="#FFE7E7E7" /> 
  17.  
  18.     <include 
  19.         android:id="@+id/head_layout" 
  20.         layout="@layout/head_panel_layout" /> 
  21.  
  22.     <View 
  23.         android:layout_width="match_parent" 
  24.         android:layout_height="1dip" 
  25.         android:layout_below="@id/head_layout" 
  26.         android:background="#FFE7E7E7" /> 
  27.     <FrameLayout 
  28.         android:id="@+id/fragment_content" 
  29.         android:layout_width="match_parent" 
  30.         android:layout_height="wrap_content" 
  31.         android:layout_below="@id/head_layout" 
  32.         android:layout_above="@id/bottom_layout" > 
  33.     </FrameLayout> 
  34.  
  35. </RelativeLayout></span> 
<span style="font-family:Comic Sans MS;font-size:18px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="org.yanzi.fragmentproject.MainActivity" >

    <include
        android:id="@+id/bottom_layout"
        layout="@layout/bottom_panel_layout" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dip"
        android:layout_above="@id/bottom_layout"
        android:background="#FFE7E7E7" />

    <include
        android:id="@+id/head_layout"
        layout="@layout/head_panel_layout" />

    <View
        android:layout_width="match_parent"
        android:layout_height="1dip"
        android:layout_below="@id/head_layout"
        android:background="#FFE7E7E7" />
    <FrameLayout
        android:id="@+id/fragment_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/head_layout"
        android:layout_above="@id/bottom_layout" >
    </FrameLayout>

</RelativeLayout></span>

注意看这里是通过include的方式把刚才自定义的上下panel加过来,而不能直接用<org.yanzi.ui.BottomControlPanel />这种方式直接加载。当然如果也模仿ImageText的构造方式,也是可以这样用的。关于include方式的使用有几个注意事项,就是最好让它的母布局是RelativeLayout,否则的话很难控制include进来的布局的位置。另外,include布局的位置一定要写在include之前,如底部面板在最底部,android:layout_alignParentBottom="true"这句话是在bottom_panel_layout.xml里写的,如果写在activity_main.xml里就是无效的,这着实是个蛋疼的问题。再就是include后设置的id会覆盖掉以前的,所以这里只在include的时候设置id。其中的两个View是分割线。整体是按照底部栏、上部栏、中间Fragment的容器来放置的。

在放Fragment的时候需要注意,究竟是否要将顶部控制栏放到各自的fragment里合适还是放到Activity里合适要看具体情况,如果顶部栏里多是显示标题这种功能或少量的点击事件,应该放到Activity里,即顶部栏的事务逻辑和当前fragment的事务逻辑耦合的不是很紧。举个例子,比如微信的顶部栏,不管你处在哪个Tab页(聊天、发现、通讯录),点击顶部栏里的按钮都呈现出同样的内容。但反过来讲,如果顶部栏里的事务逻辑和fragment耦合很紧,即在不同的fragment,顶部栏呈现的内容都不一样,且点击后处理的事务也和当前fragment紧密联系一起,那就应该一个fragment配套一个顶部栏,方便控制。本文是将两者分开的。所以让fragment的容器在顶部栏之下,底部栏之上,不这样写的话,就会遮挡。

    <FrameLayout
        android:id="@+id/fragment_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/head_layout"
        android:layout_above="@id/bottom_layout" >
    </FrameLayout>


MainActivity.java代码:

  1. <span style="font-family: Comic Sans MS; font-size: 18px;">package org.yanzi.activity; 
  2.  
  3. import org.yanzi.constant.Constant; 
  4. import org.yanzi.fragment.BaseFragment; 
  5. import org.yanzi.fragment.ContactsFragment; 
  6. import org.yanzi.fragment.MessageFragment; 
  7. import org.yanzi.fragment.NewsFragment; 
  8. import org.yanzi.fragment.SettingFragment; 
  9. import org.yanzi.ui.BottomControlPanel; 
  10. import org.yanzi.ui.BottomControlPanel.BottomPanelCallback; 
  11. import org.yanzi.ui.HeadControlPanel; 
  12.  
  13. import android.app.Activity; 
  14. import android.app.Fragment; 
  15. import android.app.FragmentManager; 
  16. import android.app.FragmentTransaction; 
  17. import android.os.Bundle; 
  18. import android.text.TextUtils; 
  19. import android.util.Log; 
  20. import android.view.Menu; 
  21. import android.widget.Toast; 
  22.  
  23. import com.example.fragmentproject.R; 
  24.  
  25. public class MainActivity extends Activity implements BottomPanelCallback { 
  26.     BottomControlPanel bottomPanel = null
  27.     HeadControlPanel headPanel = null
  28.      
  29.     private FragmentManager fragmentManager = null
  30.     private FragmentTransaction fragmentTransaction = null
  31.      
  32. /*  private MessageFragment messageFragment;
  33.     private ContactsFragment contactsFragment;
  34.     private NewsFragment newsFragment;
  35.     private SettingFragment settingFragment;*/ 
  36.      
  37.     public static String currFragTag = ""
  38.     @Override 
  39.     protected void onCreate(Bundle savedInstanceState) { 
  40.         super.onCreate(savedInstanceState); 
  41.         setContentView(R.layout.activity_main); 
  42.         initUI(); 
  43.         fragmentManager = getFragmentManager(); 
  44.         setDefaultFirstFragment(Constant.FRAGMENT_FLAG_MESSAGE); 
  45.     } 
  46.  
  47.     @Override 
  48.     public boolean onCreateOptionsMenu(Menu menu) { 
  49.         // Inflate the menu; this adds items to the action bar if it is present. 
  50.         getMenuInflater().inflate(R.menu.main, menu); 
  51.         return true
  52.     } 
  53.     private void initUI(){ 
  54.         bottomPanel = (BottomControlPanel)findViewById(R.id.bottom_layout); 
  55.         if(bottomPanel != null){ 
  56.             bottomPanel.initBottomPanel(); 
  57.             bottomPanel.setBottomCallback(this); 
  58.         } 
  59.         headPanel = (HeadControlPanel)findViewById(R.id.head_layout); 
  60.         if(headPanel != null){ 
  61.             headPanel.initHeadPanel(); 
  62.         } 
  63.     } 
  64.  
  65.     /* 处理BottomControlPanel的回调
  66.      * @see org.yanzi.ui.BottomControlPanel.BottomPanelCallback#onBottomPanelClick(int)
  67.      */ 
  68.     @Override 
  69.     public void onBottomPanelClick(int itemId) { 
  70.         // TODO Auto-generated method stub 
  71.         String tag = ""
  72.         if((itemId & Constant.BTN_FLAG_MESSAGE) != 0){ 
  73.             tag = Constant.FRAGMENT_FLAG_MESSAGE; 
  74.         }else if((itemId & Constant.BTN_FLAG_CONTACTS) != 0){ 
  75.             tag = Constant.FRAGMENT_FLAG_CONTACTS; 
  76.         }else if((itemId & Constant.BTN_FLAG_NEWS) != 0){ 
  77.             tag = Constant.FRAGMENT_FLAG_NEWS; 
  78.         }else if((itemId & Constant.BTN_FLAG_SETTING) != 0){ 
  79.             tag = Constant.FRAGMENT_FLAG_SETTING; 
  80.         } 
  81.         setTabSelection(tag); //切换Fragment 
  82.         headPanel.setMiddleTitle(tag);//切换标题  
  83.     } 
  84.      
  85.     private void setDefaultFirstFragment(String tag){ 
  86.         Log.i("yan", "setDefaultFirstFragment enter... currFragTag = " + currFragTag); 
  87.         setTabSelection(tag); 
  88.         bottomPanel.defaultBtnChecked(); 
  89.         Log.i("yan", "setDefaultFirstFragment exit..."); 
  90.     } 
  91.      
  92.     private void commitTransactions(String tag){ 
  93.         if (fragmentTransaction != null && !fragmentTransaction.isEmpty()) { 
  94.             fragmentTransaction.commit(); 
  95.             currFragTag = tag; 
  96.             fragmentTransaction = null
  97.         } 
  98.     } 
  99.      
  100.     private FragmentTransaction ensureTransaction( ){ 
  101.         if(fragmentTransaction == null){ 
  102.             fragmentTransaction = fragmentManager.beginTransaction(); 
  103.             fragmentTransaction 
  104.             .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); 
  105.              
  106.         } 
  107.         return fragmentTransaction; 
  108.          
  109.     } 
  110.      
  111.     private void attachFragment(int layout, Fragment f, String tag){ 
  112.         if(f != null){ 
  113.             if(f.isDetached()){ 
  114.                 ensureTransaction(); 
  115.                 fragmentTransaction.attach(f); 
  116.                  
  117.             }else if(!f.isAdded()){ 
  118.                 ensureTransaction(); 
  119.                 fragmentTransaction.add(layout, f, tag); 
  120.             } 
  121.         } 
  122.     } 
  123.      
  124.     private Fragment getFragment(String tag){ 
  125.          
  126.         Fragment f = fragmentManager.findFragmentByTag(tag); 
  127.          
  128.         if(f == null){ 
  129.             Toast.makeText(getApplicationContext(), "fragment = null tag = " + tag, Toast.LENGTH_SHORT).show(); 
  130.             f = BaseFragment.newInstance(getApplicationContext(), tag); 
  131.         } 
  132.         return f; 
  133.          
  134.     } 
  135.     private void detachFragment(Fragment f){ 
  136.          
  137.         if(f != null && !f.isDetached()){ 
  138.             ensureTransaction(); 
  139.             fragmentTransaction.detach(f); 
  140.         } 
  141.     } 
  142.     /**切换fragment
  143.      * @param tag
  144.      */ 
  145.     private  void switchFragment(String tag){ 
  146.         if(TextUtils.equals(tag, currFragTag)){ 
  147.             return
  148.         } 
  149.         //把上一个fragment detach掉  
  150.         if(currFragTag != null && !currFragTag.equals("")){ 
  151.             detachFragment(getFragment(currFragTag)); 
  152.         } 
  153.         attachFragment(R.id.fragment_content, getFragment(tag), tag); 
  154.         commitTransactions( tag); 
  155.     }  
  156.      
  157.     /**设置选中的Tag
  158.      * @param tag
  159.      */ 
  160.     public  void setTabSelection(String tag) { 
  161.         // 开启一个Fragment事务 
  162.         fragmentTransaction = fragmentManager.beginTransaction(); 
  163. /*       if(TextUtils.equals(tag, Constant.FRAGMENT_FLAG_MESSAGE)){
  164.            if (messageFragment == null) {
  165.                 messageFragment = new MessageFragment();
  166.             }
  167.            
  168.         }else if(TextUtils.equals(tag, Constant.FRAGMENT_FLAG_CONTACTS)){
  169.             if (contactsFragment == null) {
  170.                 contactsFragment = new ContactsFragment();
  171.             }
  172.            
  173.         }else if(TextUtils.equals(tag, Constant.FRAGMENT_FLAG_NEWS)){
  174.             if (newsFragment == null) {
  175.                 newsFragment = new NewsFragment();
  176.             }
  177.            
  178.         }else if(TextUtils.equals(tag,Constant.FRAGMENT_FLAG_SETTING)){
  179.             if (settingFragment == null) {
  180.                 settingFragment = new SettingFragment();
  181.             }
  182.         }else if(TextUtils.equals(tag, Constant.FRAGMENT_FLAG_SIMPLE)){
  183.             if (simpleFragment == null) {
  184.                 simpleFragment = new SimpleFragment();
  185.             }
  186.            
  187.         }*/ 
  188.          switchFragment(tag); 
  189.           
  190.     } 
  191.  
  192.     @Override 
  193.     protected void onStop() { 
  194.         // TODO Auto-generated method stub 
  195.         super.onStop(); 
  196.         currFragTag = ""
  197.     } 
  198.  
  199.     @Override 
  200.     protected void onSaveInstanceState(Bundle outState) { 
  201.         // TODO Auto-generated method stub 
  202.     } 
  203.  
  204. </span> 
<span style="font-family:Comic Sans MS;font-size:18px;">package org.yanzi.activity;

import org.yanzi.constant.Constant;
import org.yanzi.fragment.BaseFragment;
import org.yanzi.fragment.ContactsFragment;
import org.yanzi.fragment.MessageFragment;
import org.yanzi.fragment.NewsFragment;
import org.yanzi.fragment.SettingFragment;
import org.yanzi.ui.BottomControlPanel;
import org.yanzi.ui.BottomControlPanel.BottomPanelCallback;
import org.yanzi.ui.HeadControlPanel;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;

import com.example.fragmentproject.R;

public class MainActivity extends Activity implements BottomPanelCallback {
	BottomControlPanel bottomPanel = null;
	HeadControlPanel headPanel = null;
	
	private FragmentManager fragmentManager = null;
	private FragmentTransaction fragmentTransaction = null;
	
/*	private MessageFragment messageFragment;
	private ContactsFragment contactsFragment;
	private NewsFragment newsFragment;
	private SettingFragment settingFragment;*/
	
	public static String currFragTag = "";
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initUI();
		fragmentManager = getFragmentManager();
		setDefaultFirstFragment(Constant.FRAGMENT_FLAG_MESSAGE);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}
	private void initUI(){
		bottomPanel = (BottomControlPanel)findViewById(R.id.bottom_layout);
		if(bottomPanel != null){
			bottomPanel.initBottomPanel();
			bottomPanel.setBottomCallback(this);
		}
		headPanel = (HeadControlPanel)findViewById(R.id.head_layout);
		if(headPanel != null){
			headPanel.initHeadPanel();
		}
	}

	/* 处理BottomControlPanel的回调
	 * @see org.yanzi.ui.BottomControlPanel.BottomPanelCallback#onBottomPanelClick(int)
	 */
	@Override
	public void onBottomPanelClick(int itemId) {
		// TODO Auto-generated method stub
		String tag = "";
		if((itemId & Constant.BTN_FLAG_MESSAGE) != 0){
			tag = Constant.FRAGMENT_FLAG_MESSAGE;
		}else if((itemId & Constant.BTN_FLAG_CONTACTS) != 0){
			tag = Constant.FRAGMENT_FLAG_CONTACTS;
		}else if((itemId & Constant.BTN_FLAG_NEWS) != 0){
			tag = Constant.FRAGMENT_FLAG_NEWS;
		}else if((itemId & Constant.BTN_FLAG_SETTING) != 0){
			tag = Constant.FRAGMENT_FLAG_SETTING;
		}
		setTabSelection(tag); //切换Fragment
		headPanel.setMiddleTitle(tag);//切换标题 
	}
	
	private void setDefaultFirstFragment(String tag){
		Log.i("yan", "setDefaultFirstFragment enter... currFragTag = " + currFragTag);
		setTabSelection(tag);
		bottomPanel.defaultBtnChecked();
		Log.i("yan", "setDefaultFirstFragment exit...");
	}
	
	private void commitTransactions(String tag){
		if (fragmentTransaction != null && !fragmentTransaction.isEmpty()) {
			fragmentTransaction.commit();
			currFragTag = tag;
			fragmentTransaction = null;
		}
	}
	
	private FragmentTransaction ensureTransaction( ){
		if(fragmentTransaction == null){
			fragmentTransaction = fragmentManager.beginTransaction();
			fragmentTransaction
			.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
			
		}
		return fragmentTransaction;
		
	}
	
	private void attachFragment(int layout, Fragment f, String tag){
		if(f != null){
			if(f.isDetached()){
				ensureTransaction();
				fragmentTransaction.attach(f);
				
			}else if(!f.isAdded()){
				ensureTransaction();
				fragmentTransaction.add(layout, f, tag);
			}
		}
	}
	
	private Fragment getFragment(String tag){
		
		Fragment f = fragmentManager.findFragmentByTag(tag);
		
		if(f == null){
			Toast.makeText(getApplicationContext(), "fragment = null tag = " + tag, Toast.LENGTH_SHORT).show();
			f = BaseFragment.newInstance(getApplicationContext(), tag);
		}
		return f;
		
	}
	private void detachFragment(Fragment f){
		
		if(f != null && !f.isDetached()){
			ensureTransaction();
			fragmentTransaction.detach(f);
		}
	}
	/**切换fragment 
	 * @param tag
	 */
	private  void switchFragment(String tag){
		if(TextUtils.equals(tag, currFragTag)){
			return;
		}
		//把上一个fragment detach掉 
		if(currFragTag != null && !currFragTag.equals("")){
			detachFragment(getFragment(currFragTag));
		}
		attachFragment(R.id.fragment_content, getFragment(tag), tag);
		commitTransactions( tag);
	} 
	
	/**设置选中的Tag
	 * @param tag
	 */
	public  void setTabSelection(String tag) {
		// 开启一个Fragment事务
		fragmentTransaction = fragmentManager.beginTransaction();
/*		 if(TextUtils.equals(tag, Constant.FRAGMENT_FLAG_MESSAGE)){
		   if (messageFragment == null) {
				messageFragment = new MessageFragment();
			} 
			
		}else if(TextUtils.equals(tag, Constant.FRAGMENT_FLAG_CONTACTS)){
			if (contactsFragment == null) {
				contactsFragment = new ContactsFragment();
			} 
			
		}else if(TextUtils.equals(tag, Constant.FRAGMENT_FLAG_NEWS)){
			if (newsFragment == null) {
				newsFragment = new NewsFragment();
			}
			
		}else if(TextUtils.equals(tag,Constant.FRAGMENT_FLAG_SETTING)){
			if (settingFragment == null) {
				settingFragment = new SettingFragment();
			}
		}else if(TextUtils.equals(tag, Constant.FRAGMENT_FLAG_SIMPLE)){
			if (simpleFragment == null) {
				simpleFragment = new SimpleFragment();
			} 
			
		}*/
		 switchFragment(tag);
		 
	}

	@Override
	protected void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		currFragTag = "";
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		// TODO Auto-generated method stub
	}

}
</span>

注意这块我作了改动,不需要申明

/* private MessageFragment messageFragment;
private ContactsFragment contactsFragment;
private NewsFragment newsFragment;
private SettingFragment settingFragment;*/
这些内容,因为Fragment的生成是通过BaseFragment.newInstance()来生成的,传进去Tag生成相应的Fragment。所有的Fragment,ContactsFragment、MessageFragment、NewsFragment、SettingFragment都继承自BaseFragment,通过BaseFragment里的newInstance()接口进行实例化对应的fragment。优点是方便管理,缺点么也有,因为java继承继承一个类,不能同时继承两个类。所以如ListFragment这些,就没法同时继承了。不过好在有listview这些,也妨碍不了我们做到同样的效果。

Activity里事件的入口是在onBottomPanelClick()监听点击了谁,然后:

setTabSelection(tag); //切换Fragment

headPanel.setMiddleTitle(tag);//切换标题

先切换Fragment再切换顶部栏的标题。setTabSelection()里直接调switchFragment(),在switchFragment函数里先判断标签是否一样,一样则意外着无需切换,否则的话就先把当前Fragment找到然后detach掉,之后进到attachFragment()函数里。在这里,先判断这个fragment是不是被detach掉的,如果是的话意味着之前曾被add过,所以只需attach就ok了。否则的话,意味着这是第一次,进行add.这里记录下Fragment的声明周期:

MessageFragment正常打开
Line 155: 01-04 11:50:46.688 E/MessageFragment( 2546): onAttach-----
Line 159: 01-04 11:50:46.688 E/MessageFragment( 2546): onCreate------
Line 161: 01-04 11:50:46.693 D/MessageFragment( 2546): onCreateView---->
Line 165: 01-04 11:50:46.694 E/MessageFragment( 2546): onActivityCreated-------
Line 169: 01-04 11:50:46.694 E/MessageFragment( 2546): onStart----->
Line 173: 01-04 11:50:46.694 E/MessageFragment( 2546): onresume---->
返回键退出:
Line 183: 01-04 11:52:26.506 E/MessageFragment( 2546): onpause
Line 259: 01-04 11:52:27.131 E/MessageFragment( 2546): onStop
Line 263: 01-04 11:52:27.132 E/MessageFragment( 2546): ondestoryView
Line 269: 01-04 11:52:27.134 E/MessageFragment( 2546): ondestory
Line 271: 01-04 11:52:27.135 D/MessageFragment( 2546): onDetach------

按home按键退出:
Line 97: 01-05 05:06:15.659 E/MessageFragment(18835): onpause
Line 215: 01-05 05:06:16.292 E/MessageFragment(18835): onStop
再次打开
Line 81: 01-05 05:07:02.408 E/MessageFragment(18835): onStart----->
Line 85: 01-05 05:07:02.408 E/MessageFragment(18835): onresume---->

通过detach的方式切换至其他Fragment:
Line 69: 01-04 11:53:33.381 E/MessageFragment( 2546): onpause
Line 73: 01-04 11:53:33.382 E/MessageFragment( 2546): onStop
Line 77: 01-04 11:53:33.382 E/MessageFragment( 2546): ondestoryView
再次切换过来:
Line 55: 01-04 11:54:59.462 D/MessageFragment( 2546): onCreateView---->
Line 59: 01-04 11:54:59.463 E/MessageFragment( 2546): onActivityCreated-------
Line 63: 01-04 11:54:59.463 E/MessageFragment( 2546): onStart----->
Line 67: 01-04 11:54:59.464 E/MessageFragment( 2546): onresume---->


四、适配器和MessageBean

本来要连数据库的,时间原因用个简单的MessageBean代替了。一个消息分联系人头像、名字、消息正文和时间四部分组成,封装到一个MessageBean里。

MessageBean.java

  1. <span style="font-family: Comic Sans MS; font-size: 18px;">package org.yanzi.bean; 
  2.  
  3. public class MessageBean { 
  4.     private int PhotoDrawableId; 
  5.     private String MessageName; 
  6.     private String MessageContent; 
  7.     private String MessageTime; 
  8.      
  9.     public MessageBean(){ 
  10.          
  11.     } 
  12.      
  13.     public MessageBean(int photoDrawableId, String messageName, 
  14.             String messageContent, String messageTime) { 
  15.         super(); 
  16.         PhotoDrawableId = photoDrawableId; 
  17.         MessageName = messageName; 
  18.         MessageContent = messageContent; 
  19.         MessageTime = messageTime; 
  20.     } 
  21.  
  22.     public int getPhotoDrawableId() { 
  23.         return PhotoDrawableId; 
  24.     } 
  25.     public void setPhotoDrawableId(int mPhotoDrawableId) { 
  26.         this.PhotoDrawableId = mPhotoDrawableId; 
  27.     } 
  28.     public String getMessageName() { 
  29.         return MessageName; 
  30.     } 
  31.     public void setMessageName(String messageName) { 
  32.         MessageName = messageName; 
  33.     } 
  34.     public String getMessageContent() { 
  35.         return MessageContent; 
  36.     } 
  37.     public void setMessageContent(String messageContent) { 
  38.         MessageContent = messageContent; 
  39.     } 
  40.     public String getMessageTime() { 
  41.         return MessageTime; 
  42.     } 
  43.     public void setMessageTime(String messageTime) { 
  44.         MessageTime = messageTime; 
  45.     } 
  46.     @Override 
  47.     public String toString() { 
  48.         return "MessageBean [mPhotoDrawableId=" + PhotoDrawableId 
  49.                 + ", MessageName=" + MessageName + ", MessageContent=" 
  50.                 + MessageContent + ", MessageTime=" + MessageTime + "]"
  51.     } 
  52.      
  53.      
  54.      
  55. </span> 
<span style="font-family:Comic Sans MS;font-size:18px;">package org.yanzi.bean;

public class MessageBean {
	private int PhotoDrawableId;
	private String MessageName;
	private String MessageContent;
	private String MessageTime;
	
	public MessageBean(){
		
	}
	
	public MessageBean(int photoDrawableId, String messageName,
			String messageContent, String messageTime) {
		super();
		PhotoDrawableId = photoDrawableId;
		MessageName = messageName;
		MessageContent = messageContent;
		MessageTime = messageTime;
	}

	public int getPhotoDrawableId() {
		return PhotoDrawableId;
	}
	public void setPhotoDrawableId(int mPhotoDrawableId) {
		this.PhotoDrawableId = mPhotoDrawableId;
	}
	public String getMessageName() {
		return MessageName;
	}
	public void setMessageName(String messageName) {
		MessageName = messageName;
	}
	public String getMessageContent() {
		return MessageContent;
	}
	public void setMessageContent(String messageContent) {
		MessageContent = messageContent;
	}
	public String getMessageTime() {
		return MessageTime;
	}
	public void setMessageTime(String messageTime) {
		MessageTime = messageTime;
	}
	@Override
	public String toString() {
		return "MessageBean [mPhotoDrawableId=" + PhotoDrawableId
				+ ", MessageName=" + MessageName + ", MessageContent="
				+ MessageContent + ", MessageTime=" + MessageTime + "]";
	}
	
	
	
}
</span>
然后就是MessageFragment的ListView里的适配器,MessageAdapter.java

  1. <span style="font-family: Comic Sans MS; font-size: 18px;">package org.yanzi.fragment.adapter; 
  2.  
  3. import java.util.List; 
  4.  
  5. import org.yanzi.bean.MessageBean; 
  6.  
  7. import com.example.fragmentproject.R; 
  8.  
  9. import android.content.Context; 
  10. import android.view.LayoutInflater; 
  11. import android.view.View; 
  12. import android.view.ViewGroup; 
  13. import android.widget.BaseAdapter; 
  14. import android.widget.ImageView; 
  15. import android.widget.TextView; 
  16.  
  17. public class MessageAdapter extends BaseAdapter { 
  18.     private List<MessageBean> mListMsgBean = null
  19.     private Context mContext; 
  20.     private LayoutInflater mInflater; 
  21.     public MessageAdapter(List<MessageBean> listMsgBean, Context context){ 
  22.         mListMsgBean = listMsgBean; 
  23.         mContext = context; 
  24.         mInflater = LayoutInflater.from(mContext); 
  25.     } 
  26.     @Override 
  27.     public int getCount() { 
  28.         // TODO Auto-generated method stub 
  29.         return mListMsgBean.size(); 
  30.     } 
  31.  
  32.     @Override 
  33.     public Object getItem(int position) { 
  34.         // TODO Auto-generated method stub 
  35.         return mListMsgBean.get(position); 
  36.     } 
  37.  
  38.     @Override 
  39.     public long getItemId(int position) { 
  40.         // TODO Auto-generated method stub 
  41.         return position; 
  42.     } 
  43.  
  44.     @Override 
  45.     public View getView(int position, View convertView, ViewGroup parent) { 
  46.         // TODO Auto-generated method stub 
  47.         View v = mInflater.inflate(R.layout.message_item_layout, null); 
  48.          
  49.         ImageView imageView = (ImageView) v.findViewById(R.id.img_msg_item); 
  50.         imageView.setImageResource(mListMsgBean.get(position).getPhotoDrawableId()); 
  51.          
  52.         TextView nameMsg = (TextView)v.findViewById(R.id.name_msg_item); 
  53.         nameMsg.setText(mListMsgBean.get(position).getMessageName()); 
  54.  
  55.         TextView contentMsg = (TextView)v.findViewById(R.id.content_msg_item); 
  56.         contentMsg.setText(mListMsgBean.get(position).getMessageContent()); 
  57.          
  58.         TextView timeMsg = (TextView)v.findViewById(R.id.time_msg_item); 
  59.         timeMsg.setText(mListMsgBean.get(position).getMessageTime()); 
  60.  
  61.         return v; 
  62.     } 
  63.  
  64. </span> 
<span style="font-family:Comic Sans MS;font-size:18px;">package org.yanzi.fragment.adapter;

import java.util.List;

import org.yanzi.bean.MessageBean;

import com.example.fragmentproject.R;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MessageAdapter extends BaseAdapter {
	private List<MessageBean> mListMsgBean = null;
	private Context mContext;
	private LayoutInflater mInflater;
	public MessageAdapter(List<MessageBean> listMsgBean, Context context){
		mListMsgBean = listMsgBean;
		mContext = context;
		mInflater = LayoutInflater.from(mContext);
	}
	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return mListMsgBean.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return mListMsgBean.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO Auto-generated method stub
		View v = mInflater.inflate(R.layout.message_item_layout, null);
		
		ImageView imageView = (ImageView) v.findViewById(R.id.img_msg_item);
		imageView.setImageResource(mListMsgBean.get(position).getPhotoDrawableId());
		
		TextView nameMsg = (TextView)v.findViewById(R.id.name_msg_item);
		nameMsg.setText(mListMsgBean.get(position).getMessageName());

		TextView contentMsg = (TextView)v.findViewById(R.id.content_msg_item);
		contentMsg.setText(mListMsgBean.get(position).getMessageContent());
		
		TextView timeMsg = (TextView)v.findViewById(R.id.time_msg_item);
		timeMsg.setText(mListMsgBean.get(position).getMessageTime());

		return v;
	}

}
</span>
因为是示例,getView里没用ViewHolder。
最后是MessageFragment里通过对listview设置适配器,将MessageBean作为信息的提供者也填充到适配器里。

MessageFragment.java代码:

  1. <span style="font-family: Comic Sans MS; font-size: 18px;">package org.yanzi.fragment; 
  2.  
  3. import java.util.ArrayList; 
  4. import java.util.List; 
  5.  
  6. import org.yanzi.activity.MainActivity; 
  7. import org.yanzi.bean.MessageBean; 
  8. import org.yanzi.constant.Constant; 
  9. import org.yanzi.fragment.adapter.MessageAdapter; 
  10.  
  11. import android.app.Activity; 
  12. import android.os.Bundle; 
  13. import android.util.Log; 
  14. import android.view.LayoutInflater; 
  15. import android.view.View; 
  16. import android.view.ViewGroup; 
  17. import android.widget.AdapterView; 
  18. import android.widget.Toast; 
  19. import android.widget.AdapterView.OnItemClickListener; 
  20. import android.widget.ListView; 
  21.  
  22. import com.example.fragmentproject.R; 
  23.  
  24. public class MessageFragment extends BaseFragment { 
  25.  
  26.     private static final String TAG = "MessageFragment"
  27.     private MainActivity mMainActivity ; 
  28.     private ListView mListView; 
  29.     private MessageAdapter mMsgAdapter; 
  30.     private List<MessageBean> mMsgBean = new ArrayList<MessageBean>(); 
  31.     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
  32.             Bundle savedInstanceState) { 
  33.         View messageLayout = inflater.inflate(R.layout.message_layout, 
  34.                 container, false); 
  35.         Log.d(TAG, "onCreateView---->"); 
  36.         mMainActivity = (MainActivity) getActivity(); 
  37.         mFragmentManager = getActivity().getFragmentManager(); 
  38.         mListView = (ListView)messageLayout.findViewById(R.id.listview_message); 
  39.         mMsgAdapter = new MessageAdapter(mMsgBean, mMainActivity); 
  40.         mListView.setAdapter(mMsgAdapter); 
  41.         mListView.setOnItemClickListener(new OnItemClickListener() { 
  42.  
  43.             @Override 
  44.             public void onItemClick(AdapterView<?> parent, View view, 
  45.                     int position, long id) { 
  46.                 // TODO Auto-generated method stub 
  47.                 Toast.makeText(mMainActivity, mMsgBean.get(position).toString(), 
  48.                         Toast.LENGTH_SHORT).show(); 
  49.             } 
  50.  
  51.         }); 
  52.         return messageLayout; 
  53.     } 
  54.  
  55.  
  56.     @Override 
  57.     public void onAttach(Activity activity) { 
  58.         // TODO Auto-generated method stub 
  59.         super.onAttach(activity); 
  60.         Log.e(TAG, "onAttach-----"); 
  61.  
  62.     } 
  63.     @Override 
  64.     public void onCreate(Bundle savedInstanceState) { 
  65.         // TODO Auto-generated method stub 
  66.         super.onCreate(savedInstanceState); 
  67.         Log.e(TAG, "onCreate------"); 
  68.         mMsgBean.add(new MessageBean(R.drawable.ic_photo_1, "张三", "吃饭没?", "昨天")); 
  69.         mMsgBean.add(new MessageBean(R.drawable.ic_photo_2, "李四", "哈哈", "昨天")); 
  70.         mMsgBean.add(new MessageBean(R.drawable.ic_photo_3, "小明", "吃饭没?", "昨天")); 
  71.         mMsgBean.add(new MessageBean(R.drawable.ic_photo_4, "王五", "吃饭没?", "昨天")); 
  72.         mMsgBean.add(new MessageBean(R.drawable.ic_photo_5, "Jack", "吃饭没?", "昨天")); 
  73.         mMsgBean.add(new MessageBean(R.drawable.ic_photo_6, "Jone", "吃饭没?", "昨天")); 
  74.         mMsgBean.add(new MessageBean(R.drawable.ic_photo_7, "Jone", "吃饭没?", "昨天")); 
  75.         mMsgBean.add(new MessageBean(R.drawable.ic_photo_8, "Jone", "吃饭没?", "昨天")); 
  76.         mMsgBean.add(new MessageBean(R.drawable.ic_photo_9, "Jone", "吃饭没?", "昨天")); 
  77.     } 
  78.  
  79.     @Override 
  80.     public void onActivityCreated(Bundle savedInstanceState) { 
  81.         // TODO Auto-generated method stub 
  82.         super.onActivityCreated(savedInstanceState); 
  83.         Log.e(TAG, "onActivityCreated-------"); 
  84.     } 
  85.  
  86.     @Override 
  87.     public void onStart() { 
  88.         // TODO Auto-generated method stub 
  89.         super.onStart(); 
  90.  
  91.         Log.e(TAG, "onStart----->"); 
  92.     } 
  93.  
  94.     @Override 
  95.     public void onResume() { 
  96.         // TODO Auto-generated method stub 
  97.         super.onResume(); 
  98.         Log.e(TAG, "onresume---->"); 
  99.         MainActivity.currFragTag = Constant.FRAGMENT_FLAG_MESSAGE; 
  100.     } 
  101.  
  102.     @Override 
  103.     public void onPause() { 
  104.         // TODO Auto-generated method stub 
  105.         super.onPause(); 
  106.         Log.e(TAG, "onpause"); 
  107.     } 
  108.  
  109.     @Override 
  110.     public void onStop() { 
  111.         // TODO Auto-generated method stub 
  112.         super.onStop(); 
  113.         Log.e(TAG, "onStop"); 
  114.     } 
  115.  
  116.     @Override 
  117.     public void onDestroyView() { 
  118.         // TODO Auto-generated method stub 
  119.         super.onDestroyView(); 
  120.         Log.e(TAG, "ondestoryView"); 
  121.     } 
  122.     @Override 
  123.     public void onDestroy() { 
  124.         // TODO Auto-generated method stub 
  125.         super.onDestroy(); 
  126.         Log.e(TAG, "ondestory"); 
  127.     } 
  128.  
  129.     @Override 
  130.     public void onDetach() { 
  131.         // TODO Auto-generated method stub 
  132.         super.onDetach(); 
  133.         Log.d(TAG, "onDetach------"); 
  134.  
  135.     } 
  136.  
  137.  
  138.  
  139. </span> 
<span style="font-family:Comic Sans MS;font-size:18px;">package org.yanzi.fragment;

import java.util.ArrayList;
import java.util.List;

import org.yanzi.activity.MainActivity;
import org.yanzi.bean.MessageBean;
import org.yanzi.constant.Constant;
import org.yanzi.fragment.adapter.MessageAdapter;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;

import com.example.fragmentproject.R;

public class MessageFragment extends BaseFragment {

	private static final String TAG = "MessageFragment";
	private MainActivity mMainActivity ;
	private ListView mListView;
	private MessageAdapter mMsgAdapter;
	private List<MessageBean> mMsgBean = new ArrayList<MessageBean>();
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View messageLayout = inflater.inflate(R.layout.message_layout,
				container, false);
		Log.d(TAG, "onCreateView---->");
		mMainActivity = (MainActivity) getActivity();
		mFragmentManager = getActivity().getFragmentManager();
		mListView = (ListView)messageLayout.findViewById(R.id.listview_message);
		mMsgAdapter = new MessageAdapter(mMsgBean, mMainActivity);
		mListView.setAdapter(mMsgAdapter);
		mListView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view,
					int position, long id) {
				// TODO Auto-generated method stub
				Toast.makeText(mMainActivity, mMsgBean.get(position).toString(),
						Toast.LENGTH_SHORT).show();
			}

		});
		return messageLayout;
	}


	@Override
	public void onAttach(Activity activity) {
		// TODO Auto-generated method stub
		super.onAttach(activity);
		Log.e(TAG, "onAttach-----");

	}
	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		Log.e(TAG, "onCreate------");
		mMsgBean.add(new MessageBean(R.drawable.ic_photo_1, "张三", "吃饭没?", "昨天"));
		mMsgBean.add(new MessageBean(R.drawable.ic_photo_2, "李四", "哈哈", "昨天"));
		mMsgBean.add(new MessageBean(R.drawable.ic_photo_3, "小明", "吃饭没?", "昨天"));
		mMsgBean.add(new MessageBean(R.drawable.ic_photo_4, "王五", "吃饭没?", "昨天"));
		mMsgBean.add(new MessageBean(R.drawable.ic_photo_5, "Jack", "吃饭没?", "昨天"));
		mMsgBean.add(new MessageBean(R.drawable.ic_photo_6, "Jone", "吃饭没?", "昨天"));
		mMsgBean.add(new MessageBean(R.drawable.ic_photo_7, "Jone", "吃饭没?", "昨天"));
		mMsgBean.add(new MessageBean(R.drawable.ic_photo_8, "Jone", "吃饭没?", "昨天"));
		mMsgBean.add(new MessageBean(R.drawable.ic_photo_9, "Jone", "吃饭没?", "昨天"));
	}

	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onActivityCreated(savedInstanceState);
		Log.e(TAG, "onActivityCreated-------");
	}

	@Override
	public void onStart() {
		// TODO Auto-generated method stub
		super.onStart();

		Log.e(TAG, "onStart----->");
	}

	@Override
	public void onResume() {
		// TODO Auto-generated method stub
		super.onResume();
		Log.e(TAG, "onresume---->");
		MainActivity.currFragTag = Constant.FRAGMENT_FLAG_MESSAGE;
	}

	@Override
	public void onPause() {
		// TODO Auto-generated method stub
		super.onPause();
		Log.e(TAG, "onpause");
	}

	@Override
	public void onStop() {
		// TODO Auto-generated method stub
		super.onStop();
		Log.e(TAG, "onStop");
	}

	@Override
	public void onDestroyView() {
		// TODO Auto-generated method stub
		super.onDestroyView();
		Log.e(TAG, "ondestoryView");
	}
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		super.onDestroy();
		Log.e(TAG, "ondestory");
	}

	@Override
	public void onDetach() {
		// TODO Auto-generated method stub
		super.onDetach();
		Log.d(TAG, "onDetach------");

	}



}
</span>
最后来看下效果吧,只有MessageFragment填充了数据:

     


横屏情况下:


--------------本文系原创,转载请注明作者yanzi1225627

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值