Android kotlin 实现仿蜜源ViewPager和指示器对应上面TabLayout功能
一、实现效果
二、引入依赖
在app
的build.gradle
在添加以下代码
1、TabLayout
:implementation 'com.google.android.material:material:1.1.0'
2、implementation 'com.github.li-xiaojun:StateLayout:1.3.4'
//allprojects {…增加:maven { url ‘https://jitpack.io’ }…}
3、implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.6'
,这个里面带的适配器,直接调用就即可
这依赖包还需要得到要添加,在Project
的build.gradle
在添加以下代码,不添加就不行
allprojects {
repositories {
...
maven { url "https://jitpack.io" }//加上
}
}
三、源码实现
1、ViewPager实体类
PageInfo.java
package com.example.myapplication3.bean;
import com.example.myapplication3.fragment.BaseFragment;
public class PageInfo {
// public String title;
public BaseFragment fragment;
// public PageInfo(String title, BaseFragment fragment) {
// this.title = title;
// this.fragment = fragment;
// }
public PageInfo(BaseFragment fragment) {
this.fragment = fragment;
}
}
ViewPager
两个页面,TestFragment1.kt
和TestFragment2.tk
的代码一样,布局也一样,自己写就即可
TestFragment1.kt
package com.example.myapplication3.fragment
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.myapplication3.R
import com.example.myapplication3.adapter.RvAdapter
import kotlinx.android.synthetic.main.testfragment1.recyclerView
class TestFragment1 : BaseFragment(){
private val mAdapter by lazy {
RvAdapter().apply {
// setOnItemLongClickListener(activity)
}
}
override val layoutId: Int = R.layout.testfragment1
override fun init(view: View?) {
val itemList: MutableList<String> = ArrayList()
for (i in 0..2) {
itemList.add("position $i")
}
val layoutManager = LinearLayoutManager(activity)
layoutManager.orientation = LinearLayoutManager.HORIZONTAL
recyclerView.layoutManager = layoutManager
recyclerView.adapter = mAdapter
mAdapter.setList(itemList)
}
}
testfragment1.kt
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
列表适配器RvAdapter.kt
package com.example.myapplication3.adapter
import android.widget.TextView
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.viewholder.BaseViewHolder
import com.example.myapplication3.R
class RvAdapter(layoutResId: Int = R.layout.rv_item) : BaseQuickAdapter<String, BaseViewHolder>(layoutResId) {
override fun convert(holder: BaseViewHolder, item: String) {
val itemTv = holder.getView<TextView>(R.id.item_tv)
itemTv.text = item
}
}
rv_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_width="112dp"
android:layout_height="112dp"
android:foreground="?android:attr/selectableItemBackground"
card_view:cardBackgroundColor="@color/light_gray"
card_view:cardCornerRadius="20dp"
card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/iv"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_gravity="center"
android:src="@mipmap/ic_c" />
<TextView
android:id="@+id/item_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="测试"
android:textSize="14dp"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
colors.xml
中添加的颜色
<color name="black">#000000</color><!-- 黑色 -->
<color name="white">#FFFFFFFF</color><!-- 白色 -->
<color name="gray">#959595</color><!-- 灰色 -->
<color name="light_gray">#E7E7E7</color><!-- 浅灰 -->
<color name="red">#FF0000</color><!-- 红色 -->
<color name="yellow">#FFC107</color><!-- 黄色 -->
<color name="purple">#FFBB86FC</color><!-- 紫色 -->
这两个页面代码要继承父类BaseFragment()
,BaseFragment.kt
package com.example.myapplication3.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.lxj.statelayout.StateLayout
abstract class BaseFragment : Fragment() {
var vieww: View? = null
var isInit = false
var stateLayout: StateLayout? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
if (vieww == null) {
vieww = inflater.inflate(layoutId, container, false)
stateLayout = StateLayout(requireContext()).wrap(vieww).showLoading()
}
return stateLayout
}
override fun onResume() {
super.onResume()
safeInit()
}
private fun safeInit() {
if (userVisibleHint && vieww != null) {
if (!isInit) {
isInit = true
init(vieww)
stateLayout!!.postDelayed({ stateLayout!!.showContent() }, 300)
}
}
}
override fun setUserVisibleHint(isVisibleToUser: Boolean) {
super.setUserVisibleHint(isVisibleToUser)
safeInit()
}
protected abstract val layoutId: Int
abstract fun init(view: View?)
fun toast(msg: String?) {
// Toast.makeText(XPopupApp.context, msg, Toast.LENGTH_SHORT).show();
}
}
2、指示器样式(自定义类)
自定义ViewPagerIndicator.kt
package com.example.myapplication3.view
import android.content.Context
import android.graphics.Canvas
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.widget.FrameLayout
import androidx.annotation.Nullable
import androidx.viewpager.widget.ViewPager
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
import com.example.myapplication3.R
class ViewPagerIndicator @JvmOverloads constructor(
context: Context,
@Nullable attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) :
FrameLayout(context, attrs, defStyleAttr) {
// private val rootView: View
private val mRootView: View
private val indView: View
var indViewWidth = 0
init {
val root = inflate(context, R.layout.app_viewpager_indicator, this)
mRootView = root.findViewById<View>(R.id.root)
indView = root.findViewById<View>(R.id.ind_view)
}
override fun draw(canvas: Canvas) {
super.draw(canvas)
}
fun setWithViewPager(viewPager: ViewPager) {
//如果没有adapter,则隐藏不显示
if (null == viewPager.adapter) {
visibility = GONE
Log.e(javaClass.simpleName, "no adapter")
return
}
//获取viewPager中fragment的数量
val count = viewPager.adapter!!.count
if (count == 0) {
return
}
//加载到window之后再进行view宽度的获取
mRootView.post(Runnable { //获取当前滑块的宽度
indViewWidth = width / count
val layoutParams = indView.layoutParams as LayoutParams
layoutParams.width = indViewWidth
indView.layoutParams = layoutParams
})
viewPager.addOnPageChangeListener(object : OnPageChangeListener {
/**
*
* @param position
* @param positionOffset [0,1]中的值,指示在位置处与页面的偏移百分比。
* @param positionOffsetPixels 以像素为单位的值,表示与位置的偏移量。
*/
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
//获取滑块距父布局左侧的距离
val left = (position * indViewWidth + positionOffset * indViewWidth).toInt()
//重新布局滑块view
indView.layout(left, indView.top, left + indViewWidth, indView.bottom)
}
override fun onPageSelected(position: Int) {}
override fun onPageScrollStateChanged(state: Int) {}
})
}
}
指示器布局app_viewpager_indicator.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/shape_indicator_radius_gray">
<View
android:id="@+id/ind_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shape_indicator_radius_yellow"/>
</FrameLayout>
指示器背景灰色shape_indicator_radius_gray.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/gray" />
<corners android:radius="50dp" />
</shape>
指示器黄色shape_indicator_radius_yellow.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/yellow" />
<corners android:radius="50dp" />
</shape>
3、主视图实现
MainActivity.kt
package com.example.myapplication3
import android.graphics.Typeface
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter
import com.example.myapplication3.bean.PageInfo
import com.example.myapplication3.fragment.TestFragment1
import com.example.myapplication3.fragment.TestFragment2
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayout.OnTabSelectedListener
import kotlinx.android.synthetic.main.activity_main.indicator
import kotlinx.android.synthetic.main.activity_main.tablayout
import kotlinx.android.synthetic.main.activity_main.viewPager
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
init()
}
private fun init() {
//TabLayout添加自定义分割线并且可以修改分割线高度
val linearLayout = tablayout.getChildAt(0) as LinearLayout
linearLayout.showDividers = LinearLayout.SHOW_DIVIDER_MIDDLE
linearLayout.dividerDrawable = ContextCompat.getDrawable(this, R.drawable.layout_divider_vertical)
// linearLayout.dividerPadding = 50
linearLayout.dividerPadding = 23
viewPager.adapter = MainAdapter(supportFragmentManager)
viewPager.currentItem = 0 //当前值设置为1才能仅显示一个默认视图
tablayout.setupWithViewPager(viewPager)
//****新代码**
tablayout.getTabAt(0)?.setCustomView(R.layout.text)
val toMyTextView1 = tablayout.getTabAt(0)?.customView?.findViewById<TextView>(R.id.textView)
toMyTextView1?.typeface = Typeface.defaultFromStyle(Typeface.BOLD)
toMyTextView1?.textSize = 15F
toMyTextView1?.setTextColor(resources.getColor(R.color.black))
toMyTextView1?.text = "热销好货"
tablayout.getTabAt(1)?.setCustomView(R.layout.text)
val toMyTextView2 = tablayout.getTabAt(1)?.customView?.findViewById<TextView>(R.id.textView)
toMyTextView2?.textSize = 12F
toMyTextView2?.setTextColor(resources.getColor(R.color.gray))
toMyTextView2?.text = "图文直播"
//****
indicator.setWithViewPager(viewPager)
tablayout.addOnTabSelectedListener(object : OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
tab?.customView?.findViewById<TextView>(R.id.textView)?.isSelected = true
val tv = tab?.customView?.findViewById<TextView>(R.id.textView)
tv?.typeface = Typeface.defaultFromStyle(Typeface.BOLD)//加粗
tv?.textSize = 15F//直接用setTextSize(15F)也一样
tv?.setTextColor(resources.getColor(R.color.black))
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
tab?.customView?.findViewById<TextView>(R.id.textView)?.isSelected = false
val tv = tab?.customView?.findViewById<TextView>(R.id.textView)
tv?.textSize = 12F
tv?.setTextColor(resources.getColor(R.color.gray))
}
override fun onTabReselected(tab: TabLayout.Tab?) {
Log.i("Tag","onTabReselected = ${tab?.position}")
}
})
}
class MainAdapter(fm: FragmentManager?) : FragmentPagerAdapter(fm!!) {
private val pageInfos = arrayOf(
PageInfo(TestFragment1()),
PageInfo(TestFragment2()),
)
override fun getItem(i: Int): Fragment {
return pageInfos[i].fragment
}
override fun getCount(): Int {
return pageInfos.size
}
// override fun getPageTitle(position: Int): CharSequence? {
// return pageInfos[position].title
// }
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dp"
android:background="@drawable/shape_indicator_radius_white"
android:padding="10dp">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/bar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@color/white"
app:elevation="0dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tablayout"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_alignParentLeft="true"
android:layout_centerInParent="true"
android:overScrollMode="never"
app:tabContentStart="10dp"
app:tabIndicator="@drawable/tab_indicator"
app:tabIndicatorColor="@color/yellow"
app:tabMode="scrollable"
app:tabRippleColor="@android:color/transparent"
app:tabSelectedTextColor="@color/black"
app:tabTextColor="@color/gray">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="热销好货" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="图文直播" />
</com.google.android.material.tabs.TabLayout>
<!-- app:tabBackground="@color/yellow"
app:tabTextAppearance="@style/TabLayoutTextStyle"-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerInParent="true"
android:text="更多 >" />
</RelativeLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager.widget.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="112dp"
android:layout_below="@id/bar" />
<com.example.myapplication3.view.ViewPagerIndicator
android:id="@+id/indicator"
android:layout_width="40dp"
android:layout_height="5dp"
android:layout_below="@id/viewPager"
android:layout_centerInParent="true" />
</RelativeLayout>
布局圆角shape_indicator_radius_white.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white" />
<corners android:radius="10dp" />
</shape>
TabLayout
下的下划线样式tab_indicator.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="20dp"
android:height="2dp"
android:gravity="center">
<shape>
<corners android:radius="1dp" />
</shape>
</item>
</layer-list>
更多推荐
所有评论(0)