碎片fragment

碎片(Fragment)是一种可以嵌入在活动当中的 UI 片段,它能让程序更加合理和充分地利用大屏幕的空间,因而在平板上应用的非常广泛。虽然碎片对你来说应该是个全新的概念, 但我相信你学习起来应该毫不费力, 因为它和活动实在是太像了, 同样都能包含布局,同样都有自己的生命周期。你甚至可以将碎片理解成一个迷你型的活动,虽然这个迷你型的活动有可能和普通的活动是一样大的。

那么究竟要如何使用碎片才能充分地利用平板屏幕的空间呢?想象我们正在开发一个新闻应用,其中一个界面使用 ListView 展示了一组新闻的标题,当点击了其中一个标题,就打开另一个界面显示新闻的详细内容。如果是在手机中设计,我们可以将新闻标题列表放在一个活动中,将新闻的详细内容放在另一个活动中


可是如果在平板上也这么设计,那么新闻标题列表将会被拉长至填充满整个平板的屏幕, 而新闻的标题一般都不会太长, 这样将会导致界面上有大量的空白区域




因此,更好的设计方案是将新闻标题列表界面和新闻详细内容界面分别放在两个碎片中,然后在同一个活动里引入这两个碎片,这样就可以将屏幕空间充分地利用起来了





现在启动这个平板模拟器




这里我们准备先写一个最简单的碎片示例来练练手,在一个活动当中添加两个碎片,并让这两个碎片平分活动空间。新建一个左侧碎片布局 left_fragment.xml,

<?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" >

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button" />

</LinearLayout>

这个布局非常简单,只放置了一个按钮,并让它水平居中显示。然后新建右侧碎片布局right_fragment.xml

<?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:background="#00ff00"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/right1" />

</LinearLayout>

可以看到,我们将这个布局的背景色设置成绿色,并放置了一个 TextView 用于显示一段文本。接着新建一个 LeftFragment 类,继承自 Fragment。注意,这里可能会有两个不同包下的 Fragment 供你选择,建议使用 android.app.Fragment,因为我们的程序是面向Android 4.0以上系统的, 另一个包下的Fragment主要是用于兼容低版本的Android系统

public class LeftFragment extends Fragment{

	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		View view=inflater.inflate(R.layout.left_fragment, container,false);
		return view;
	}
}

这里仅仅是重写了 Fragment 的 onCreateView()方法,然后在这个方法中通过LayoutInflater 的 inflate()方法将刚才定义的 left_fragment 布局动态加载进来, 整个方法简单明了。接着我们用同样的方法再新建一个 RightFragment,


public class RightFragment extends Fragment{

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		View view=inflater.inflate(R.layout.right_fragment, container, false);
		return view;
	}
}
基 本 上 代 码 都 是 相 同 的 , 相 信 已 经 没 有 必 要 再 做 什 么 解 释 了 。 接 下 来 修 改activity_main.xml 中的代码



动态添加碎片

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:background="#ffff00"
  android:orientation="vertical" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:textSize="20sp"
            android:text="This is another right fragment"
         />
</LinearLayout>
这个布局文件的代码和 right_fragment.xml 中的代码基本相同,只是将背景色改成了黄色,并将显示的文字改了改。然后新建 AnotherRightFragment 作为另一个右侧碎片
public class AnotherRightFragment extends Fragment {
@Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
       View view = inflater.inflate(R.layout.another_right_fragment, container, false);
       return view;
  }
}

代 码 同 样 非 常 简 单 , 在 onCreateView() 方 法 中 加 载 了 刚 刚 创 建 的another_right_fragment 布局。这样我们就准备好了另一个碎片,接下来看一下如何将它动态地添加到活动当中。修改 activity_main.xml,


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent">
   <fragment
          android:id="@+id/left_fragment"
          android:name="com.example.fragmenttest.LeftFragment"
          android:layout_width="0dp"
          android:layout_height="match_parent"
          android:layout_weight="1" />
    <FrameLayout
          android:id="@+id/right_layout"
          android:layout_width="0dp"
          android:layout_height="match_parent"
          android:layout_weight="1" >
    <fragment
          android:id="@+id/right_fragment"
          android:name="com.example.fragmenttest.RightFragment"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />
    </FrameLayout>
</LinearLayout>

可以看到,现在将右侧碎片放在了一个 FrameLayout 中,还记得这个布局吗?在上一章中我们学过,这是 Android 中最简单的一种布局,它没有任何的定位方式,所有的控件都会摆放在布局的左上角。由于这里仅需要在布局里放入一个碎片,因此非常适合使用FrameLayout。之后我们将在代码中替换 FrameLayout 里的内容,从而实现动态添加碎片的功能。修改 MainActivity 中的代码

