<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android仿美團(tuán)滑動(dòng)標(biāo)題欄漸變效果

          共 6896字,需瀏覽 14分鐘

           ·

          2022-03-23 11:13

          最近公司的項(xiàng)目剛好需要這個(gè)效果,雖然GitHub上有很多成型的開(kāi)源項(xiàng)目,不過(guò)都附帶了很多其他的東西,為了這個(gè)效果去引用一個(gè)第三方庫(kù)明顯不合適,所以就決定自力更生了。


          其實(shí)在日常軟件中還是挺常見(jiàn)的,比如帶Banner廣告圖的首頁(yè)或者是帶頭部的個(gè)人中心,下面是美團(tuán)的實(shí)現(xiàn)效果:



          實(shí)現(xiàn)思路:


          看下美團(tuán)的效果圖,其實(shí)就可以很明顯的發(fā)現(xiàn)頭部(標(biāo)題欄+狀態(tài)欄)其實(shí)是沒(méi)有動(dòng)的,只是一開(kāi)始呈透明裝,然后隨著內(nèi)容的向上滑動(dòng)在某個(gè)坐標(biāo)點(diǎn)開(kāi)始漸變顏色。


          基于這樣的思考,我們把代碼實(shí)現(xiàn)拆分3點(diǎn):
          1、整體界面是個(gè)ScrollView,并且我們需要對(duì)滑動(dòng)進(jìn)行監(jiān)聽(tīng)
          2、確定坐標(biāo)點(diǎn),在什么時(shí)候開(kāi)始變色,在什么時(shí)候停止變色
          3、需要將狀態(tài)欄透明化,并且讓我們的內(nèi)容區(qū)域可以擴(kuò)展到狀態(tài)欄


          好了,理清思路,我們就可以開(kāi)始干活了!


          先看下我們實(shí)現(xiàn)的效果:



          ObservableScrollView的實(shí)現(xiàn)


          雖然谷歌官方給ScrollView提供了一個(gè)設(shè)置滑動(dòng)監(jiān)聽(tīng)方法setOnScrollChangeListener,不過(guò)這個(gè)方法需要基于API23之上(Android6.0系統(tǒng)),在日常開(kāi)發(fā)中,我們需要對(duì)老系統(tǒng)用戶進(jìn)行兼容(當(dāng)前兼容版本為Android4.1系統(tǒng)以上),所以這里我們需要去繼承ScrollView并把這個(gè)監(jiān)聽(tīng)事件通過(guò)接口的方式對(duì)外暴露,這里把這個(gè)View取名為ObservableScrollView。

          /**?*?重寫(xiě)ScrollView對(duì)外拋出滑動(dòng)監(jiān)聽(tīng)數(shù)據(jù) */public class ObservableScrollView extends ScrollView {
          /** * 回調(diào)接口監(jiān)聽(tīng)事件 */ private OnObservableScrollViewListener mOnObservableScrollViewListener;
          public ObservableScrollView(Context context) { super(context); }
          public ObservableScrollView(Context context, AttributeSet attrs) { super(context, attrs); }
          public ObservableScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }

          /** * 添加回調(diào)接口,便于把滑動(dòng)事件的數(shù)據(jù)向外拋 */ public interface OnObservableScrollViewListener { void onObservableScrollViewListener(int l, int t, int oldl, int oldt); }
          /** * 注冊(cè)回調(diào)接口監(jiān)聽(tīng)事件 * * @param onObservableScrollViewListener */ public void setOnObservableScrollViewListener(OnObservableScrollViewListener onObservableScrollViewListener) { this.mOnObservableScrollViewListener = onObservableScrollViewListener; }
          /** * This is called in response to an internal scroll in this view (i.e., the * view scrolled its own contents). This is typically as a result of * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been * called. * * @param l Current horizontal scroll origin. 當(dāng)前滑動(dòng)的x軸距離 * @param t Current vertical scroll origin. 當(dāng)前滑動(dòng)的y軸距離 * @param oldl Previous horizontal scroll origin. 上一次滑動(dòng)的x軸距離 * @param oldt Previous vertical scroll origin. 上一次滑動(dòng)的y軸距離 */ @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (mOnObservableScrollViewListener != null) { //將監(jiān)聽(tīng)到的數(shù)據(jù)向外拋 mOnObservableScrollViewListener.onObservableScrollViewListener(l, t, oldl, oldt); } }}


          開(kāi)始變色的坐標(biāo)點(diǎn)


          首先我們需要先了解Android系統(tǒng)的坐標(biāo)軸,這里不像我們以前學(xué)數(shù)學(xué)的坐標(biāo)軸一樣,在中心建軸,以中心向上和右為正方向,向下和左為負(fù)方向。


          在Android系統(tǒng)里是以屏幕的左上角為原點(diǎn)(0,0),向右為X正軸,向下為Y正軸。


          知道了坐標(biāo)系,我們?cè)賮?lái)分解下效果圖:





          一開(kāi)始標(biāo)題欄和狀態(tài)欄呈透明色,隨著頁(yè)面的向上滑動(dòng)標(biāo)題欄和狀態(tài)欄開(kāi)始變色,當(dāng)A點(diǎn)達(dá)到B點(diǎn)的時(shí)候完成顏色的完整變化,這里我們只需要測(cè)量出A點(diǎn)到B點(diǎn)的距離,然后跟ScrollView所監(jiān)聽(tīng)到的滑動(dòng)距離相比對(duì)并作出相對(duì)應(yīng)的顏色變化,這樣就可以了,其中的A點(diǎn)到頂部的距離和B點(diǎn)到頂部的距離,我們可以通過(guò)ViewTreeObserver得到對(duì)應(yīng)的高度,然后相減即可。


          實(shí)現(xiàn)代碼:

          /**?*?高仿美團(tuán)APP頁(yè)面滑動(dòng)標(biāo)題欄漸變效果 */public class MainActivity extends AppCompatActivity implements ObservableScrollView.OnObservableScrollViewListener {
          private ObservableScrollView mObservableScrollView; private TextView mImageView; private LinearLayout mHeaderContent;
          private int mHeight;
          @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //設(shè)置透明狀態(tài)欄 StatusbarUtils.enableTranslucentStatusbar(this); setContentView(R.layout.activity_main);
          //初始化控件 mObservableScrollView = (ObservableScrollView) findViewById(R.id.sv_main_content); mImageView = (TextView) findViewById(R.id.iv_main_topImg); mHeaderContent = (LinearLayout) findViewById(R.id.ll_header_content);
          //獲取標(biāo)題欄高度 ViewTreeObserver viewTreeObserver = mImageView.getViewTreeObserver(); viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { mImageView.getViewTreeObserver().removeOnGlobalLayoutListener(this); mHeight = mImageView.getHeight() - mHeaderContent.getHeight();//這里取的高度應(yīng)該為圖片的高度-標(biāo)題欄 //注冊(cè)滑動(dòng)監(jiān)聽(tīng) mObservableScrollView.setOnObservableScrollViewListener(MainActivity.this); } }); }

          /** * 獲取ObservableScrollView的滑動(dòng)數(shù)據(jù) * * @param l * @param t * @param oldl * @param oldt */ @Override public void onObservableScrollViewListener(int l, int t, int oldl, int oldt) { if (t <= 0) { //頂部圖處于最頂部,標(biāo)題欄透明 mHeaderContent.setBackgroundColor(Color.argb(0, 48, 63, 159)); } else if (t > 0 && t < mHeight) { //滑動(dòng)過(guò)程中,漸變 float scale = (float) t / mHeight;//算出滑動(dòng)距離比例 float alpha = (255 * scale);//得到透明度 mHeaderContent.setBackgroundColor(Color.argb((int) alpha, 48, 63, 159)); } else { //過(guò)頂部圖區(qū)域,標(biāo)題欄定色 mHeaderContent.setBackgroundColor(Color.argb(255, 48, 63, 159)); } }
          }


          透明狀態(tài)欄的實(shí)現(xiàn)


          關(guān)于透明狀態(tài)欄這個(gè)東西,國(guó)內(nèi)很多人把它叫成沉浸式狀態(tài)欄,有人認(rèn)同有人反對(duì),因?yàn)楣雀韫俜綄?duì)這個(gè)沒(méi)有具體的定義,所以這里我就不發(fā)表看法了,反正我們就是要讓狀態(tài)欄變成透明,然后內(nèi)容區(qū)域可以擴(kuò)展到狀態(tài)欄,這樣就可以了。


          1、首先我們需要對(duì)app的風(fēng)格進(jìn)行設(shè)置:

              


          2、再來(lái)我們要對(duì)狀態(tài)欄進(jìn)行透明化處理,其實(shí)這個(gè)東西我們也可以在xml里去做設(shè)置android:windowTranslucentStatus,不過(guò)現(xiàn)在國(guó)產(chǎn)手機(jī)滿天飛的ROM真是無(wú)奈,有些奇葩的機(jī)型是沒(méi)辦法識(shí)別的,所以這里為了更好的兼容,我們可以在代碼里面去實(shí)現(xiàn)。首先,我們需要判斷當(dāng)前的手機(jī)系統(tǒng)版本,4.4以上和5.0以上的處理方法是有區(qū)別的,具體實(shí)現(xiàn)代碼:

          /**?*?設(shè)置系統(tǒng)狀態(tài)欄和導(dǎo)航欄透明化 */
          public class StatusbarUtils { /** * 啟用 透明狀態(tài)欄 * * @param activity */ public static void enableTranslucentStatusbar(Activity activity) {

          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { Window window = activity.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); }
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = activity.getWindow(); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(Color.TRANSPARENT); window.setNavigationBarColor(Color.TRANSPARENT); } }}


          在4.4以上及5.0以下的系統(tǒng)狀態(tài)欄會(huì)成半透明狀,在5.0及以上的系統(tǒng)可以實(shí)現(xiàn)完全透明。


          如果此時(shí)你運(yùn)行了代碼你會(huì)發(fā)現(xiàn),雖然狀態(tài)欄透明化了,但是我們的布局內(nèi)容并沒(méi)有擴(kuò)展到狀態(tài)欄中,這里需要而外的提到一個(gè)屬性fitsSystemWindows它是在Android4.4系統(tǒng)以后引入的,當(dāng)你的內(nèi)容需要顯示在系統(tǒng)作用域中時(shí)(比如頂部狀態(tài)欄,底部導(dǎo)航欄等),此時(shí)你需要在相關(guān)的第一個(gè)View屬性中添加該屬性,并設(shè)置屬性值為true,它會(huì)按照View的排列順序進(jìn)行深度優(yōu)先的作用在View上。


          3、實(shí)現(xiàn)了以上的操作后,我們基本上已經(jīng)成功了,此時(shí)你會(huì)發(fā)現(xiàn)你的標(biāo)題欄已經(jīng)可以擴(kuò)展到透明的系統(tǒng)狀態(tài)欄了,不過(guò)此時(shí)你會(huì)發(fā)現(xiàn),狀態(tài)欄離你的標(biāo)題欄太靠近了,如果你想實(shí)現(xiàn)和上面效果圖一樣的效果,只需要在你的標(biāo)題欄添加一個(gè)paddingTop值就可以,一般系統(tǒng)是25dp,當(dāng)然如果你采用代碼動(dòng)態(tài)獲取的方式也是可以的,這樣可以做好更好的適配,畢竟國(guó)內(nèi)各大廠商都有自己的一套標(biāo)準(zhǔn)。


          具體實(shí)現(xiàn)代碼:


          activity_mian.xml

              xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent">
          android:id="@+id/sv_main_content" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:scrollbars="none">
          android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical">
          android:id="@+id/tv_main_topContent" android:layout_width="match_parent" android:layout_height="280dp" android:background="#b5b433" android:gravity="center" android:src="@mipmap/ic_launcher" android:text="我是頭部" android:textSize="22sp" />
          android:layout_width="match_parent" android:layout_height="600dp" android:background="#ffffff" android:gravity="center" android:src="@mipmap/ic_launcher" android:text="我是內(nèi)容" android:textSize="22sp" />

          ????


          include_header_itl.xml

              android:id="@+id/ll_header_content"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="#00000000"    android:fitsSystemWindows="true"    android:orientation="vertical">
          android:layout_width="match_parent" android:layout_height="80dp" android:orientation="horizontal" android:paddingTop="25dp">
          android:id="@+id/iv_header_left" android:layout_width="40dp" android:layout_height="match_parent" android:paddingLeft="8dp" android:paddingRight="12dp" android:src="@mipmap/icon_header_back" />

          android:id="@+id/tv_header_title" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_centerHorizontal="true" android:ellipsize="end" android:gravity="center" android:maxLines="2" android:text="我是標(biāo)題" android:textColor="#ffffff" android:textSize="16sp" android:textStyle="bold" />

          android:id="@+id/iv_header_img" android:layout_width="40dp" android:layout_height="match_parent" android:layout_alignParentRight="true" android:layout_gravity="center" android:paddingLeft="12dp" android:paddingRight="8dp" android:src="@mipmap/icon_header_kefu" />


          源碼地址:

          https://github.com/Lichenwei-Dev/ObservableScrollView


          到這里就結(jié)束啦。


          瀏覽 133
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  大香蕉伊在视频 | 日韩插穴| 小黄片免费 | 欧美色色资源 | 豆花视频在线看 |