天天看點

如何建構一個類似于安卓QQ的頁面架構(低耦合)

該架構的優勢:

1)、每個頁面有單獨的xml布局檔案,降低各個頁面之間耦合性,便于各個頁面的分開操作。

2)、共用一個activity便于資料傳遞。

3)、結構清晰。

4)、便于擴充。

結構圖:

如何建構一個類似于安卓QQ的頁面架構(低耦合)

1、檔案清單:

MainActivity:Activity,對應布局檔案:activity_main.xml---一個空的FrameLayout,主要作為容器,容納首頁面的内容和側頁面的内容

ContentFragment:首頁面Fragment,對應布局檔案:fragment_content.xml------包括一個容納三個首頁面内容的PagerView和三個首頁面的 首頁、購物車和設定的RadioGroup

LeftFragment:側頁面Fragment,對應布局檔案:fragment_leftmenu.xml-----側頁面的内容

BaseFragment:以上ContentFragment和LeftFragment的基類,繼承自Fragment類

HomePager:home頁面,對應布局檔案:pager_homepager.xml-----首頁的内容

CartPager:cart頁面,對應布局檔案:pager_cartpager.xml-----購物車的内容

SetPager:set頁面,對應布局檔案:pager_setpager.xml-----設定的内容

BasePager:以上HomePager、CartPager和SetPager的基類,對應布局檔案pager_basepager----以上三個頁面都有的側頁面打開按鈕、标題、分享按鈕以及容納以上三個頁面的FrameLayout

2、詳細介紹

2.1、MainActivity.java

public class MainActivity extends SlidingFragmentActivity {

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);// 設定首頁面沒有标題欄
		setContentView(R.layout.activity_main);
		setLeftMenu();//
	}

	/*
	 * 使用第三方架構SlidingMenu實作側滑欄:使用方式:import SlipMenu,然後設定為library,引用即可
	 */
	private void setLeftMenu() {
		// TODO Auto-generated method stub
		setBehindContentView(R.layout.fragment_leftmenu_container);// 設定側滑欄的布局檔案,是一個容器
		SlidingMenu slidingMenu = getSlidingMenu();// 拿取側滑欄對象

		slidingMenu.setMode(SlidingMenu.LEFT);// 設定側滑欄的模式為左滑動。(當然可以設定為右滑動、左右一起滑動等)
		slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_MARGIN);// 設定手指在螢幕最左邊線時滑動才可以劃出側邊欄(可以設定為不允許劃出、全屏都可以操作等)
		// 設定漸入漸出效果的值
		slidingMenu.setFadeDegree(0.35f);
		int width = getWindowManager().getDefaultDisplay().getWidth();
		slidingMenu.setBehindOffset(width * 2 / 5);// 設定側邊欄劃開之後,左邊剩下的距離
		initFragment();
	}

	// 初始化Fragment
	private void initFragment() {
		// TODO Auto-generated method stub
		FragmentManager fm = getSupportFragmentManager();// 拿取FragmentManager
		/*
		 * 開啟事務,加載需要的“容器加載”
		 */
		FragmentTransaction ft = fm.beginTransaction();
		ft.replace(R.id.fl_main, new ContentFragment());// 把fl_main的内容替換成ContentFragment裡面的内容
		ft.replace(R.id.ll_leftmenu_container, new LeftFragment());
		ft.commit();
	}

	// 拿取側邊欄對象。該方法供home用
	public LeftFragment getLeftFragment() {
		FragmentManager supportFragmentManager = getSupportFragmentManager();
		LeftFragment leftFragment = (LeftFragment) supportFragmentManager
				.findFragmentById(R.id.ll_leftmenu_container);
		return leftFragment;
	}
}
           

2.2、BaseFragment.java

/*
 * 對Framgent進行簡單的封裝,在此Framgent中:
 * 1、拿取調用的Activity對象,便于繼承的子類進行操作。2、聲明兩個方法initView()
 * 和initData()。分别放在onCreateView()和onActivityCreated(),子類可以直接調用,不用再次引用。
 */
public abstract class BaseFragment extends Fragment {
	public Activity mActivity;