public class MainActivity extends Activity implements OnClickListener {
       @Override
         protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          Button button = (Button) findViewById(R.id.button);
          button.setOnClickListener(this);
      }
       @Override
          public void onClick(View v) {
           switch (v.getId()) {
          case R.id.button:
            AnotherRightFragment fragment = new AnotherRightFragment();
            FragmentManager fragmentManager = getFragmentManager();
            FragmentTransaction transaction = fragmentManager. beginTransaction();
            transaction.replace(R.id.right_layout, fragment);
            transaction.commit();
             break;
             default:
             break;
           }
      }
}



我们成功实现了向活动中动态添加碎片的功能,不过你尝试一下就会发现,通过点击按钮添加了一个碎片之后,这时按下 Back 键程序就会直接退出。如果这里我们想模仿类似于返回栈的效果,按下 Back 键可以回到上一个碎片,FragmentTransaction 中提供了一个 addToBackStack()方法,可以
用于将一个事务添加到返回栈中,修改 MainActivity 中的代码

public class MainActivity extends Activity implements OnClickListener {
⋯⋯
@Override
public void onClick(View v) {
  switch (v.getId()) {
     case R.id.button:
        AnotherRightFragment fragment = new AnotherRightFragment();
        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction transaction = fragmentManager. beginTransaction();
        transaction.replace(R.id.right_layout, fragment);
        transaction.addToBackStack(null);
        transaction.commit();
      break;
      default:
       break;
       }
    }
}



这里我们在事务提交之前调用了FragmentTransaction的addToBackStack()方法,它可以接收一个名字用于描述返回栈的状态,一般传入 null 即可。现在重新运行程序,并
点击按钮将 AnotherRightFragment 添加到活动中,然后按下 Back 键,你会发现程序并没有退出,而是回到了 RightFragment 界面,再次按下 Back 键程序才会退出



public class RightFragment extends Fragment {
     public static final String TAG = "RightFragment";
      @Override
          public void onAttach(Activity activity) {
          super.onAttach(activity);
          Log.d(TAG, "onAttach");
      }
      @Override
          public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          Log.d(TAG, "onCreate");
      }
      @Override
          public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
          Log.d(TAG, "onCreateView");
          View view = inflater.inflate(R.layout.right_fragment, container, false);
           return view;
      }
      @Override
          public void onActivityCreated(Bundle savedInstanceState) {
          super.onActivityCreated(savedInstanceState);
          Log.d(TAG, "onActivityCreated");
      }
     @Override
          public void onStart() {
          super.onStart();
          Log.d(TAG, "onStart");
      }
     @Override
         public void onResume() {
        super.onResume();
         Log.d(TAG, "onResume");
      }
     @Override
          public void onPause() {
         super.onPause();
         Log.d(TAG, "onPause");
     }
     @Override
         public void onStop() {
         super.onStop();
         Log.d(TAG, "onStop");
      }
     @Override
         public void onDestroyView() {
         super.onDestroyView();
         Log.d(TAG, "onDestroyView");
     }
     @Override
         public void onDestroy() {
         super.onDestroy();
         Log.d(TAG, "onDestroy");
     }
     @Override
         public void onDetach() {
         super.onDetach();
        Log.d(TAG, "onDetach");
   }
}




当 RightFragment 第一次被加载到屏幕上时,会依次执行 onAttach()、onCreate()、onCreateView()、onActivityCreated()、onStart()和 onResume()方法。然后点击 LeftFragment 中的按钮,


由于 AnotherRightFragment 替换了 RightFragment,此时的 RightFragment 进入了停止状态,因此 onPause()、onStop()和 onDestroyView()方法会得到执行。当然如果在替换的时候没有调用 addToBackStack()方法,此时的 RightFragment 就会进入销毁状态,onDestroy()和 onDetach()方法就会得到执行接着按下 Back 键RightFragment 会重新回到屏幕



由于 RightFragment 重新回到了运行状态,因此 onActivityCreated()、onStart()和 onResume()方法会得到执行。注意此时 onCreate()和 onCreateView()方法并不会执
行,因为我们借助了 addToBackStack()方法使得 RightFragment 和它的视图并没有销毁。再次按下 Back 键退出程序


会执行 onPause()、onStop()、onDestroyView()、onDestroy()和 onDetach()方法,最终将活动和碎片一起销毁



fragment与activity:



public void onClick(View arg0) {
        if (arg0.getId()==R.id.send_data_btn) {
            LeftFragment fragment = new LeftFragment();
            Bundle bundle = new Bundle();
            bundle.putString("order", "带兵攻打岛国");
            fragment.setArguments(bundle);
            FragmentManager fragmentManager = getFragmentManager();
            //开始Fragment事务
            FragmentTransaction fTransaction = fragmentManager.beginTransaction();
            //将Fragment添加到事务中,并指定一个TAG 
            fTransaction.add(fragment, "179521");
            //提交Fragment事务
            fTransaction.commit();
        }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值