您的位置:首页 > 移动开发 > Android开发

Android四大控件之Fragment的使用

2016-04-20 10:17 453 查看
Hi,众猿们,今天和大家讲讲Fragment(碎片)的使用。

先看碎片的定义,碎片是一种可以嵌入到活动中的UI片段,它可以让程序更合理和充分的利用大屏的空间,也就是说,碎片是一种可以兼顾手机和平板设备的技术,碎片的生命周期和活动非常相似,但碎片是要依赖于活动的,因此它又比活动多出了如下几个生命周期的方法(这些方法名什么时候被调用,一看方法名就应该知道了):

onAttach():当碎片与活动关联的时候被调用

onCreateView():

onActivityCreated():

onDestoryView():

onDetach():

碎片的生命周期图为(官方文档上貌似没有这张图,本猿猿就在其它书上盗了一张了):



通常在创建自定义碎片时,我们需要重写onCreateView方法以返回碎片的界面,重写onCreated方法以保存上下文对象,重写onActivityCreated方法以初始化界面数据,因此我们可以对碎片进行包装,定义一个基类的碎片(推荐使用android.support.v4.app包下的碎片对象):

public abstract class BaseFragment  extends Fragment {
protected Activity mActivity;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = getActivity();
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return initView(inflater, container);
}
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
}

protected void initData() {
}
protected abstract View initView(LayoutInflater inflater, ViewGroup container);
}


现在碎片已不仅仅是兼顾平板设备了,随着APP的界面越来越复杂,现在活动基本已经把管理界面的工作交给了碎片, 下面本猿猿就写一个基本的UI框架吧(老猿们勿笑呀):

其运行效果截图如下:





其项目包结构如下:

要理解这个项目,众猿猿们要对ViewPager控件和SlidingMenu开源项目有所了解,下面贴出几个主要类的源码吧:

MainActivity类的源码:

/**
*
* 注意:该类需要继承自SlidingFragmentActivity,这样以便于用Fragment来管理其侧边栏
*/
public class MainActivity extends SlidingFragmentActivity {

public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

//其布局会交由一个Fragment来管理
setContentView(R.layout.fgm_main);
//设置侧边栏的布局,会交由一个Fragment管理
setBehindContentView(R.layout.fgm_left);

//设置
SlidingMenu slidingMenu = getSlidingMenu();
slidingMenu = super.getSlidingMenu();
slidingMenu.setMode(SlidingMenu.LEFT);
slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
slidingMenu.setBehindOffset(160);
slidingMenu.setFadeEnabled(true);
slidingMenu.setFadeDegree(1);

initFragment();
}

private void initFragment() {
//获取Fragment对象的管理器并启动Fragment事务,学过数据库的猿猿对事务应该很清楚
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.fgm_left, new LeftFragment());
transaction.replace(R.id.fgm_content, new ContentFragment());
transaction.commit();
}
}


BasePager的源码为:

public abstract class BasePager {
protected Activity mActivity;
//保存该页面的根布局,ViewPager对象会用到它
public View mRootView;
public BasePager(Activity activity){
mActivity = activity;
mRootView = initView();
}
protected abstract View initView();
}


NewsPager的源码为:

public class NewsPager extends BasePager{

public NewsPager(Activity activity) {
super(activity);
}
/**
* 返回其布局文件,其布局中只有一个文本框
*/
@Override
protected View initView() {
return View.inflate(mActivity, R.layout.pager_news, null);
}
}


ContactsPager和DynamicsPager的源码就不贴出来了,其布局文件和源码与NewsPager相似,都很简单。

ContentFragment的源码为:

public class ContentFragment extends BaseFragment{
NoScrollViewPager viewPager;
List<BasePager> pagers = new ArrayList<BasePager>();
RadioGroup mRadioGroup;

@Override
protected View initView(LayoutInflater inflater, ViewGroup container) {
View view = inflater.inflate(R.layout.content, container, false);
viewPager = (NoScrollViewPager) view.findViewById(R.id.viewPager);
mRadioGroup = (RadioGroup) view.findViewById(R.id.bottom_tabs);
mRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch(checkedId){
case R.id.rb_news:
//设置viewpager切换时无动画
viewPager.setCurrentItem(0, false);
break;
case R.id.rb_contacts:
viewPager.setCurrentItem(1, false);
break;
case R.id.rb_dynamics:
viewPager.setCurrentItem(2, false);
break;
}
}
});
pagers.add(new NewsPager(mActivity));
pagers.add(new ContactsPager(mActivity));
pagers.add(new DynamicsPager(mActivity));

viewPager.setAdapter(new PagerAdapter() {
@Override
public int getCount() {
return pagers.size();
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
BasePager pager = pagers.get(position);
View view = pager.mRootView;
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position,
Object object) {
container.removeView((View)object);
}
});
return view;
}
}


其布局文件的源码为:

<?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" >
<lmz.fragmentexample.view.NoScrollViewPager
android:id="@+id/viewPager"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1">
</lmz.fragmentexample.view.NoScrollViewPager>
<RadioGroup
android:id="@+id/bottom_tabs"
android:layout_width="fill_parent"
android:layout_height="45dp"
android:orientation="horizontal"
android:background="#000">
<RadioButton
android:id="@+id/rb_news"
android:layout_width="0dp"
style="@style/bottom_tab_style"
android:layout_height="fill_parent"
android:text="消息"
android:layout_weight="1"/>
<RadioButton
android:id="@+id/rb_contacts"
android:layout_width="0dp"
style="@style/bottom_tab_style"
android:layout_height="fill_parent"
android:text="联系人"
android:layout_weight="1"/>
<RadioButton
android:id="@+id/rb_dynamics"
android:layout_width="0dp"
style="@style/bottom_tab_style"
android:layout_height="fill_parent"
android:layout_weight="1"
android:text="动态"/>
</RadioGroup>
</LinearLayout>


其它的代码和布局文件就不贴了,都挺简单的。在这个框架的基础上大家去修改和继承Pager的布局和源码,就可以搭建出界面丰富、功能复杂的App了。

关注微信公众号:猿聚于此,可获取更多文章。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: