Android自定义ViewGroup多行多列效果

本文实例为大家分享了Android自定义ViewGroup多行多列的具体代码,供大家参考,具体内容如下

先看下效果图

每行两个子孩子

每行一个子孩子

实现思路

自定义viewGroup,实现测量和布局,使控件适应业务场景。

测量

根据父控件的宽度,平均分给每个子孩子固定的宽度。高度就是行数乘以一个子孩子的高度,再加上空隙的高度。

根据子孩子个数计算行数

val rows = if (childCount % perLineChild == 0) {
            childCount / perLineChild
        } else {
            childCount / perLineChild + 1
        }

代码示例

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width = MeasureSpec.getSize(widthMeasureSpec)
        for (i in 0 until childCount) {
            val child: View = getChildAt(i)
            if (child.visibility != GONE) {
                val lp = child.layoutParams
                val childWidthMeasureSpec = getChildMeasureSpec(
                    widthMeasureSpec,
                    0, (width - (perLineChild - 1) * space) / perLineChild
                )
                val childHeightMeasureSpec = getChildMeasureSpec(
                    heightMeasureSpec,
                    0, lp.height
                )
                child.measure(childWidthMeasureSpec, childHeightMeasureSpec)
            }
        }
        val rows = if (childCount % perLineChild == 0) {
            childCount / perLineChild
        } else {
            childCount / perLineChild + 1
        }
        if (childCount > 0) {
            setMeasuredDimension(
                width,
                getChildAt(0).measuredHeight * rows + (rows - 1) * space
            )
        }
    }

布局

需要注意摆放的顺序和位置,每行摆放固定的个数,达到个数之后换行继续摆放

代码示例 

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var left = l
        var top = t
        children.forEachIndexed { index, view ->
            if (index % perLineChild == 0) {
                left = 0
                if (index != 0) {
                    top += view.measuredHeight
                    top+=space
                }
                view.layout(left, top, view.measuredWidth + left, top + view.measuredHeight)
            } else {
                view.layout(left, top, view.measuredWidth + left, top + view.measuredHeight)
            }
            left += view.measuredWidth
            left += space
        }
    }

完整代码

class MultiLineViewG @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ViewGroup(context, attrs, defStyleAttr) {

    var perLineChild = 2

