Android吸頂效果并有著ViewPager左右切換功能
老規(guī)矩,先上圖,看看是不是你想要的
美團(tuán):
來(lái)一個(gè)圖形分析
接下來(lái)我要寫(xiě)一個(gè)簡(jiǎn)單示例,先分析一下布局,見(jiàn)下圖,最外層是NestedScrollView,之后嵌套一個(gè)LinearLayout頭部,中間TabLayout選擇器,底部一個(gè)ViewPager ViewPager高度需要?jiǎng)討B(tài)控制,看自己的需求了,如果是美團(tuán)那種效果,就是 ViewPager高度 = NestedScrollView高度 - TabLayout高度
話不多說(shuō),代碼實(shí)現(xiàn)
接下來(lái)我寫(xiě)一個(gè)例子,如果按照普通控件的嵌套方式來(lái)實(shí)現(xiàn),那么肯定存在滑動(dòng)沖突,會(huì)出現(xiàn)RecyclerView先進(jìn)行滑動(dòng)其次才是ScrollView滑動(dòng),那么就需要先重寫(xiě)NestedScrollView控件,用于控制最大的滑動(dòng)距離,當(dāng)達(dá)到最大滑動(dòng)距離,再分發(fā)給RecyclerView滑動(dòng)!
NestedScrollView重寫(xiě)
需要繼承自NestedScrollView并重寫(xiě)onStartNestedScroll和onNestedPreScroll方法,如下
import android.content.Context import android.util.AttributeSet import android.view.View import androidx.core.view.NestedScrollingParent2 import androidx.core.widget.NestedScrollView /** * @author: shuhuai * @desc: * @date: 2024/11/20 * @version: * @remark */ class CoordinatorScrollview : NestedScrollView, NestedScrollingParent2 { private var maxScrollY = 0 constructor(context: Context?) : super(context!!) constructor(context: Context?, attrs: AttributeSet?) : super( context!!, attrs ) constructor( context: Context?, attrs: AttributeSet?, defStyleAttr: Int ) : super(context!!, attrs, defStyleAttr) override fun onStartNestedScroll( child: View, target: View, axes: Int, type: Int ): Boolean { return true } /** * 設(shè)置最大滑動(dòng)距離 * * @param maxScrollY 最大滑動(dòng)距離 */ fun setMaxScrollY(maxScrollY: Int) { this.maxScrollY = maxScrollY } /** * @param target 觸發(fā)嵌套滑動(dòng)的View * @param dx 表示 View 本次 x 方向的滾動(dòng)的總距離 * @param dy 表示 View 本次 y 方向的滾動(dòng)的總距離 * @param consumed 表示父布局消費(fèi)的水平和垂直距離 * @param type 觸發(fā)滑動(dòng)事件的類(lèi)型 */ override fun onNestedPreScroll( target: View, dx: Int, dy: Int, consumed: IntArray, type: Int ) { if (dy > 0 && scrollY < maxScrollY) { scrollBy(0, dy) consumed[1] = dy } } }
布局文件
我按照美團(tuán)的布局大體寫(xiě)出這樣的布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical" tools:context=".MainActivity"> <!--titleBar--> <LinearLayout android:id="@+id/titleBar" android:layout_width="match_parent" android:layout_height="45dp" android:gravity="center_vertical" android:orientation="horizontal" android:paddingLeft="18dp" android:paddingRight="18dp"> <EditText android:layout_width="0dp" android:layout_height="35dp" android:layout_marginEnd="12dp" android:layout_marginRight="12dp" android:layout_weight="1" android:background="@drawable/edit_style" android:paddingLeft="12dp" android:paddingRight="12dp" /> <TextView android:layout_width="wrap_content" android:layout_height="35dp" android:background="@drawable/button_style" android:gravity="center" android:paddingLeft="15dp" android:paddingRight="15dp" android:text="搜索" android:textColor="#333333" android:textStyle="bold" /> </LinearLayout> <!--coordinatorScrollView--> <com.cyn.mt.CoordinatorScrollview android:id="@+id/coordinatorScrollView" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <!--相當(dāng)于分析圖中頭部的LinearLayout,模擬動(dòng)態(tài)添加的情況--> <LinearLayout android:id="@+id/titleLinerLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" /> <!--相當(dāng)于分析圖中紅色標(biāo)記處TabLayout--> <com.google.android.material.tabs.TabLayout android:id="@+id/tabLayout" android:layout_width="match_parent" android:layout_height="wrap_content" /> <!--相當(dāng)于分析圖中綠色標(biāo)記處ViewPager,代碼中動(dòng)態(tài)設(shè)置高度--> <androidx.viewpager.widget.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </com.cyn.mt.CoordinatorScrollview> </LinearLayout>
Fragment
加入,在Fragment中放入RecyclerView,提供給ViewPager使用,這里代碼就不貼了,可以直接下源碼!源碼在文章末尾!
主要代碼(重點(diǎn)來(lái)了)
coordinatorScrollView最大滑動(dòng)距離即是titleLinerLayout的高度,所以實(shí)現(xiàn)titleLinerLayout的post方法,來(lái)監(jiān)聽(tīng)titleLinerLayout的高度,由于這一塊布局常常是通過(guò)網(wǎng)絡(luò)請(qǐng)求后加載,所以,網(wǎng)絡(luò)請(qǐng)求完畢后要再次實(shí)現(xiàn)post設(shè)置coordinatorScrollView最大滑動(dòng)距離,如第80行代碼和第90行代碼,在這里,我并不推薦使用多次回調(diào)監(jiān)聽(tīng)的方法!使用post只用調(diào)用一次,如果使用多次監(jiān)聽(tīng)View變化的方法,應(yīng)該在最后一次網(wǎng)絡(luò)請(qǐng)求完畢后將此監(jiān)聽(tīng)事件remove掉!
class MainActivity : AppCompatActivity() { //屏幕寬 var screenWidth = 0 //屏幕高 var screenHeight = 0 //tabLayout的文本和圖片 private val tabTextData = arrayOf("常用藥品", "夜間送藥", "隱形眼鏡", "成人用品", "醫(yī)療器械", "全部商家") private val tabIconData = arrayOf( R.mipmap.tab_icon, R.mipmap.tab_icon, R.mipmap.tab_icon, R.mipmap.tab_icon, R.mipmap.tab_icon, R.mipmap.tab_icon ) private var fragmentData = mutableListOf<Fragment>() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) initView() initData() } private fun initView() { //獲取屏幕寬高 val resources: Resources = this.resources val dm: DisplayMetrics = resources.displayMetrics screenWidth = dm.widthPixels screenHeight = dm.heightPixels //狀態(tài)欄沉浸 StatusBarUtil.immersive(this) //titleBar填充 StatusBarUtil.setPaddingSmart(this, titleBar) //狀態(tài)欄字體顏色設(shè)置為黑色 StatusBarUtil.darkMode(this) //動(dòng)態(tài)設(shè)置ViewPager高度 coordinatorScrollView.post { val layoutParams = viewPager.layoutParams layoutParams.width = screenWidth layoutParams.height = coordinatorScrollView.height - tabLayout.height viewPager.layoutParams = layoutParams } } private fun initData() { //我模擬在頭部動(dòng)態(tài)添加三個(gè)布局,就用圖片代替了,要設(shè)置的圖片高度都是我提前算好的,根據(jù)屏幕的比例來(lái)計(jì)算的 val titleView1 = getTitleView(screenWidth * 0.42F, R.mipmap.title1) val titleView2 = getTitleView(screenWidth * 0.262F, R.mipmap.title2) titleLinerLayout.addView(titleView1) titleLinerLayout.addView(titleView2) //設(shè)置最大滑動(dòng)距離 titleLinerLayout.post { coordinatorScrollView.setMaxScrollY(titleLinerLayout.height) } //用于請(qǐng)求網(wǎng)絡(luò)后動(dòng)態(tài)添加子布局 Handler().postDelayed({ val titleView3 = getTitleView(screenWidth * 0.589F, R.mipmap.title3) titleLinerLayout.addView(titleView3) //再次設(shè)置最大滑動(dòng)距離 titleLinerLayout.post { coordinatorScrollView.setMaxScrollY(titleLinerLayout.height) } }, 200) //添加TabLayout for (i in tabTextData.indices) { tabLayout.addTab(tabLayout.newTab()) tabLayout.getTabAt(i)!!.setText(tabTextData[i]).setIcon(tabIconData[i]) //添加Fragment fragmentData.add(TestFragment.newInstance(tabTextData[i])) } //Fragment ViewPager viewPager.adapter = ViewPagerAdapter(supportFragmentManager, fragmentData) //TabLayout關(guān)聯(lián)ViewPager tabLayout.setupWithViewPager(viewPager) //設(shè)置TabLayout數(shù)據(jù) for (i in tabTextData.indices) { tabLayout.getTabAt(i)!!.setText(tabTextData[i]).setIcon(tabIconData[i]) } } /** * 獲取一個(gè)title布局 * 我這里就用三張圖片模擬的 * * @height 要設(shè)置的圖片高度 */ private fun getTitleView(height: Float, res: Int): View { val inflate = from(this).inflate(R.layout.title_layout, null, false) val layoutParams = inflate.titleImage.layoutParams layoutParams.width = screenWidth layoutParams.height = height.toInt() inflate.titleImage.setImageResource(res) return inflate } }
最終效果
到此這篇關(guān)于Android吸頂效果,并有著ViewPager左右切換的文章就介紹到這了,更多相關(guān)android ViewPager左右切換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android ViewPager實(shí)現(xiàn)頁(yè)面左右切換效果
- 基于Android實(shí)現(xiàn)一個(gè)常用的布局吸頂效果
- Android進(jìn)階CoordinatorLayout協(xié)調(diào)者布局實(shí)現(xiàn)吸頂效果
- Android進(jìn)階NestedScroll嵌套滑動(dòng)機(jī)制實(shí)現(xiàn)吸頂效果詳解
- Android實(shí)現(xiàn)上拉吸頂效果
- Android RecyclerView實(shí)現(xiàn)懸浮吸頂、分隔線、到底提示效果
- android中RecyclerView懸浮吸頂效果
相關(guān)文章
Android實(shí)現(xiàn)鍵盤(pán)彈出界面上移的實(shí)現(xiàn)思路
這篇文章主要介紹了Android實(shí)現(xiàn)鍵盤(pán)彈出界面上移的實(shí)現(xiàn)思路,需要的朋友可以參考下2018-04-04實(shí)例解析Android中使用Pull解析器解析XML的方法
這篇文章主要介紹了Android中使用Pull解析器解析XML的方法,與DOM和SAX解析方式相比人們更推崇Pull,需要的朋友可以參考下2016-04-04快速調(diào)試Android應(yīng)用系統(tǒng)修改ro.debuggable屬性的兩種方式
這篇文章主要為大家介紹了快速調(diào)試Android應(yīng)用系統(tǒng)修改ro.debuggable屬性的兩種方式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10Android獲取應(yīng)用版本號(hào)與版本名稱(chēng)
這篇文章主要介紹了Android獲取應(yīng)用版本號(hào)與版本名稱(chēng)的相關(guān)資料,需要的朋友可以參考下2016-03-03Android9.0 SystemUI 網(wǎng)絡(luò)信號(hào)欄定制修改的流程解析
這篇文章主要介紹了Android9.0 SystemUI 網(wǎng)絡(luò)信號(hào)欄定制修改的流程,本文通過(guò)圖文實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11Android基于reclyview實(shí)現(xiàn)列表回彈動(dòng)畫(huà)效果
這篇文章主要為大家詳細(xì)介紹了Android基于reclyview實(shí)現(xiàn)列表回彈動(dòng)畫(huà)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04Android實(shí)現(xiàn)zip文件壓縮及解壓縮的方法
這篇文章主要介紹了Android實(shí)現(xiàn)zip文件壓縮及解壓縮的方法,涉及Android針對(duì)文件的遍歷及zip壓縮與解壓縮的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07Android Studio自定義萬(wàn)能注釋模板與創(chuàng)建類(lèi),方法注釋模板操作
這篇文章主要介紹了Android Studio自定義萬(wàn)能注釋模板與創(chuàng)建類(lèi),方法注釋模板操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-03-03詳解Android端與JavaWeb傳輸加密(DES+RSA)
這篇文章主要介紹了詳解Android端與JavaWeb傳輸加密(DES+RSA),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11