Android-自定义流布局标签

简介: Android-自定义流布局标签
效果

效果分析
  • 标签支持居左,居右,居中显示
  • 标签支持设置最大显示行数
  • 支持展开,折叠
分析思路

流布局标签,在日常应用中使用特别的广,使用场景及使用花样也很多,这里简单介绍其中的几点。

  • 功能1: 标签展示的方式:左 中 右 三种
  • 功能2: 标签支持折叠和展开,以及折叠时行数的控制

当我们需要做一种效果,或者需要自定义View的时候,本着 "不重复造轮子" 的方式来进行实现

像这种流布局最初大部分都是自定义ViewGrop来实现,自从google的flexbox发布,基本上都是用这个库来实现流布局效果。那么本文也是采用flexbox中的 FlexboxLayoutManager 来实现我们的效果,如果你对FlexboxLayoutManager有所了解的话,就知道是多么的方便。

流布局
recyclerView?.layoutManager = FlexboxLayoutManager(this)

为Recycleview设置为FlexboxLayoutManager的layoutManager就支持流布局展示了。

居左|居中|居右
//居左
setJustifyContent(JustifyContent.FLEX_START)
//居中
setJustifyContent(JustifyContent.CENTER)
//居右
setJustifyContent(JustifyContent.FLEX_END)

就是方便,现成的轮子就是爽啊!


固定最大显示行数

有的时候,我们会有固定行数的需求,当数据已经超出我们固定的行数时,只展示固定行数据,其他的裁掉,当点击展开的时候再显示所有数据。我们就带着这个需求去看下FlexboxLayoutManager有没有现成的方法。 诶,我找到了一个setMaxLine方法

   @Override
    public void setMaxLine(int maxLine) {
        if (mMaxLine != maxLine) {
            mMaxLine = maxLine;
            requestLayout();
        }
    }

字面上就是设置最大行的意思,马上试了一下:

setMaxLine(4)

效果出来是这样的

看来只能自己想办法了,本着 "有问题就谷歌,没谷歌看源码"的方式来搞他,一堆操作猛如虎。终于找到了

 override fun getFlexLinesInternal(): MutableList<FlexLine> {
        val originList = super.getFlexLinesInternal()
        //数据 总行数
        val totalLines = originList.size
        //总行数>设定行数,进行折叠
        if (totalLines > mLineCount) {
            //对数据处理(清理从设定行到最大行的数据)
            originList.subList(mLineCount, totalLines).clear()
            //当前状态不是折叠状态时,再处理状态改变回调及状态更新,防止返回多次问题
            if (mState != State.FOLD) {
                foldStateListener?.stateChange(State.FOLD)
                mState = State.FOLD
            }
        }
        //没有设置行数时,默认打开状态
        if (mLineCount == NOT_SET) {
            //当前状态不是打开状态,进行打开操作,并回调状态改变
            if (mState != State.OPEN) {
                foldStateListener?.stateChange(State.OPEN)
                mState = State.OPEN
            }
        }
        return originList
    }
    

根据判断当前行数是否大于设定的固定行数来进行数据裁剪来达到折叠的效果。代码比较的简单,全部贴出来

自定义 FlexboxLayoutManager

class MYFlexboxLayoutManager @JvmOverloads constructor(context: Context, var space: Int = 0) : FlexboxLayoutManager(context) {

    private var NOT_SET = Integer.MAX_VALUE

    private var mLineCount = NOT_SET

    private var mLinesCountTemp = NOT_SET

    private var mState = State.INIT

    var foldStateListener: OnFoldStateListener? = null

    enum class State {
        INIT, OPEN, FOLD,
    }


    /**
     * 设置显示最大行数
     */
    fun setMaxShowLine(lines: Int) {
        this.mLinesCountTemp = lines
        this.mLineCount = lines
    }


    /**
     * 切换展开/折叠
     */
    fun toggle() {
        if (mState == State.OPEN) {
            close()
        } else {
            open()
        }
    }

    /**
     * 展开
     */
    private fun open() {
        this.mLineCount = NOT_SET
        requestLayout()
    }

