Activity + 多個Fragment的形式
代碼開源在Github:https://github.com/yanzhenjie/NoFragment
Demo:https://github.com/huangshuyuan/NoFragmentDemo/tree/master
ViewPager自動輪播:http://blog.csdn.net/yanzhenjie1003/article/details/51327392
Demo中包括:
- NoFragment的使用
- Design-CollapsingToobarLayout武学、ToolBar使用(沉浸式標(biāo)題欄)5.0+
- 自動滾動的ViewPager的使用(自定義伦意、沉浸式樣式)5.0+
一、NoFragment的使用
NoFragment 特點(diǎn)
支持傳統(tǒng)Fragment的所有用法熏矿。
支持startFragmentForResult(Fragment)、onFragmentResult(int, int, Bundle)褪储,原生只有Activity慧域。
支持同一個Fragment啟動多個實(shí)例。
支持自動維護(hù)Back Stack辛藻,不會錯亂互订。
支持在Fragment中直接setToolbar()、setTitle()氮墨、displayHomeButton()吐葵。
返回鍵和homeButton自動處理,支持開發(fā)者攔截處理粒褒。
支持ActionBar Menu诚镰、溢出Menu等。
當(dāng)然最基本的是一個Activity + 多個Fragment月杉。
使用方法
Gradle一句話遠(yuǎn)程依賴
compile 'com.yanzhenjie:fragment:1.0.1'
主Activity需要繼承CompatActivity抠艾,然后啟動一個Fragment:
public class MainActivity extends CompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*
* 一句話即可,不要懷疑自己的眼睛腌歉,這是真的齐苛。
*/
startFragment(MainFragment.class);
}
@Override
protected int fragmentLayoutId() {
return R.id.fragment_root;
}
}
一、以standard模式啟動一個Fragment
startFragment(MoreMenuFragment.class);
二馍驯、以startActivityForResult()方式啟動一個Fragment
// 啟動,等待回調(diào)結(jié)果狂打。
startFragmentForResult(StartResultFragment.class, 100);
// 不論怎樣回來都會回調(diào)onFragmentResult()混弥。
@Override
public void onFragmentResult(int requestCode, int resultCode, @Nullable Bundle result) {
switch (requestCode) {
case 100: {
if (resultCode == RESULT_OK) {
// 操作成功:result就是調(diào)用的Fragment返回的結(jié)果。
} else if (resultCode == RESULT_CANCELED) {
// 操作取消浙宜。
}
break;
}
}
}
在StartResultFragment中如果要返回結(jié)果蛹磺,那么:
Bundle bundle = new Bundle();
bundle.putString("message", result);
setResult(RESULT_OK, bundle);
finish();
當(dāng)然你也不設(shè)置同仆,那么resultCode的默認(rèn)值是RESULT_CANCELED。
三俗或、跳轉(zhuǎn)時帶參數(shù)
// 封裝參數(shù):
Bundle bundle = new Bundle();
bundle.putString("hehe", "呵呵噠");
bundle.putString("meng", "萌萌噠");
bundle.putString("bang", "棒棒噠");
bundle.putString("meme", "么么噠");
// 在Activity中或者Fragment調(diào)用此方法:
NoFragment fragment = fragment(ArgumentFragment.class, bundle);
// 最后啟動:
startFragment(fragment);
四辛慰、跳轉(zhuǎn)的Fragment不保存在Back Stack
這種方式顯示的fragment中如果調(diào)用了其它fragment干像,從其它fragment中回來時,這個fragment將會跳過麻汰,不會顯示五鲫,也就是說:A-B-C-[back]-A,從A到B位喂,B不加入回退棧塑崖,B再到C,C按下返回鍵弃舒,或者調(diào)用finish()方法,將會直接回到A苗踪。
startFragment(StackFragment.class, false);
五、同一個Fragment毕莱,啟動多個實(shí)例
startFragment(MoreMenuFragment.class);
startFragment(MoreMenuFragment.class);
startFragment(MoreMenuFragment.class);
startFragment(MoreMenuFragment.class);
比如我們這里調(diào)用四次颅夺,那么回退棧中有四個MoreMenuFragment
吧黄,按下返回鍵時將一個個退出。
六拗慨、Toolbar菜單的加載和處理
我們知道MD設(shè)計中赵抢,Toolbar的菜單很好看,而且利用Toolbar也很好加載烦却,那么NoFragment也是完美支持的其爵,當(dāng)重寫了onCreateOptionsMenu()方法后,調(diào)用setToolbar(Toolbar)方法時醋闭,將會調(diào)用onCreateOptionsMenu()方法证逻,此時你就該加載菜單了,當(dāng)然也只需要一句話囚企。
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Load your menu.
inflater.inflate(R.menu.menu_fragment_main, menu);
}
當(dāng)用戶點(diǎn)擊meun的item時將會回調(diào)這個方法龙宏,和原生Activity是一樣的。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle menu item click.
int id = item.getItemId();
switch (id) {
case R.id.action_settings: {
Snackbar.make(mToolbar, R.string.action_settings, Snackbar.LENGTH_SHORT).show();
break;
}
case R.id.action_exit: {
Snackbar.make(mToolbar, R.string.action_exit, Snackbar.LENGTH_SHORT).show();
break;
}
}
return true;
}
七辆影、Toolbar的返回按鈕的處理
在正常開發(fā)中給Toolbar設(shè)置返回按鈕也要好幾行代碼的,如果使用了NoFragment锯蛀,那么:
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// 首先設(shè)置Toolbar:
setToolbar(mToolbar);
// 設(shè)置標(biāo)題:
setTitle(R.string.title_fragment_main);
// 顯示返回按鈕次慢,圖標(biāo)開發(fā)者指定:
displayHomeAsUpEnabled(R.drawable.ic_close_white);
}
設(shè)置了返回按鈕后,用戶點(diǎn)擊返回按鈕將自動殺死當(dāng)前Fragment劈愚,當(dāng)然你也可以攔截用戶的返回行為:
@Override
public boolean onInterceptToolbarBack() {
// 返回true將攔截闻妓,返回false將不攔截。
return true;
}
八算凿、Toolbar的標(biāo)題自定義
xml
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="?attr/colorPrimary"
android:gravity="center_horizontal"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="@style/AppTheme.PopupOverlay">
<!--自定義標(biāo)題位置-->
<TextView
android:id="@+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#ffffff"
android:textSize="20sp" />
</android.support.v7.widget.Toolbar>
BaseFargment中,extends NoFragment
/**
* @param resId 資源文件
*/
@Override
public void setTitle(@StringRes int resId) {
TextView titleTV = (TextView) getView().findViewById(R.id.toolbar_title);
titleTV.setText(getContext().getText(resId));
}
九浸卦、Toolbar跟隨RecylerView滾動設(shè)置
需要在xml中設(shè)置app:layout_behavior案糙、 app:layout_scrollFlags
注意一點(diǎn): 需要嵌套在CoordinatorLayout中
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="@style/AppTheme.PopupOverlay" />
<!--標(biāo)題跟隨滾動 1.toolbar app:layout_scrollFlags="scroll|enterAlways|snap"
下方:app:layout_behavior="@string/appbar_scrolling_view_behavior"-->
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
> </android.support.v7.widget.RecyclerView>
<!--標(biāo)題跟隨滾動 1.toolbar app:layout_scrollFlags="scroll|enterAlways|snap"
下方:app:layout_behavior="@string/appbar_scrolling_view_behavior"-->
</android.support.design.widget.CoordinatorLayout>
混淆
-keep public class * extends android.support.v4.app.Fragment
二时捌、Material Design之CollapsingToolbarLayout使用
參考:http://www.reibang.com/p/564a0c56022b
三、ViewPager自定義實(shí)現(xiàn)Banner輪播+沉浸式樣式
輪播器最重要的幾個特點(diǎn)就是:自動滾動、手動滑動拿诸、滾動方向、每個Item顯示時間季率。因此我們設(shè)計提供以下幾個方法供外部調(diào)用:
**
* 設(shè)置每個Item的播放時間描沟,默認(rèn)3000毫秒
*/
public void setShowTime(int showTimeMillis);
/**
* 設(shè)置滾動方向鞭光,默認(rèn)向左滾動
*/
public void setDirection(Direction direction);
/**
* 開始自動滾動
*/
public void start();
/**
* 停止自動滾動
*/
public void stop();
/**
* 播放上一個
*/
public void previous();
/**
* 播放下一個
*/
public void next();
如果使用自定ViewPager
AutoPlayViewPager autoPlayViewPage = (AutoPlayViewPager) findViewById(R.id.view_pager);
autoPlayViewPage.setAdapter(bannerAdapter);
// 以下兩個方法不是必須的惰许,因為有默認(rèn)值
autoPlayViewPage.setDirection(AutoPlayViewPager.Direction.LEFT);// 設(shè)置播放方向
autoPlayViewPage.setCurrentItem(200); // 設(shè)置每個Item展示的時間
autoPlayViewPage.start(); // 開始輪播
無限輪播
其實(shí)我們看到就是多調(diào)用了一個star方法刹孔,但是還不夠,我們在適配器中還要做一點(diǎn)點(diǎn)小事情卦睹。為了能讓輪播無限循環(huán)方库,所以我們在getCount中返回int的最大值:
@Override
public int getCount() {
return resIds == null ? 0 : Integer.MAX_VALUE;
}
resIds是我們的數(shù)據(jù)源。該了這個Count后徐鹤,我們的instantiateItem()方法也要修改邀层,不然會發(fā)生下標(biāo)越界的異常,我們在拿到position后要做個處理:
@Override
public Object instantiateItem(ViewGroup container, int position) {
position = position % resIds.size();
Object xxoo = resIds.get(position);
...
}