- 1月23日更新:將fragmentnew的實(shí)現(xiàn)改為viewpager+viewpagerindicater+fragment實(shí)現(xiàn)激蹲,可以在資訊詳情頁內(nèi)滑動(dòng)切換頁面。
博主最近在做一個(gè)資訊類app科雳,要求實(shí)現(xiàn)類似頭條那種的界面,即底部導(dǎo)航欄切換改變fragment,在某一個(gè)界面后恃锉,點(diǎn)擊上部導(dǎo)航欄也改變fragment港粱,這里就用到了fragment嵌套fragment螃成。
其中需要注意的地方就是在使用時(shí), 主要要依靠宿主Fragment的 getChildFragmentManager() 來獲取FragmentManger.
博主的思路是:主activity的導(dǎo)航欄使用radiogroup+radiobutton實(shí)現(xiàn),通過點(diǎn)擊radiobutton查坪,來切換頁面剑肯。資訊頁面是一個(gè)fragmentnews嵌套viewpager+fragment實(shí)現(xiàn)頁面滑動(dòng)切換媒役。其他頁面都分別為一個(gè)fragment乏悄,內(nèi)容可以自定義谜洽;其中我的界面是一個(gè)新的activity。
這里給出主界面代碼望忆,MainActivity.java
initView()函數(shù)來監(jiān)聽RadioGroup狀態(tài)變化罩阵,在狀態(tài)改變時(shí),調(diào)用setIndexSelected()隱藏當(dāng)前fragment炭臭,顯示被選中RadioButton對(duì)應(yīng)的fragment永脓。
initFragment函數(shù)初始化fragment并將fragment加入到fragmentManager中,初始設(shè)置為默認(rèn)隱藏鞋仍。
setIndexSelected函數(shù)用來實(shí)現(xiàn)fragmen的顯示和隱藏
package com.example.zyk97.infotest.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
import android.widget.Button;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;
import com.example.zyk97.infotest.Fragment.FragmentAnalysis;
import com.example.zyk97.infotest.Fragment.FragmentData;
import com.example.zyk97.infotest.Fragment.FragmentHome;
import com.example.zyk97.infotest.Fragment.FragmentNews;
import com.example.zyk97.infotest.R;
/**
* 應(yīng)用主界面常摧,主activity
* 用戶打開顯示首頁
*/
public class Mainactivity extends FragmentActivity {
private Fragment[] mfragments;
private FragmentHome fh;
private FragmentNews fn;
private FragmentData fd;
private FragmentAnalysis fa;
private int mindex = 0;
private RadioGroup rg;
private Button searchimage;
private TextView searchtext;
private int last = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainactivity);
initFragment();
initView();
search();
}
private void initView() {
rg = findViewById(R.id.rgbtm);
searchimage = findViewById(R.id.search_image_main);
searchtext = findViewById(R.id.search_text_main);
rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
//遍歷RagioGroup中的所有子控件
for (int index = 0; index < 4; index++) {
//獲取到指定位置的RadioButton
RadioButton rb = (RadioButton) group.getChildAt(index);
//如果被選中,顯示對(duì)應(yīng)fragment
if (rb.isChecked()) {
setIndexSelected(index);
last = index;
break;
}
}
RadioButton me = (RadioButton) group.getChildAt(4);
if (me.isChecked()) {
Intent intent = new Intent(Mainactivity.this, FirstIn.class);
RadioButton radioButton = (RadioButton) rg.getChildAt(last);
radioButton.setChecked(true);
startActivity(intent);
}
}
});
}
private void initFragment() {
fh = FragmentHome.newInstance();
fn = FragmentNews.newInstance();
fd = FragmentData.newInstance();
fa = FragmentAnalysis.newInstance();
mfragments = new Fragment[]{fh, fn, fd, fa};
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
//初始化直接全部加載所有fragment
for (int i = 0; i < 4; i++) {
ft.add(R.id.content_main, mfragments[i]).hide(mfragments[i]);
}
ft.show(fh).commit();
setIndexSelected(0);
}
//選中顯示和隱藏
private void setIndexSelected(int index) {
if (mindex == index) {
return;
}
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
//隱藏
ft.hide(mfragments[mindex]);
//判斷是否顯示
if (!mfragments[index].isAdded()) {
if (index == 1) {
ft.add(R.id.content_main, mfragments[index]).show(mfragments[index]);
} else {
ft.add(R.id.content_main, mfragments[index]).show(mfragments[index]);
}
} else {
ft.show(mfragments[index]);
}
ft.commit();
//再次賦值
mindex = index;
}
private void search() {
searchimage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent1 = new Intent(Mainactivity.this, SearchPage.class);
startActivity(intent1);
}
});
searchtext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent2 = new Intent(Mainactivity.this, SearchPage.class);
startActivity(intent2);
}
});
}
}
資訊界面的fragment也類似主界面activity威创,要對(duì)他嵌套的幾個(gè)fragment進(jìn)行管理落午,其中需要注意的是,在獲取FragmentManager時(shí)肚豺,需要用getChildFragmentManager()溃斋,在宿主fragment中調(diào)用這個(gè)函數(shù),即可用它來向這個(gè)fragment內(nèi)部添加fragments.
FragmentManager fragmentManager=getChildFragmentManager();
FragmentTransaction ft=fragmentManager.beginTransaction();
這里只給出資訊界面的fragmentNews.java,其他幾個(gè)界面類似吸申。
博主使用了viewpagerindicator梗劫,具體添加依賴和注意事項(xiàng)參考引入第三方包V4沖突解決方法
package com.example.zyk97.infotest.Fragment;
import android.os.Bundle;
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.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.zyk97.infotest.R;
import com.example.zyk97.infotest.Update.MessageEvent;
import com.viewpagerindicator.TabPageIndicator;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
public class FragmentNews extends Fragment {
private static FragmentNews fm;
public String titles[] = new String[]{"快訊", "同業(yè)", "推薦", "定制", "要聞"};
private ViewPager viewPager;
private TabPageIndicator indicator;
private TabPageIndicatorAdapter mAdapter;
//首頁傳遞的數(shù)據(jù)享甸,表示資訊頁應(yīng)顯示msgIndex頁
private int msgIndex=0;
public static FragmentNews newInstance() {
if (fm == null) {
fm = new FragmentNews();
}
return fm;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragmentnews, container, false);
initView(view);
//注冊(cè)eventbus
EventBus.getDefault().register(this);
return view;
}
//接受home界面?zhèn)鱽淼臄?shù)據(jù),切換界面
@Subscribe(threadMode = ThreadMode.MAIN)
public void onEvent(MessageEvent msg) {
msgIndex = msg.getIndex();
indicator.setCurrentItem(msgIndex);
}
private void initView(View view) {
mAdapter = new TabPageIndicatorAdapter(getChildFragmentManager());
//實(shí)例化ViewPager梳侨, 然后給ViewPager設(shè)置Adapter
viewPager = view.findViewById(R.id.viewpager_news);
viewPager.setAdapter(mAdapter);
//實(shí)例化TabPageIndicator蛉威,然后與ViewPager綁在一起(核心步驟)
indicator = view.findViewById(R.id.indicator_news);
indicator.setViewPager(viewPager);
indicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
if (EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().unregister(this);
}
}
/**
* viewpager的adapter
*/
class TabPageIndicatorAdapter extends FragmentPagerAdapter {
Bundle args = new Bundle();
Fragment f1=new Fragment1();
Fragment f2=new Fragment2();
Fragment f3=new Fragment3();
Fragment f4=new Fragment4();
Fragment f5=new Fragment5();
public TabPageIndicatorAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position){
case 0:
args.putString("arg", titles[position]);
f1.setArguments(args);
return f1;
case 1:
args.putString("arg", titles[position]);
f1.setArguments(args);
return f2;
case 2:
args.putString("arg", titles[position]);
f1.setArguments(args);
return f3;
case 3:
args.putString("arg", titles[position]);
f1.setArguments(args);
return f4;
case 4:
args.putString("arg", titles[position]);
f1.setArguments(args);
return f5;
}
return f1;
}
@Override
public CharSequence getPageTitle(int position) {
return titles[position % titles.length];
}
@Override
public int getCount() {
return titles.length;
}
}
}
下面是主界面和資訊界面布局文件:
mainactivity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="55dp"
android:background="@color/dark_blue"
android:orientation="horizontal">
<Button
android:id="@+id/search_image_main"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="5dp"
android:layout_gravity="center"
android:background="@mipmap/search"
/>
<TextView
android:id="@+id/search_text_main"
android:layout_width="match_parent"
android:layout_height="30dp"
android:layout_marginRight="15dp"
android:layout_gravity="center"
android:background="@drawable/textview_round_border"
android:gravity="center"
android:text="輸入關(guān)鍵字!" />
</LinearLayout>
<FrameLayout
android:id="@+id/content_main"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</FrameLayout>
<RadioGroup
android:id="@+id/rgbtm"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/border_bottom"
android:orientation="horizontal">
<RadioButton
android:id="@+id/home"
style="@style/button_bottom"
android:checked="true"
android:drawableTop="@drawable/home_image_selector"
android:text="首頁" />
<RadioButton
android:id="@+id/news"
style="@style/button_bottom"
android:checked="false"
android:drawableTop="@drawable/news_image_selector"
android:text="資訊" />
<RadioButton
android:id="@+id/data"
style="@style/button_bottom"
android:checked="false"
android:drawableTop="@drawable/data_image_selector"
android:text="數(shù)據(jù)" />
<RadioButton
android:id="@+id/analysis"
style="@style/button_bottom"
android:checked="false"
android:drawableTop="@drawable/analysis_image_selector"
android:text="智能分析" />
<RadioButton
android:id="@+id/me"
style="@style/button_bottom"
android:checked="false"
android:drawableTop="@drawable/me_image_selector"
android:text="我的" />
</RadioGroup>
</android.support.v7.widget.LinearLayoutCompat>
fragmentnews.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<com.viewpagerindicator.TabPageIndicator
android:id="@+id/indicator_news"
android:layout_width="match_parent"
android:layout_height="50dp"
android:theme="@style/StyledIndicators"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager_news"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
</android.support.v4.view.ViewPager>
</android.support.v7.widget.LinearLayoutCompat>
TabPageIndicator的style樣式文件
//indicator的style
<style name="StyledIndicators" parent="@android:style/Theme.Light">
<item name="vpiTabPageIndicatorStyle">@style/CustomTabPageIndicator</item>
</style>
<style name="CustomTabPageIndicator" parent="Widget.TabPageIndicator">
<item name="android:background">@drawable/tab_indicator</item>
<item name="android:textAppearance">@style/CustomTabPageIndicator.Text</item>
<item name="android:textSize">14sp</item>
<item name="android:dividerPadding">8dp</item>
<item name="android:showDividers">middle</item>
<item name="android:paddingLeft">10dp</item>
<item name="android:paddingRight">10dp</item>
<item name="android:fadingEdge">horizontal</item>
<item name="android:fadingEdgeLength">8dp</item>
</style>
<style name="CustomTabPageIndicator.Text" parent="android:TextAppearance.Medium">
<item name="android:typeface">monospace</item>
<item name="android:textColor">@drawable/selector_tabtext</item>
</style>
兩個(gè)drawable資源文件:
selector_tabtext.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:color="@color/dark_blue" />
<item android:state_pressed="true" android:color="@color/dark_blue" />
<item android:state_focused="true" android:color="@color/dark_blue" />
<item android:color="@color/gray2"/>
</selector>
tab_indicator.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="false" android:state_pressed="false" android:drawable="@android:color/transparent" />
<item android:state_selected="false" android:state_pressed="true" android:drawable="@android:color/transparent" />
</selector>
本文樣例完整代碼InfoTest
本文參考:
-《 Fragment里邊嵌套Fragment》走哺,Mr_Billzhang
-《開源控件ViewPagerIndicator的使用》蚯嫌,陳利健