前言
專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計(jì)、成都做網(wǎng)站服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)興安免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了超過千家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
大家在做APP開發(fā)的過程中,有很多時候,我們需要實(shí)現(xiàn)類似于下面這種沉浸式的體驗(yàn)。
沉浸式體驗(yàn)
一開始接觸的時候,似乎大家都會覺這種體驗(yàn)實(shí)現(xiàn)起來,會比較困難。難點(diǎn)在于:
好,總結(jié)起來以上就是我們的問題,也是需要解決的,一個一個解決了,這種需求也就實(shí)現(xiàn)了,那么,我們?nèi)绾稳ヒ徊揭徊絹斫鉀Q以上的問題呢?
1、頭部背景和標(biāo)題的漸隱漸現(xiàn)
首先,我們來分析第一個問題,頭部的背景圖在推上去的過程中,慢慢的變得不可見了,這種聽起來好像是某種collapse,因此,很容易讓人想到CollapsingToolbarLayout,如果你想要比較容易的了解CollapsingToolbarLayout
應(yīng)用,建議看這位兄臺的文章,他給也給了一個動畫,比較詳細(xì)的介紹了這個的應(yīng)用,例如:
CollapsingToolbarLayout
對于里面的用法,我這里不作講解了,但是如果你不了解這個布局的應(yīng)用,我強(qiáng)烈建議你好好了解一下,才能繼續(xù)下面走,只是想說明一下,走到這里,你有一個坑需要去填,那就是我們的標(biāo)題動畫可以不是這樣的,而且,還是標(biāo)題還是居中的,注意,這里的實(shí)現(xiàn),標(biāo)題不是居中的,是靠左的,這本來是Android設(shè)計(jì)規(guī)范,但是設(shè)計(jì)師偏偏不買Android規(guī)范的賬,因此,我們必須躺過這個坑,然后,從Stack Overflow上了解到一個issue:
假設(shè),這個方式是可行的,那么要解決居中的問題后,把返回按鈕改為我們的按鈕樣式,然后,在耍點(diǎn)小詭計(jì),讓title開始是透明的,并且改變返回按鈕的圖片:
collapsingToolbarLayout.setCollapsedTitleTextColor(Color.WHITE); //collapsingToolbarLayout.setExpandedTitleColor(Color.WHITE); collapsingToolbarLayout.setExpandedTitleColor(Color.TRANSPARENT);
然而,假設(shè),始終只是一個假設(shè),實(shí)際上,這個假設(shè)不成立,我在嘗試的時候,發(fā)現(xiàn)Toolbar中的TextView根本就不能使用android:layout_gravity="center"這種屬性好吧,即使強(qiáng)行加上,效果也是靠左的。
那么,如何做,我的解決方式是這樣的
.........
然后,include里面的布局是這樣的
<?xml version="1.0" encoding="utf-8"?>//*****請注意這個View*******///
效果就是這樣
當(dāng)然,這時候,標(biāo)題是需要你自己設(shè)置漸隱漸現(xiàn)的。那么,我們依據(jù)什么呢?
appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { mTitle.setAlpha(-verticalOffset * 1.0f / appBarLayout.getTotalScrollRange()); } });
依據(jù)的就是對appBarLayout的監(jiān)聽。
2、將statusBar變?yōu)橥该鳎依盟目臻g來放我們的布局內(nèi)容。
/** * 使?fàn)顟B(tài)欄透明,并覆蓋狀態(tài)欄,對API大于19的顯示正常,但小于的界面擴(kuò)充到狀態(tài)欄,但狀態(tài)欄不為透明 */ @TargetApi(Build.VERSION_CODES.KITKAT) public static void transparentAndCoverStatusBar(Activity activity) { //FLAG_LAYOUT_NO_LIMITS這個千萬別用,帶虛擬按鍵的機(jī)型會有特別多問題 // //FLAG_TRANSLUCENT_STATUS要求API大于19 // activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); // activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); // //FLAG_LAYOUT_NO_LIMITS對API沒有要求 // activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = activity.getWindow(); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(Color.TRANSPARENT); window.setNavigationBarColor(Resources.getSystem().getColor(android.R.color.background_dark)); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Window window = activity.getWindow(); window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } }
這里是在網(wǎng)上找的一個方法,直接調(diào)用即可,但是API需要大于19,相信目前基本上都滿足吧。請注意,我的AppBarLayout中并沒有這個屬性
android:fitsSystemWindows="true"
如果你加了這個屬性,嘿嘿,statusbar雖然空間可以利用,但是有一個你揮之不去的顏色覆蓋在上面,
然后,你還記得上面那個布局中
//*****請注意這個View*******///
這個作用可大了,就是為了對status_bar原始空間做偏移的,在代碼中,需要動態(tài)的改變這個View的高度為statusBar的高度,怎么獲?。?/p>
/** * 獲取狀態(tài)欄高度 * * @param context context * @return 狀態(tài)欄高度 */ public static int getStatusBarHeight(Context context) { // 獲得狀態(tài)欄高度 int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); return context.getResources().getDimensionPixelSize(resourceId); }
完了之后,還需要設(shè)置我們自己塞進(jìn)去的那個toolbar的高度為toolbar的高度加上StatusBar的高度。
3、ViewPager推到actionbar下面就不讓在推了
這個其實(shí)需要你CollapsingToolbarLayout里面有一個子view是要使用pin模式的,那么這個子view是誰,顯然就是那個toolbar了
4、底部控件隨著列表的滑動漸漸隱藏
可以看到,底部的控件是覆蓋在列表上的,列表向上滑動的時候,把他隱藏,就可以空出更多的控件看列表。那么,如何做呢?
既然,我們是包裹在CoordinatorLayout中,那么,顯然,最好的方式是使用layout_behavior了,我這里實(shí)現(xiàn)了一個BottomBehavior:
public class BottomBehavior extends CoordinatorLayout.Behavior { private int id; private float bottomPadding; private int screenWidth; private float designWidth = 375.0f;//設(shè)計(jì)視圖的寬度,通常是375dp, public BottomBehavior() { super(); } public BottomBehavior(Context context, AttributeSet attrs) { super(context, attrs); screenWidth = getScreenWidth(context); TypedArray typedArray = context.getResources().obtainAttributes(attrs, R.styleable.BottomBehavior); id = typedArray.getResourceId(R.styleable.BottomBehavior_anchor_id, -1); bottomPadding = typedArray.getFloat(R.styleable.BottomBehavior_bottom_padding, 0f); typedArray.recycle(); } @Override public void onAttachedToLayoutParams(@NonNull CoordinatorLayout.LayoutParams params) { params.dodgeInsetEdges = Gravity.BOTTOM; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { return dependency.getId() == id; } @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { child.setTranslationY(-(dependency.getTop() - (screenWidth * bottomPadding / designWidth))); Log.e("BottomBehavior", "layoutDependsOn() called with: parent = [" + dependency.getTop()); return true; } public static int getScreenWidth(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); Display display = null; if (wm != null) { display = wm.getDefaultDisplay(); Point size = new Point(); display.getSize(size); int width = size.x; // int height = size.y; return width; } return 0; } }
這個里面有兩個自定義屬性,id,bottomPadding,id表示基于哪個控件的相對位置改變,我這打算基于viewpager
這個控件,看源碼可以知道,只有當(dāng)onDependentViewChanged返回ture時,layoutDependsOn才會被回調(diào)。bottomPadding是表示一個初始的偏移,因?yàn)関iewpager本身不是頂在屏幕頂端的(開始被圖片占據(jù)了一部分控件),因此,需要扣除這部分占有。
同理,加入讓你實(shí)現(xiàn)一個懸浮在左側(cè),右側(cè),滑動隱藏,停止顯示的,也都可以參考類似Behavior的方式,減少代碼耦合。
總結(jié)
最后整個布局是這樣子的
<?xml version="1.0" encoding="utf-8"?>............ ..........底部布局
注:IGameRefreshLayout實(shí)際上就是封裝的PullToRefreshView,IgameViewPager是我們封裝的Viewpager,減少每次寫Viewpager的套路代碼。
按照這個框架來,相信你很容易寫出這個樣子的布局。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對創(chuàng)新互聯(lián)的支持。