您好,登錄后才能下訂單哦!
Fragment是一種可以嵌入在活動(dòng)當(dāng)中的UI 片段,它能讓程序更加合理和充分地利用大屏幕的空間,因而在平板上應(yīng)用的非常廣泛。擁有自己的生命周期和接收、處理用戶的事件。你可以動(dòng)態(tài)的添加、替換和移除某個(gè)Fragment。
Fragment使用非常廣泛,在此不介紹Fragment的生命周期,本例子將使用Fragment實(shí)現(xiàn)如下效果:
Message Friend Setting
圖一
Message Friend Setting
圖二
Message Friend Setting
圖三
底部的三個(gè)按鈕分別控制三個(gè)Fragment的展示,為方便說明,底部三個(gè)按鈕從左至右命名為Message、Friend、Setting,如上面三張圖所示。
圖三的上部是展現(xiàn)使用ViewPager的效果,加了一條藍(lán)色的指示器。
bottombar的布局文件
<?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="horizontal" > <RelativeLayout android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="1" > <Button android:id="@+id/btn_messaage" android:layout_width="40dp" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/message1_normal"/> </RelativeLayout> <RelativeLayout android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="1" > <Button android:id="@+id/btn_friend" android:layout_width="40dp" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/friend_normal" /> </RelativeLayout> <RelativeLayout android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="1" > <Button android:id="@+id/btn_setting" android:layout_width="40dp" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/setting_normal"/> </RelativeLayout> </LinearLayout>
topbar的布局文件
<?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="horizontal" > <RelativeLayout android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="1" > <Button android:id="@+id/btn_insect" android:layout_width="40dp" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/insect" /> </RelativeLayout> <RelativeLayout android:layout_width="0dp" android:layout_height="40dp" android:layout_weight="1" > <Button android:id="@+id/btn_menu" android:layout_width="40dp" android:layout_height="wrap_content" android:layout_centerInParent="true" android:background="@drawable/menu" /> </RelativeLayout> </LinearLayout>
MainActivity的布局文件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.jam.fragmentdemo.MainActivity" > <include android:id="@+id/bottombar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" layout="@layout/bottombar" /> <FrameLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/bottombar" /> </RelativeLayout>
由于message和friend兩個(gè)fragment的布局文件簡單,所以在此就不貼上來了。
SettingFragment的布局文件
<?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" > <include android:layout_width="match_parent" android:layout_height="wrap_content" layout="@layout/topbar" /> <ImageView android:id="@+id/iv_tabline" android:layout_width="match_parent" android:layout_height="3dp" android:layout_marginLeft="0dp" android:background="@drawable/tabline" /> <android.support.v4.view.ViewPager android:id="@+id/setting_fragment_viewpager" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_weight="1.0" android:flipInterval="30" android:persistentDrawingCache="animation" /> </LinearLayout>
MainActivity代碼:
package com.jam.fragmentdemo; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.view.View; import android.view.View.OnClickListener; import android.view.Window; import android.widget.Button; /** * 由于這個(gè)工程還需要用到ViewPager,所以在此繼承FragmentActivity * @author Jam * */ public class MainActivity extends FragmentActivity implements OnClickListener { // 三個(gè)按鈕 private Button messageButton; private Button friendButton; private Button settingButton; // 三個(gè)fragment private MessageFragment messgeFragment; private FriendFragment friendFragment; private SettingFragment settingFragment; private int fragmentIndex = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); messageButton = (Button) findViewById(R.id.btn_messaage); friendButton = (Button) findViewById(R.id.btn_friend); settingButton = (Button) findViewById(R.id.btn_setting); setDefaultFragment(); // 為三個(gè)按鈕綁定監(jiān)聽器 messageButton.setOnClickListener(this); friendButton.setOnClickListener(this); settingButton.setOnClickListener(this); } /** * 設(shè)置初始化默認(rèn)的Fragment為MessageFragment */ private void setDefaultFragment() { FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); messgeFragment = new MessageFragment(); transaction.replace(R.id.content, messgeFragment); transaction.commit(); } /** * 在下面的onClick內(nèi), 用了兩個(gè)switch語句來處理頁面的更換第一層判斷按下了哪一個(gè)按鈕 * 第二層判斷當(dāng)前頁是哪一頁,在決定隱藏哪一頁 * 這里的實(shí)現(xiàn)方法可能會(huì)不太靈活 */ @Override public void onClick(View v) { // FragmentTransaction每一次都需要拿到,否則程序會(huì)報(bào)錯(cuò) FragmentTransaction transaction = getSupportFragmentManager() .beginTransaction(); switch (v.getId()) { case R.id.btn_messaage: if (messgeFragment == null) { messgeFragment = new MessageFragment(); transaction.add(R.id.content, messgeFragment); } switch (fragmentIndex) { case 0: if (messgeFragment != null) { transaction.hide(messgeFragment); } break; case 1: if (friendFragment != null) { transaction.hide(friendFragment); } break; case 2: if (settingFragment != null) { transaction.hide(settingFragment); } break; } transaction.show(messgeFragment); fragmentIndex = 0; break; case R.id.btn_friend: if (friendFragment == null) { friendFragment = new FriendFragment(); transaction.add(R.id.content, friendFragment); } switch (fragmentIndex) { case 0: if (messgeFragment != null) { transaction.hide(messgeFragment); } break; case 1: if (friendFragment != null) { transaction.hide(friendFragment); } break; case 2: if (settingFragment != null) { transaction.hide(settingFragment); } break; } transaction.show(friendFragment); fragmentIndex = 1; break; case R.id.btn_setting: if (settingFragment == null) { settingFragment = new SettingFragment(); transaction.add(R.id.content, settingFragment); } switch (fragmentIndex) { case 0: if (messgeFragment != null) { transaction.hide(messgeFragment); } break; case 1: if (friendFragment != null) { transaction.hide(friendFragment); } break; case 2: if (settingFragment != null) { transaction.hide(settingFragment); } break; } transaction.show(settingFragment); fragmentIndex = 2; break; } transaction.commit(); } }
這段代碼中要注意,在做事務(wù)操作時(shí)FragmentTransaction每次都要拿到,即
FragmentTransaction transaction = getSupportFragmentManager() .beginTransaction();
否則程序會(huì)報(bào)錯(cuò),完成操作記得transaction.commit();
另外在使用流程大致如下
首先
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
(注意上面getSupportFragmentManager是V4包的用法)
transaction.add()
往Activity中添加一個(gè)Fragment
transaction.remove()
從Activity中移除一個(gè)Fragment,如果被移除的Fragment沒有添加到回退棧(回退棧后面會(huì)詳細(xì)說),這個(gè)Fragment實(shí)例將會(huì)被銷毀。
transaction.replace()
使用另一個(gè)Fragment替換當(dāng)前的,實(shí)際上就是remove()然后add()的合體~
transaction.hide()
隱藏當(dāng)前的Fragment,僅僅是設(shè)為不可見,并不會(huì)銷毀
transaction.show()
顯示之前隱藏的Fragment
detach()
會(huì)將view從UI中移除,和remove()不同,此時(shí)fragment的狀態(tài)依然由FragmentManager維護(hù)。
attach()
重建view視圖,附加到UI上并顯示。
transatcion.commit()//提交一個(gè)事務(wù)
以上是大致流程,具體使用哪種方法依照自己的工程需要。
MessageFragment的代碼和FriendFragment的代碼簡單,沒有在其中添加什么東西,只需要讓他們繼承Fragment
在此只貼出其中MessageFragment的代碼
package com.jam.fragmentdemo; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class MessageFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // TODO Auto-generated method stub return inflater.inflate(R.layout.activity_messagefragment, container, false); } }
SettingFragment由于用到了ViewPager,所以代碼比前面兩個(gè)Fragment多
SettingFragment的代碼:
package com.jam.fragmentdemo; import java.util.ArrayList; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.animation.Animation; import android.view.animation.TranslateAnimation; import android.widget.Button; import android.widget.ImageView; import com.jam.fragmentdemo.settingcontent.InsectFragment; import com.jam.fragmentdemo.settingcontent.MenuFragment; public class SettingFragment extends Fragment implements OnClickListener{ //TopBar所含有的頁數(shù) private final static int pagerNum = 2; //TopBar當(dāng)前所指向的頁下標(biāo) private int currentIndex = 0; //initTabLineWith方法中計(jì)算得到的平均值用avg記錄 //這里的平均值指的是:屏幕寬度/所含的頁數(shù)(pagerNum) private int avg; private ArrayList<Fragment> list = new ArrayList<Fragment>(); private ViewPager viewPager; private ImageView tabLine; private InsectFragment insectFragment; private MenuFragment menuFragment; private Button insectButton; private Button menuButton; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_settingfragment, null); initTabLineWith(view); //初始化部件 viewPager = (ViewPager) view.findViewById(R.id.setting_fragment_viewpager); viewPager.setCurrentItem(0); insectButton = (Button) view.findViewById(R.id.btn_insect); menuButton = (Button) view.findViewById(R.id.btn_menu); insectFragment = new InsectFragment(); menuFragment = new MenuFragment(); list.add(insectFragment); list.add(menuFragment); insectButton.setOnClickListener(this); menuButton.setOnClickListener(this); viewPager.setAdapter(new MyViewPagerAdapter(getChildFragmentManager(), list)); viewPager.setOnPageChangeListener(new OnPageChangeListener() { /** * tabLine指示器使用Animation的方法移動(dòng) */ @Override public void onPageSelected(int position) { Animation animation = null; switch (position) { case 0: animation = new TranslateAnimation(currentIndex * avg, 0 * avg, 0, 0); break; case 1: animation = new TranslateAnimation(currentIndex * avg, 1 * avg, 0, 0); break; } currentIndex = position; animation.setFillAfter(true); animation.setDuration(300); tabLine.startAnimation(animation); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int arg0) { } }); return view; } /** * 根據(jù)屏幕寬度的大小,初始化TabLine的長度 * @param view */ private void initTabLineWith(View view) { tabLine = (ImageView) view.findViewById(R.id.iv_tabline); LayoutParams lp = (LayoutParams) tabLine.getLayoutParams(); //拿到屏幕寬度的操作 DisplayMetrics dm = new DisplayMetrics(); getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); int screenWith = dm.widthPixels; avg =screenWith / pagerNum; lp.width = avg; //設(shè)置tabLine指示器的長度 tabLine.setLayoutParams(lp); } /** * 點(diǎn)擊改動(dòng)當(dāng)前頁面 */ @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_insect: viewPager.setCurrentItem(0); currentIndex = 0; break; case R.id.btn_menu: viewPager.setCurrentItem(1); currentIndex = 1; break; } } public class MyViewPagerAdapter extends FragmentPagerAdapter { private ArrayList<Fragment> fragmentsList; public MyViewPagerAdapter(FragmentManager fm) { super(fm); } public MyViewPagerAdapter(FragmentManager fm, ArrayList<Fragment> list) { super(fm); this.fragmentsList = list; } @Override public int getCount() { return fragmentsList.size(); } @Override public Fragment getItem(int arg0) { return fragmentsList.get(arg0); } @Override public int getItemPosition(Object object) { return super.getItemPosition(object); } } }
SettingFragment中又包含兩個(gè)Fragment,這兩個(gè)Fragment沒什么內(nèi)容,在此就不貼布局文件和代碼了。
單純使用Fragment,不能實(shí)現(xiàn)滑動(dòng)的效果,只能點(diǎn)擊切換,要實(shí)現(xiàn)滑動(dòng)的效果可考慮使用ViewPager。
使用Fragment實(shí)現(xiàn)這種類似TabHost,好處在于文件方便管理,每一個(gè)Fragment都是獨(dú)立的,單純的使用ViewPager的話,代碼會(huì)比較長,在修改是比較麻煩。
本次工程中的代碼只實(shí)現(xiàn)了展示了基本的效果,另外有篇寫的非常好的博文
Android項(xiàng)目Tab類型主界面大總結(jié) Fragment+TabPageIndicator+ViewPager
介紹了各種Tab實(shí)現(xiàn)的效果和對比。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。