亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

Android實現超級棒的沉浸式體驗教程

2019-10-21 21:36:24
字體:
來源:轉載
供稿:網友

前言

大家在做APP開發的過程中,有很多時候,我們需要實現類似于下面這種沉浸式的體驗。

Android,沉浸式
沉浸式體驗

一開始接觸的時候,似乎大家都會覺這種體驗實現起來,會比較困難。難點在于:

  • 頭部的背景圖在推上去的過程中,慢慢的變得不可見了,整個區域的顏色變成的暗黑色,然后標題出現了。
  • StatusBar變的透明,且空間可以被利用起來,看我們的圖片就頂到了頂 了。
  • 我們的viewpager推到actionbar的下方的時候,就固定在了actionbar的下方,不能在往上面推了。
  • 底部有一個控件,隨著列表的向上滑動,它退出視角范圍,以便于給出更多的空間來展示列表,其實整個沉浸式體驗都是為了給列表留出更多的空間來展示。

好,總結起來以上就是我們的問題,也是需要解決的,一個一個解決了,這種需求也就實現了,那么,我們如何去一步一步來解決以上的問題呢?

1、頭部背景和標題的漸隱漸現

首先,我們來分析第一個問題,頭部的背景圖在推上去的過程中,慢慢的變得不可見了,這種聽起來好像是某種collapse,因此,很容易讓人想到CollapsingToolbarLayout,如果你想要比較容易的了解CollapsingToolbarLayout

應用,建議看這位兄臺的文章,他給也給了一個動畫,比較詳細的介紹了這個的應用,例如:

Android,沉浸式
CollapsingToolbarLayout

對于里面的用法,我這里不作講解了,但是如果你不了解這個布局的應用,我強烈建議你好好了解一下,才能繼續下面走,只是想說明一下,走到這里,你有一個坑需要去填,那就是我們的標題動畫可以不是這樣的,而且,還是標題還是居中的,注意,這里的實現,標題不是居中的,是靠左的,這本來是Android設計規范,但是設計師偏偏不買Android規范的賬,因此,我們必須躺過這個坑,然后,從Stack Overflow上了解到一個issue:

<android.support.v7.widget.Toolbar android:id="@+id/toolbar_top" android:layout_height="wrap_content" android:layout_width="match_parent" android:minHeight="?attr/actionBarSize" android:background="@color/action_bar_bkgnd" app:theme="@style/ToolBarTheme" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Toolbar Title" android:layout_gravity="center" android:id="@+id/toolbar_title" /></android.support.v7.widget.Toolbar>

假設,這個方式是可行的,那么要解決居中的問題后,把返回按鈕改為我們的按鈕樣式,然后,在耍點小詭計,讓title開始是透明的,并且改變返回按鈕的圖片:

collapsingToolbarLayout.setCollapsedTitleTextColor(Color.WHITE);//collapsingToolbarLayout.setExpandedTitleColor(Color.WHITE);collapsingToolbarLayout.setExpandedTitleColor(Color.TRANSPARENT);

然而,假設,始終只是一個假設,實際上,這個假設不成立,我在嘗試的時候,發現Toolbar中的TextView根本就不能使用android:layout_gravity="center"這種屬性好吧,即使強行加上,效果也是靠左的。

那么,如何做,我的解決方式是這樣的

<android.support.design.widget.AppBarLayout android:id="@+id/appbarlayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:elevation="0dp"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/collapsing_tool_bar" android:layout_width="match_parent" android:layout_height="wrap_content" app:contentScrim="@color/b_G6" app:expandedTitleMarginEnd="10dp" app:expandedTitleMarginStart="10dp" app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> <android.support.constraint.ConstraintLayout  android:layout_width="match_parent"  android:layout_height="match_parent">  <ImageView  android:id="@+id/igame_arena_rank_class_header_bg"  android:layout_width="match_parent"  android:layout_height="0dp"  android:scaleType="centerCrop"  android:src="@drawable/bg_arena_rank_class"  app:layout_constraintDimensionRatio="375:156" />  ......... </android.support.constraint.ConstraintLayout> <android.support.v7.widget.Toolbar  android:id="@+id/common_index_activity_tb_title"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:minHeight="?android:attr/actionBarSize"  android:visibility="visible"  app:contentInsetLeft="0dp"  app:contentInsetStart="0dp"  app:layout_collapseMode="pin">  <include  layout="@layout/igame_common_tool_bar"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:layout_gravity="center" /> </android.support.v7.widget.Toolbar> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout>

