天天看点

如何构建一个类似于安卓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 未完,详细分析稍后补充