仿掘金顶部导航栏Kotlin源码

本文介绍了一个使用Kotlin编写的安卓应用顶部导航栏的实现方法。通过自定义RadioGroup和ViewPager来创建一个灵活且可扩展的导航栏,支持动态添加多个分类。此外,文章还分享了如何保持导航栏与页面之间的同步状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

效果图如下:

代码100%用kotlin实现,主要代码如下: MainActivity.kt

class MainActivity : AppCompatActivity() {
lateinit var lineNav:RadioGroup
lateinit var vpRadio:ViewPager
lateinit var scroll:HorizontalScrollView
private val titles = arrayOf("人物", "人生", "心灵", "情感", "成长", "处世", "视野", "美文", "青春",
        "生活", "智慧", "乐活")
private lateinit var radioIds: MutableMap<String, Int>
private lateinit var radioNames: MutableMap<Int, String>
private lateinit var fragments: MutableList<Fragment>

private lateinit var activity:Activity
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    lineNav = findViewById(R.id.line_top)
    vpRadio = findViewById(R.id.vp_radio)
    scroll = findViewById(R.id.hor_scroll)
    activity=this
    initViews()
}

fun initViews() {
    //设置导航栏
    val wm = this.windowManager
    val dm = DisplayMetrics()
    wm.defaultDisplay.getMetrics(dm)
    val width = dm.widthPixels
    val params = LinearLayout.LayoutParams((width / 4.5).toInt(), ViewGroup.LayoutParams.MATCH_PARENT)
    params.setMargins(10, 0, 0, 0)
    radioIds = mutableMapOf()
    radioNames = mutableMapOf()
    for (item in titles) {
        val itemView = LayoutInflater.from(this).inflate(R.layout.radio_top_nav, null) as RadioButton
        itemView.text = item
        itemView.layoutParams = params
        itemView.id = item.hashCode()
        //保存id 用来viewPager翻页时更新radioGroup选中状态
        radioIds.put(item, itemView.id)
        //保存title 用来radioGroup点击的时候更新vp页面
        radioNames.put(itemView.id, item)
        lineNav.addView(itemView)
    }
    lineNav.invalidate()
    (lineNav.getChildAt(0) as RadioButton).isChecked = true
    lineNav.setOnCheckedChangeListener { _, checkedId ->
        vpRadio.currentItem = titles.indexOf(radioNames[checkedId])
    }
    //设置页面
    fragments = mutableListOf()
    for (item in titles) {
        val b = Bundle()
        b.putString("title", item)
        val itemFragment = DemoFragment()
        itemFragment.arguments = b
        fragments.add(itemFragment)
    }
    vpRadio.adapter = FragmentAdapter(supportFragmentManager, fragments)
    vpRadio.currentItem = 0
    vpRadio.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
        override fun onPageScrollStateChanged(p0: Int) {
            if (p0 == 2) {
                radioIds[titles[vpRadio.currentItem]]?.let { lineNav.check(it) }

                //更新scroll滑动位置
                val rb: RadioButton? = radioIds[titles[vpRadio.currentItem]]?.let { findViewById(it)}
                val scrollX = scroll.scrollX
                val left = rb!!.left
                val leftScreen = left - scrollX
                scroll.smoothScrollBy(leftScreen - (width / 2)+rb.width/2, 0)
            }
        }

        override fun onPageScrolled(p0: Int, p1: Float, p2: Int) {
        }

        override fun onPageSelected(p0: Int) {
        }
    })
}
}
复制代码

FragmentAdapter.kt

class FragmentAdapter(fm: FragmentManager?, var mFragments: MutableList<Fragment>) : FragmentPagerAdapter(fm) {


override fun getItem(p0: Int): Fragment {
    return mFragments.get(p0)
}

override fun getCount(): Int {
    return mFragments.size
}
}
复制代码

github地址:https://github.com/limhGeek/TopNavDemo.git

转载于:https://juejin.im/post/5a31dc51f265da431a4333ae

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值