	/*
	 * fragment建立:在fragment建立後,拿到MainActivity對象,抽象為基類,友善後期使用,
	 */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mActivity = getActivity();
	}

	/*
	 * fragmeng加載視圖:加載視圖也要抽象為基類。子類直接重載initView()即可初始化視圖view
	 */

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View view = initView();
		return view;
	}

	/*
	 * 對應activity建立成功:當MainActivity建立成功,初始化首頁面資料(子類的資料初始化)
	 */
	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onActivityCreated(savedInstanceState);
		initData();
	}

	public abstract View initView();

	public abstract void initData();

}
           

2.3、ContentFragment.java

public class ContentFragment extends BaseFragment {
	private static final String TAG = "ContentFragment";
	@ViewInject(R.id.vp_content_pager)
	ViewPager vp_content;
	@ViewInject(R.id.rg_content)
	RadioGroup rg_content;// 三個按鈕
	@ViewInject(R.id.rb_home)
	RadioButton rb_home;
	@ViewInject(R.id.rb_cart)
	RadioButton rb_cart;
	@ViewInject(R.id.rb_set)
	RadioButton rb_set;
	private List<BasePager> pagers;// 三個首頁面的臨時存放位置,便于生成pagerview

	/*
	 * 檢視基類,可以知道:該視圖傳回給View onCreateView(LayoutInflater inflater, ViewGroup
	 * container, Bundle savedInstanceState) ,是以可以建立視圖
	 */

	@Override
	public View initView() {
		// TODO Auto-generated method stub
		View view = View.inflate(mActivity, R.layout.fragment_content, null);
		ViewUtils.inject(this, view);// 注入

		return view;
	}

	@Override
	public void initData() {
		// set default btn
		rg_content.check(R.id.rb_home);// 設定預設顯示頁面:home頁面
		rg_content.setOnCheckedChangeListener(new MyOnCheckedChangeListener());// 監聽三個按鈕
		// 初始化三個首頁面
		initPager();
	}

	/*
	 * 将三個首頁面放到PagerView中,禁止滑動事件,與單選的 RadioGroup點選按鈕綁定,即可以實作首頁面(首頁、購物車、設定)的構圖。
	 */
	private void initPager() {
		pagers = new ArrayList<BasePager>();
		pagers.add(new HomePager(mActivity));// 詳細解釋參看HomePager,一下兩個頁面同理,不再解釋
		pagers.add(new CartPager(mActivity));
		pagers.add(new SetPager(mActivity));
		vp_content.setAdapter(new MyPagerAdapter());

		pagers.get(0).initData();// 預設加載首頁的資料

	}

	/*
	 * 為pagerview構造視圖
	 */
	class MyPagerAdapter extends PagerAdapter {

		@Override
		public int getCount() {
			// TODO Auto-generated method stub
			return pagers.size();
		}

		@Override
		public boolean isViewFromObject(View arg0, Object arg1) {
			// TODO Auto-generated method stub
			return arg0 == arg1;
		}

		@Override
		public Object instantiateItem(ViewGroup container, int position) {
			BasePager basePager = pagers.get(position);
			View view = basePager.mView;
			container.addView(view);
			return view;
		}

		@Override
		public void destroyItem(ViewGroup container, int position, Object object) {
			container.removeView((View) object);
		}

	}

	class MyOnCheckedChangeListener implements OnCheckedChangeListener {

		@Override
		public void onCheckedChanged(RadioGroup group, int checkedId) {

			switch (checkedId) {
			case R.id.rb_home:
				vp_content.setCurrentItem(0, false);
				pagers.get(0).initData();
				ToastUtils.showMsg(mActivity, "init home data...");

				break;
			case R.id.rb_cart:
				vp_content.setCurrentItem(1, false);
				pagers.get(1).initData();
				ToastUtils.showMsg(mActivity, "init cart data...");

				break;
			case R.id.rb_set:
				vp_content.setCurrentItem(2, false);
				pagers.get(2).initData();
				ToastUtils.showMsg(mActivity, "init set data...");

				break;

			default:
				break;
			}
		}

	}
}
           

2.4、LeftFragment.java

public class LeftFragment extends BaseFragment {
	private static final String TAG = "LeftFragment";
	private TextView tv_leftmenu_data;
	private Button btn_leftmenu_data;