然后,include里面的布局是這樣的

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical">//*****請注意這個View*******/// <View android:id="@+id/common_index_activity_view_status_bar" android:layout_width="match_parent" android:layout_height="0dp" /> <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp"> <TextView android:id="@+id/tv_toolbar_bg" android:layout_width="match_parent" android:layout_height="50dp" android:layout_centerInParent="true" tools:background="@color/b_G6" /> <TextView android:id="@+id/common_index_header_tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" android:textColor="@color/b_G99" android:textSize="@dimen/igame_textsize_xl" tools:text="這里是標題" /> <RelativeLayout android:id="@+id/common_index_header_rl_back" android:layout_width="48dp" android:layout_height="48dp" android:layout_centerVertical="true" android:layout_gravity="center_vertical" android:visibility="visible"> <ImageView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true" android:contentDescription="@string/image_desc" android:scaleType="centerInside" android:src="@drawable/igame_actionbar_arrow_left" /> </RelativeLayout> </RelativeLayout></LinearLayout>

Android,沉浸式

效果就是這樣

當然,這時候,標題是需要你自己設置漸隱漸現的。那么,我們依據什么呢?

appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { mTitle.setAlpha(-verticalOffset * 1.0f / appBarLayout.getTotalScrollRange()); } });

依據的就是對appBarLayout的監聽。