    /**
     * 折叠
     */
    private fun close() {
        this.mLineCount = mLinesCountTemp
        requestLayout()
    }


    override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {
        val generateDefaultLayoutParams = super.generateDefaultLayoutParams()
        generateDefaultLayoutParams.setMargins(space, space, space, space)
        return generateDefaultLayoutParams
    }

    override fun getFlexLinesInternal(): MutableList<FlexLine> {
        val originList = super.getFlexLinesInternal()
        //数据 总行数
        val totalLines = originList.size
        //总行数>设定行数,进行折叠
        if (totalLines > mLineCount) {
            //对数据处理(清理从设定行到最大行的数据)
            originList.subList(mLineCount, totalLines).clear()
            //当前状态不是折叠状态时,再处理状态改变回调及状态更新,防止返回多次问题
            if (mState != State.FOLD) {
                foldStateListener?.stateChange(State.FOLD)
                mState = State.FOLD
            }
        }
        //没有设置行数时,默认打开状态
        if (mLineCount == NOT_SET) {
            //当前状态不是打开状态,进行打开操作,并回调状态改变
            if (mState != State.OPEN) {
                foldStateListener?.stateChange(State.OPEN)
                mState = State.OPEN
            }
        }
        return originList
    }


    interface OnFoldStateListener {
        fun stateChange(state: State)
    }

}

欧克,就这么愉快的解决了。

相关文章
|
29天前
|
缓存 前端开发 Android开发
安卓开发中的自定义视图:从零到英雄
【10月更文挑战第42天】 在安卓的世界里,自定义视图是一块画布,让开发者能够绘制出独一无二的界面体验。本文将带你走进自定义视图的大门,通过深入浅出的方式,让你从零基础到能够独立设计并实现复杂的自定义组件。我们将探索自定义视图的核心概念、实现步骤,以及如何优化你的视图以提高性能和兼容性。准备好了吗?让我们开始这段创造性的旅程吧!
26 1
|
2月前
|
Android开发 开发者
安卓应用开发中的自定义视图
【9月更文挑战第37天】在安卓开发的海洋中,自定义视图犹如一座座小岛,等待着勇敢的探索者去发现其独特之处。本文将带领你踏上这段旅程,从浅滩走向深海,逐步揭开自定义视图的神秘面纱。
44 3
|
2月前
|
ARouter Android开发
Android不同module布局文件重名被覆盖
Android不同module布局文件重名被覆盖
|
4月前
|
存储 Shell Android开发
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
87 2
基于Android P,自定义Android开机动画的方法
|
2月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
95 0
|
4月前
|
移动开发 监控 前端开发
构建高效Android应用:从优化布局到提升性能
【7月更文挑战第60天】在移动开发领域,一个流畅且响应迅速的应用程序是用户留存的关键。针对Android平台,开发者面临的挑战包括多样化的设备兼容性和性能优化。本文将深入探讨如何通过改进布局设计、内存管理和多线程处理来构建高效的Android应用。我们将剖析布局优化的细节,并讨论最新的Android性能提升策略,以帮助开发者创建更快速、更流畅的用户体验。
71 10
|
4月前
|
供应链 物联网 区块链
未来触手可及:探索新兴技术的趋势与应用安卓开发中的自定义视图:从基础到进阶
【8月更文挑战第30天】随着科技的飞速发展,新兴技术如区块链、物联网和虚拟现实正在重塑我们的世界。本文将深入探讨这些技术的发展趋势和应用场景,带你领略未来的可能性。
|
4月前
|
测试技术 Android开发 Python
探索软件测试的艺术:从基础到高级安卓应用开发中的自定义视图
【8月更文挑战第29天】在软件开发的世界中,测试是不可或缺的一环。它如同艺术一般,需要精细的技巧和深厚的知识。本文旨在通过浅显易懂的语言,引领读者从软件测试的基础出发,逐步深入到更复杂的测试策略和工具的使用,最终达到能够独立进行高效测试的水平。我们将一起探索如何通过不同的测试方法来确保软件的质量和性能,就像艺术家通过不同的色彩和笔触来完成一幅画作一样。
|
1月前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
1月前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
37 5