	@Override
	public View initView() {
		View view = View.inflate(mActivity, R.layout.fragment_leftmenu, null);
		tv_leftmenu_data = (TextView) view.findViewById(R.id.tv_leftmenu_data);
		btn_leftmenu_data = (Button) view.findViewById(R.id.btn_leftmenu_data);
		btn_leftmenu_data.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				ToastUtils.showMsg(mActivity, "側頁面按鈕,點選文字有效!開始傳值!");
				SetPager.setDatafromLeftFagment(btn_leftmenu_data.getText()
						.toString());
			}
		});
		return view;
	}

	@Override
	public void initData() {
		// TODO Auto-generated method stub

	}

	public void setDataFromHome(String str) {
		Log.d(TAG, "傳值過來了" + str);
		tv_leftmenu_data.setText(str);
	}
}
           

2.5、BasePager.java

/*
 * 對三個首頁面功能的抽取,形成一個BasePager頁面:拿取MainActivity。初始化視圖:标題欄的布局實作以及全局的事件的設定等
 */
public abstract class BasePager {

	public TextView tv_title;// 标題
	public ImageView iv_menu;// 打開側邊欄的按鈕
	public ImageView iv_share;// 分享按鈕
	public FrameLayout fl_content;// 首頁面内容

	public View mView;// view視圖:這個視圖會在子類中頻繁使用
	public Activity mActivity;// MainActivity

	public BasePager(Activity mActivity) {
		this.mActivity = mActivity;
		initView();

	}

	public void initView() {
		this.mView = View.inflate(mActivity, R.layout.pager_basepager, null);
		tv_title = (TextView) mView.findViewById(R.id.tv_basepager_title);
		iv_menu = (ImageView) mView.findViewById(R.id.iv_basepager_menu);
		iv_share = (ImageView) mView.findViewById(R.id.iv_basepager_share);
		fl_content = (FrameLayout) mView
				.findViewById(R.id.fl_basepager_content);
	}

	public void initData() {
		iv_menu.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				// MainActivity mainActivity = (MainActivity) mActivity;
				// SlidingMenu slidingMenu = mainActivity.getSlidingMenu();
				// slidingMenu.toggle();// 打開或者關閉側邊欄
				SlidingMenuUtils.toggle(mActivity);// 抽離成工具類
			}
		});
		iv_share.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				ToastUtils.showMsg(mActivity, "share me hahha");// 此處調用分享的接口
			}
		});
	}
}
           

2.6 HomePager.java

public class HomePager extends BasePager {
	private Button btn_home;
	private static TextView tv_home_temp;

	public HomePager(Activity mActivity) {
		super(mActivity);
		// TODO Auto-generated constructor stub

	}

	@Override
	public void initView() {
		// TODO Auto-generated method stub
		super.initView();
		tv_title.setText("home");
		View view = View.inflate(mActivity, R.layout.pager_homepager, null);// 拿取home對應的布局檔案
		tv_home_temp = (TextView) view.findViewById(R.id.tv_home_temp);
		btn_home = (Button) view.findViewById(R.id.btn_home);
		fl_content.addView(view);// 将拿到的home的布局檔案放到fl_content,實作嵌套:既有原有的側邊欄按鈕、标題、分享按鈕,又可以實作每個頁面的單獨布局

	}

	@Override
	public void initData() {
		super.initData();
		btn_home.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				MainActivity mainActivity = (MainActivity) mActivity;
				LeftFragment leftFragment = mainActivity.getLeftFragment();
				leftFragment.setDataFromHome(btn_home.getText().toString());
				// 傳值結束,打開側邊欄
				// SlidingMenu slidingMenu = mainActivity.getSlidingMenu();
				// slidingMenu.toggle();// 打開或者關閉側邊欄
				SlidingMenuUtils.toggle(mActivity);
			}
		});
	}

	/*
	 * 接收從cart傳過來的臨時參數,修改TextView裡面的值
	 */
	public static void setDatafromCart(String str) {
		tv_home_temp.setText(str);
	}
}
           

示範項目下載下傳: http://download.csdn.net/detail/wgyscsf/9456082 未完,詳細分析稍後補充