Android吸頂效果并有著ViewPager左右切換功能
老規(guī)矩,先上圖,看看是不是你想要的
美團(tuán):

來一個圖形分析
接下來我要寫一個簡單示例,先分析一下布局,見下圖,最外層是NestedScrollView,之后嵌套一個LinearLayout頭部,中間TabLayout選擇器,底部一個ViewPager ViewPager高度需要動態(tài)控制,看自己的需求了,如果是美團(tuán)那種效果,就是 ViewPager高度 = NestedScrollView高度 - TabLayout高度

話不多說,代碼實(shí)現(xiàn)
接下來我寫一個例子,如果按照普通控件的嵌套方式來實(shí)現(xiàn),那么肯定存在滑動沖突,會出現(xiàn)RecyclerView先進(jìn)行滑動其次才是ScrollView滑動,那么就需要先重寫NestedScrollView控件,用于控制最大的滑動距離,當(dāng)達(dá)到最大滑動距離,再分發(fā)給RecyclerView滑動!
NestedScrollView重寫
需要繼承自NestedScrollView并重寫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è)置最大滑動距離
*
* @param maxScrollY 最大滑動距離
*/
fun setMaxScrollY(maxScrollY: Int) {
this.maxScrollY = maxScrollY
}
/**
* @param target 觸發(fā)嵌套滑動的View
* @param dx 表示 View 本次 x 方向的滾動的總距離
* @param dy 表示 View 本次 y 方向的滾動的總距離
* @param consumed 表示父布局消費(fèi)的水平和垂直距離
* @param type 觸發(fā)滑動事件的類型
*/
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)的布局大體寫出這樣的布局
<?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,模擬動態(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,代碼中動態(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)來了)
coordinatorScrollView最大滑動距離即是titleLinerLayout的高度,所以實(shí)現(xiàn)titleLinerLayout的post方法,來監(jiān)聽titleLinerLayout的高度,由于這一塊布局常常是通過網(wǎng)絡(luò)請求后加載,所以,網(wǎng)絡(luò)請求完畢后要再次實(shí)現(xiàn)post設(shè)置coordinatorScrollView最大滑動距離,如第80行代碼和第90行代碼,在這里,我并不推薦使用多次回調(diào)監(jiān)聽的方法!使用post只用調(diào)用一次,如果使用多次監(jiān)聽View變化的方法,應(yīng)該在最后一次網(wǎng)絡(luò)請求完畢后將此監(jiān)聽事件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)
//動態(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() {
//我模擬在頭部動態(tài)添加三個布局,就用圖片代替了,要設(shè)置的圖片高度都是我提前算好的,根據(jù)屏幕的比例來計(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è)置最大滑動距離
titleLinerLayout.post {
coordinatorScrollView.setMaxScrollY(titleLinerLayout.height)
}
//用于請求網(wǎng)絡(luò)后動態(tài)添加子布局
Handler().postDelayed({
val titleView3 = getTitleView(screenWidth * 0.589F, R.mipmap.title3)
titleLinerLayout.addView(titleView3)
//再次設(shè)置最大滑動距離
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])
}
}
/**
* 獲取一個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)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)鍵盤彈出界面上移的實(shí)現(xiàn)思路
這篇文章主要介紹了Android實(shí)現(xià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-10
Android9.0 SystemUI 網(wǎng)絡(luò)信號欄定制修改的流程解析
這篇文章主要介紹了Android9.0 SystemUI 網(wǎng)絡(luò)信號欄定制修改的流程,本文通過圖文實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11
Android基于reclyview實(shí)現(xiàn)列表回彈動畫效果
這篇文章主要為大家詳細(xì)介紹了Android基于reclyview實(shí)現(xiàn)列表回彈動畫效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Android實(shí)現(xiàn)zip文件壓縮及解壓縮的方法
這篇文章主要介紹了Android實(shí)現(xiàn)zip文件壓縮及解壓縮的方法,涉及Android針對文件的遍歷及zip壓縮與解壓縮的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07
Android Studio自定義萬能注釋模板與創(chuàng)建類,方法注釋模板操作
這篇文章主要介紹了Android Studio自定義萬能注釋模板與創(chuàng)建類,方法注釋模板操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
詳解Android端與JavaWeb傳輸加密(DES+RSA)
這篇文章主要介紹了詳解Android端與JavaWeb傳輸加密(DES+RSA),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11