2、將statusBar變為透明,且利用他的空間來放我們的布局內容。

 /** * 使狀態欄透明,并覆蓋狀態欄,對API大于19的顯示正常,但小于的界面擴充到狀態欄,但狀態欄不為透明 */ @TargetApi(Build.VERSION_CODES.KITKAT) public static void transparentAndCoverStatusBar(Activity activity) { //FLAG_LAYOUT_NO_LIMITS這個千萬別用,帶虛擬按鍵的機型會有特別多問題// //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); } }

這里是在網上找的一個方法,直接調用即可,但是API需要大于19,相信目前基本上都滿足吧。請注意,我的AppBarLayout中并沒有這個屬性

android:fitsSystemWindows="true"

如果你加了這個屬性,嘿嘿,statusbar雖然空間可以利用,但是有一個你揮之不去的顏色覆蓋在上面,

然后,你還記得上面那個布局中

//*****請注意這個View*******/// <View android:id="@+id/common_index_activity_view_status_bar" android:layout_width="match_parent" android:layout_height="0dp" />

這個作用可大了,就是為了對status_bar原始空間做偏移的,在代碼中,需要動態的改變這個View的高度為statusBar的高度,怎么獲?。?/p>

/** * 獲取狀態欄高度 * * @param context context * @return 狀態欄高度 */ public static int getStatusBarHeight(Context context) { // 獲得狀態欄高度 int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); return context.getResources().getDimensionPixelSize(resourceId); }

完了之后,還需要設置我們自己塞進去的那個toolbar的高度為toolbar的高度加上StatusBar的高度。

3、ViewPager推到actionbar下面就不讓在推了

這個其實需要你CollapsingToolbarLayout里面有一個子view是要使用pin模式的,那么這個子view是誰,顯然就是那個toolbar了

<android.support.v7.widget.Toolbar   android:id="@+id/common_index_activity_tb_title"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:minHeight="?android:attr/actionBarSize"   android:visibility="visible"   app:contentInsetLeft="0dp"   app:contentInsetStart="0dp"   app:layout_collapseMode="pin">   <include   layout="@layout/igame_common_tool_bar"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:layout_gravity="center" />  </android.support.v7.widget.Toolbar>

4、底部控件隨著列表的滑動漸漸隱藏

可以看到,底部的控件是覆蓋在列表上的,列表向上滑動的時候,把他隱藏,就可以空出更多的控件看列表。那么,如何做呢?

既然,我們是包裹在CoordinatorLayout中,那么,顯然,最好的方式是使用layout_behavior了,我這里實現了一個BottomBehavior:

public class BottomBehavior extends CoordinatorLayout.Behavior { private int id; private float bottomPadding; private int screenWidth; private float designWidth = 375.0f;//設計視圖的寬度,通常是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

這個控件,看源碼可以知道,只有當onDependentViewChanged返回ture時,layoutDependsOn才會被回調。bottomPadding是表示一個初始的偏移,因為viewpager本身不是頂在屏幕頂端的(開始被圖片占據了一部分控件),因此,需要扣除這部分占有。

同理,加入讓你實現一個懸浮在左側,右側,滑動隱藏,停止顯示的,也都可以參考類似Behavior的方式,減少代碼耦合。

總結

最后整個布局是這樣子的

<?xml version="1.0" encoding="utf-8"?><com.tencent.igame.view.common.widget.IGameRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/igame_competition_detail_fragment_refresh" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout  android:id="@+id/appbarlayout"  android:layout_width="match_parent"  android:layout_height="wrap_content"  app:elevation="0dp">  <android.support.design.widget.CollapsingToolbarLayout  android:id="@+id/collapsing_tool_bar"  android:layout_width="match_parent"  android:layout_height="wrap_content"  app:contentScrim="@color/b_G6"  app:expandedTitleMarginEnd="10dp"  app:expandedTitleMarginStart="10dp"  app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">  <android.support.constraint.ConstraintLayout   android:layout_width="match_parent"   android:layout_height="match_parent">   <ImageView   android:id="@+id/igame_arena_rank_class_header_bg"   android:layout_width="match_parent"   android:layout_height="0dp"   android:scaleType="centerCrop"   android:src="@drawable/bg_arena_rank_class"   app:layout_constraintDimensionRatio="375:156" />   ............  </android.support.constraint.ConstraintLayout>  <android.support.v7.widget.Toolbar   android:id="@+id/common_index_activity_tb_title"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:minHeight="?android:attr/actionBarSize"   android:visibility="visible"   app:contentInsetLeft="0dp"   app:contentInsetStart="0dp"   app:layout_collapseMode="pin">   <include   layout="@layout/igame_common_tool_bar"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:layout_gravity="center" />  </android.support.v7.widget.Toolbar>  </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <com.tencent.igame.widget.viewpager.IgameViewPager  android:id="@+id/igame_arena_rank_class_vp_content"  android:layout_width="match_parent"  android:layout_height="match_parent"  app:layout_behavior="@string/appbar_scrolling_view_behavior" /> <android.support.constraint.ConstraintLayout  android:layout_width="match_parent"  android:layout_height="60dp"  android:layout_gravity="bottom"  android:background="@color/b_G6"  android:paddingLeft="12dp"  android:paddingRight="12dp"  app:anchor_id="@+id/igame_arena_rank_class_vp_content"  app:bottom_padding="156.0"  app:layout_behavior="com.tencent.igame.common.widget.BottomBehavior">..........底部布局 </android.support.constraint.ConstraintLayout> </android.support.design.widget.CoordinatorLayout></com.tencent.igame.view.common.widget.IGameRefreshLayout>

注:IGameRefreshLayout實際上就是封裝的PullToRefreshView,IgameViewPager是我們封裝的Viewpager,減少每次寫Viewpager的套路代碼。

按照這個框架來,相信你很容易寫出這個樣子的布局。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到Android開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产美女精彩久久| 深夜福利亚洲导航| 欧美视频在线观看免费网址| 欧美国产日韩一区二区| 欧美国产亚洲精品久久久8v| 91精品久久久久久久久久久久久久| 久久久久久av| 亚洲日韩欧美视频| 欧美激情视频三区| 欧美猛男性生活免费| 日韩av网站在线| 久久久久久久久久久av| 美女黄色丝袜一区| 国产精品美女久久| 日本人成精品视频在线| 成年人精品视频| 午夜精品99久久免费| 精品无人国产偷自产在线| 成人激情综合网| 亚洲一区二区在线播放| 中文字幕综合一区| 欧美性猛交99久久久久99按摩| 成人妇女淫片aaaa视频| 久久99精品久久久久久噜噜| 国产欧美精品在线播放| 亚洲精品国产精品国自产在线| 欧美性高跟鞋xxxxhd| 奇门遁甲1982国语版免费观看高清| 91久久精品美女| 国产69精品久久久久99| 欧洲一区二区视频| 日韩福利视频在线观看| 日韩精品亚洲元码| 亚洲剧情一区二区| 精品欧美一区二区三区| 国产一区二区三区精品久久久| 91免费人成网站在线观看18| 欧美在线视频导航| 91在线播放国产| 69视频在线播放| 97热在线精品视频在线观看| 国产精品一区二区久久久| 欧美激情xxxxx| 国产偷亚洲偷欧美偷精品| 国产精品久久久久久久久免费看| 日韩欧美在线视频| 丁香五六月婷婷久久激情| 成人激情视频小说免费下载| 久久久久中文字幕2018| 人妖精品videosex性欧美| 九九热r在线视频精品| 亚洲欧美成人在线| 欧美最近摘花xxxx摘花| 亚洲色图日韩av| 91麻豆国产精品| 九色成人免费视频| 亚洲欧美日韩精品久久奇米色影视| 日韩精品亚洲精品| 精品中文字幕在线观看| 国产精品aaaa| 亚洲国产日韩欧美在线动漫| 精品国产视频在线| 国产日韩欧美中文在线播放| 亚洲综合中文字幕在线观看| 欧美精品一本久久男人的天堂| 国产精品久久久久久久天堂| 亚洲国产精品悠悠久久琪琪| 成人国产在线视频| 懂色av中文一区二区三区天美| 国产99久久精品一区二区 夜夜躁日日躁| 国产精品扒开腿爽爽爽视频| 国产精品入口夜色视频大尺度| 亚洲色图13p| 亚洲香蕉伊综合在人在线视看| 国产一区二区丝袜| 91在线高清视频| 国产一区二区丝袜高跟鞋图片| 国产一区二区在线播放| 最近2019中文字幕mv免费看| 亚洲一区中文字幕在线观看| 日日狠狠久久偷偷四色综合免费| 成人亚洲欧美一区二区三区| 日韩免费在线免费观看| 一本一本久久a久久精品综合小说| 日韩中文娱乐网| 久久精品2019中文字幕| 日韩人在线观看| 国产婷婷97碰碰久久人人蜜臀| 久久青草精品视频免费观看| 欧美高清视频在线观看| 国产日韩av在线| 欧美在线播放视频| 久久青草福利网站| 亚洲成人av片在线观看| 久久天天躁夜夜躁狠狠躁2022| 亚洲精品国产精品自产a区红杏吧| 欧美日韩国产色| 精品亚洲一区二区三区在线播放| 亚洲天堂网站在线观看视频| 久久久91精品国产一区不卡| 欧美大成色www永久网站婷| 97成人精品区在线播放| 亚洲欧美一区二区三区情侣bbw| wwwwwwww亚洲| 亚洲成年人在线播放| 国产精品va在线播放我和闺蜜| 久久精品国产91精品亚洲| 久久精品视频网站| 亚洲成人网av| 国产91免费看片| 久久午夜a级毛片| 日韩中文字幕国产精品| 自拍亚洲一区欧美另类| 日韩av电影在线播放| 亚洲男人天堂2019| 国产精品一区电影| 日韩中文字幕网址| 亚洲成人精品视频在线观看| 黑人巨大精品欧美一区二区三区| 亚洲精品成人久久| 中文字幕国产精品久久| 亚洲一区二区三区四区视频| 久久国产加勒比精品无码| 精品亚洲国产成av人片传媒| 九九精品在线观看| 一本大道香蕉久在线播放29| 国产成人精品a视频一区www| 亚洲少妇中文在线| 亚洲91av视频| 久久免费在线观看| 国产欧亚日韩视频| 国产a级全部精品| 日本伊人精品一区二区三区介绍| 色综合久久久久久中文网| 78色国产精品| 久久久久久美女| 亚洲第一色中文字幕| 日韩在线观看高清| 亚洲曰本av电影| 日产日韩在线亚洲欧美| 欧美丰满片xxx777| 欧美做爰性生交视频| 97在线观看免费高清| 色婷婷综合久久久久| 亚洲综合视频1区| 亚洲高清av在线| 久久久久久12| 亚洲色图17p| 日韩电影免费观看在线观看| 日韩综合视频在线观看| 欧美日韩国产精品专区| 亚洲精品第一国产综合精品| 欧美另类极品videosbest最新版本| 国产精品美女免费视频| 97成人精品视频在线观看| 国产精品96久久久久久又黄又硬| 国产精品香蕉在线观看| 久久精品福利视频| 成人免费网站在线看| 久久天天躁夜夜躁狠狠躁2022| 最好看的2019年中文视频| 国产视频精品久久久| 欧美成人网在线| 在线观看视频亚洲|