溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Fragment和ViewPager的使用和比較

發(fā)布時(shí)間:2020-06-09 14:37:42 來源:網(wǎng)絡(luò) 閱讀:896 作者:imjam 欄目:移動(dòng)開發(fā)

Fragment是一種可以嵌入在活動(dòng)當(dāng)中的UI 片段,它能讓程序更加合理和充分地利用大屏幕的空間,因而在平板上應(yīng)用的非常廣泛。擁有自己的生命周期和接收、處理用戶的事件。你可以動(dòng)態(tài)的添加、替換和移除某個(gè)Fragment。

Fragment使用非常廣泛,在此不介紹Fragment的生命周期,本例子將使用Fragment實(shí)現(xiàn)如下效果:

Fragment和ViewPager的使用和比較

Message   Friend   Setting

圖一


Fragment和ViewPager的使用和比較

Message   Friend   Setting

圖二


Fragment和ViewPager的使用和比較

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)的效果和對比。

向AI問一下細(xì)節(jié)

免責(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)容。

AI