    /**
     * 子孩子之间的空隙
     */
    var space = 10

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width = MeasureSpec.getSize(widthMeasureSpec)
        for (i in 0 until childCount) {
            val child: View = getChildAt(i)
            if (child.visibility != GONE) {
                val lp = child.layoutParams
                val childWidthMeasureSpec = getChildMeasureSpec(
                    widthMeasureSpec,
                    0, (width - (perLineChild - 1) * space) / perLineChild
                )
                val childHeightMeasureSpec = getChildMeasureSpec(
                    heightMeasureSpec,
                    0, lp.height
                )
                child.measure(childWidthMeasureSpec, childHeightMeasureSpec)
            }
        }
        val rows = if (childCount % perLineChild == 0) {
            childCount / perLineChild
        } else {
            childCount / perLineChild + 1
        }
        if (childCount > 0) {
            setMeasuredDimension(
                width,
                getChildAt(0).measuredHeight * rows + (rows - 1) * space
            )
        }
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        var left = l
        var top = t
        children.forEachIndexed { index, view ->
            if (index % perLineChild == 0) {
                left = 0
                if (index != 0) {
                    top += view.measuredHeight
                    top+=space
                }
                view.layout(left, top, view.measuredWidth + left, top + view.measuredHeight)
            } else {
                view.layout(left, top, view.measuredWidth + left, top + view.measuredHeight)
            }
            left += view.measuredWidth
            left += space
        }
    }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义RadioGroupX实现多行多列布局

    前言 今天在做新需求的时候,活动有多个类型可以选择,UI给的设计图为多行多列排版,且单项选择,细细想来,谷歌并没有为我们提供类似的控件,初步设想使用RecyclerView实现多行多列布局,然后再用代码控制逻辑部分,总感觉不太稳妥,又想到让UI小姐姐重新设计一番?感觉也不太稳妥,这样UI小姐姐就会认为我菜,为了不让別人觉得我菜,干脆自定义RadioGroupX实现多行多列布局. 思考 在工作中,面对一个功能,首先想到的是应该怎样实现完成它,然后再考虑究竟怎样实现才更优雅.正如前面提到,实现这种需

  • Android控件gridview实现单行多列横向滚动效果

    本文实例为大家分享了安卓实现单行多列横向滚动,供大家参考,具体内容如下 <GridLayout android:layout_width="match_parent" android:layout_height="match_parent" android:columnCount="1" > <HorizontalScrollView android:layout_width="match_parent" a

  • Android中控件GridView实现设置行列分割线的方法示例

    前言 虽然Aandroid目前已经有RecyclerView了.非常强大的一个View.可以直接控制成ListView以及GridView等.而且画框线也比较方便.但是呢在很多情况下我们不得不仍然使用GridView来实现布局.那么在这个时候我们又要怎么来对GridViw进行画框线呢.下面将提供两种实现方式.大家可以选择一下 一.设置垂直.横向间距.通过GRIDVIEW和ITEM的背景色来实现 1.设置GridView背景色 2.设置水平和竖直方向间隔:android:horizontalSpa

  • android 修改launcher行数和列数的方法

    android 修改launcher行数和列数 Launcher3桌面的行数和列数都是在InvariantDeviceProfile.java和DeviceProfile.java中动态计算的,xml中无法配置. Note:L版本无InvariantDeviceProfile.java,是DynamicGrid.java,但是计算方法都是一样的. InvariantDeviceProfile中用InvariantDeviceProfile来配置各种屏幕的手机桌面.如下: InvariantDev

  • Android自定义ViewGroup多行多列效果

    本文实例为大家分享了Android自定义ViewGroup多行多列的具体代码,供大家参考,具体内容如下 先看下效果图 每行两个子孩子 每行一个子孩子 实现思路 自定义viewGroup,实现测量和布局,使控件适应业务场景. 测量 根据父控件的宽度,平均分给每个子孩子固定的宽度.高度就是行数乘以一个子孩子的高度,再加上空隙的高度. 根据子孩子个数计算行数 val rows = if (childCount % perLineChild == 0) { childCount / perLineChi

  • Android自定义viewGroup实现点击动画效果

    本文实例为大家分享了viewGroup实现点击动画效果展示的具体代码,供大家参考,具体内容如下 public class MyCustomView extends ViewGroup implements View.OnClickListener { private OnMenuItemClickListener mMenuItemClickListener; /** * 点击子菜单项的回调接口 */ public interface OnMenuItemClickListener { void

  • Android自定义ViewGroup实现标签流效果

    本文实例为大家分享了Android自定义ViewGroup实现标签流效果的具体代码,供大家参考,具体内容如下 自定义View,一是为了满足设计需求,二是开发者进阶的标志之一.随心所欲就是我等奋斗的目标!!! 效果 实现逻辑 明确需求 1.标签流效果;2.可以动态添加标签;3.标签需要有点击效果以及回调; 整理思路 既然要装载标签,就需要自定义ViewGroup ,而自定义ViewGroup 比较复杂的就是onLayout()中对子View的排版.既然是标签,在一行中一定要显示完整,在排版的时候注

  • Android自定义ViewGroup实现绚丽的仿支付宝咻一咻雷达脉冲效果

    去年春节的时候支付宝推行的集福娃活动着实火的不能再火了,更给力的是春晚又可以全民参与咻一咻集福娃活动,集齐五福就可平分亿元大红包,只可惜没有敬业福--那时候在家没事写了个咻一咻插件,只要到了咻一咻的时间点插件就可以自动的点击咻一咻来咻红包,当时只是纯粹练习这部分技术代码没有公开,后续计划写篇关于插件这方面的文章,扯远了(*^__^*) --我们知道在支付宝的咻一咻页面有个雷达扩散的动画效果,当时感觉动画效果非常棒,于是私下尝试着实现了类似的效果,后来在github发现有大神也写有类似效果,于是读

  • Android自定义ViewGroup实现弹性滑动效果

    自定义View实现一个弹性滑动的效果,供大家参考,具体内容如下 实现原理 onMeasure()中测量所有子View @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 测量所有子View int count = getChildCount(); for (int i = 0; i < count; i++) { View childView = getChildAt(i); m

  • Android自定义ViewGroup实现九宫格布局

    目录 前言 一.九宫格的测量 二.九宫格的布局 三.单图片与四宫格的单独处理 四.自定义布局的抽取 4.1 先布局再隐藏的思路 4.2 数据适配器的思路 前言 在之前的文章我们复习了 ViewGroup 的测量与布局,那么我们这一篇效果就可以在之前的基础上实现一个灵活的九宫格布局. 那么一个九宫格的 ViewGroup 如何定义,我们分解为如下的几个步骤来实现: 先计算与测量九宫格内部的子View的宽度与高度. 再计算整体九宫格的宽度和高度. 进行子View九宫格的布局. 对单独的图片和四宫格的

  • Android自定义ViewGroup实现竖向引导界面

    一般进入APP都有欢迎界面,基本都是水平滚动的,今天和大家分享一个垂直滚动的例子. 先来看看效果把: 1.首先是布局文件: <com.example.verticallinearlayout.VerticalLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:i

  • Android自定义ViewGroup实现流式布局

    本文实例为大家分享了Android自定义ViewGroup实现流式布局的具体代码,供大家参考,具体内容如下 1.概述 本篇给大家带来一个实例,FlowLayout,什么是FlowLayout,我们常在App 的搜索界面看到热门搜索词,就是FlowLayout,我们要实现的就是图中的效果,就是根据容器的宽,往容器里面添加元素,如果剩余的控件不足时候,自行添加到下一行,FlowLayout也叫流式布局,在开发中还是挺常用的. 2.对所有的子View进行测量 onMeasure方法的调用次数是不确定的

  • Android自定义ViewGroup实现朋友圈九宫格控件

    目录 一.简介 1.1.效果图如下 1.2.主要功能如下 二.使用 2.1.自定义属性如下 2.2.布局中使用自定义NineImageLayout 2.3.Adapter方式绑定数据和UI 2.4.列表里面使用 三.源码地址 四.总结 一.简介 最近项目里有个类似微信朋友圈的九图控件的需求,Github找了一下,发现都不太满足需求,我需要单张图片的时候可以按照图片宽高比列在一定范围内自适应,而大多开源项目单张图片也是一个小正方形,所以,干脆自己动手写一个 1.1.效果图如下 1.2.主要功能如下

  • Android自定义ViewGroup实现右滑进入详情

    目录 前言 一.抖音直接右滑进入详情 二.闲鱼右滑进入详情 三.列表的右滑进入详情 后记 前言 在之前的 ViewGroup 的事件相关一文中,我们详细的讲解了一些常见的 ViewGroup 需要处理的事件与运动的方式. 我们了解了如何处理拦截事件,如何滚动,如何处理子 View 的协调运动等. 再复杂一点,我们可以组合在一起使用.例如在拦截事件之后滚动,或者在滚动到一个阈值之后拦截事件. 今天我们一起再巩固一下相关的知识点,以比较常见的一个应用场景,右滑进入详情的场景为例子. 这个例子中又分几

随机推荐