直播网站程序源码,FlowLayoutManager 流式布局

直播网站程序源码,FlowLayoutManager 流式布局

 

1
import android.graphics.Rect<br>import android.util.Log<br>import android.util.SparseArray<br>import android.view.View<br>import android.view.ViewGroup<br>import androidx.recyclerview.widget.RecyclerView<br>class FlowLayoutManager : RecyclerView.LayoutManager() {<br>    companion object {<br>        const val TAG = "FlowLayoutManager2"<br>    }<br>    var widthFlow = 0<br>    var heightFlow = 0<br>    private var left = 0<br>    private var top = 0<br>    private var right = 0<br>    private var useMaxWidth = 0<br>    private var verticalScrollOffset = 0<br>    var totalHeight = 0<br>        private set<br>    private var row = Row()<br>    private val lineRows: MutableList<Row> = mutableListOf()<br>    private val allItemFrames = SparseArray<Rect>()<br>    override fun isAutoMeasureEnabled(): Boolean {<br>        return true<br>    }<br>    override fun generateDefaultLayoutParams(): RecyclerView.LayoutParams {<br>        return RecyclerView.LayoutParams(<br>            ViewGroup.LayoutParams.WRAP_CONTENT,<br>            ViewGroup.LayoutParams.WRAP_CONTENT<br>        )<br>    }<br>    override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) {<br>        Log.d(TAG, "onLayoutChildren")<br>        totalHeight = 0<br>        var cuLineTop = top<br>        //当前行使用的高度<br>        var cuLineWidth = 0<br>        var itemLeft: Int<br>        var itemTop: Int<br>        var maxHeightItem = 0<br>        row = Row()<br>        lineRows.clear()<br>        allItemFrames.clear()<br>        removeAllViews()<br>        if (itemCount == 0) {<br>            recycler?.let {<br>                detachAndScrapAttachedViews(it)<br>            }<br>            verticalScrollOffset = 0<br>            return<br>        }<br>        if (childCount == 0 && state?.isPreLayout == true) {<br>            return<br>        }<br>        //onLayoutChildren方法在RecyclerView 初始化时 会执行两遍<br>        recycler?.let {<br>            detachAndScrapAttachedViews(it)<br>        }<br>        if (childCount == 0) {<br>            widthFlow = width<br>            heightFlow = height<br>            left = paddingLeft<br>            right = paddingRight<br>            top = paddingTop<br>            useMaxWidth = widthFlow - left - right<br>        }<br>        for (i in 0 until itemCount) {<br>            Log.d(TAG, "index:$i")<br>            val childAt = recycler?.getViewForPosition(i) ?: continue<br>            if (View.GONE == childAt.visibility) {<br>                continue<br>            }<br>            measureChildWithMargins(childAt, 0, 0)<br>            val childWidth = getDecoratedMeasuredWidth(childAt)<br>            val childHeight = getDecoratedMeasuredHeight(childAt)<br>            if ((cuLineWidth + childWidth) <= useMaxWidth) {<br>                itemLeft = left + cuLineWidth<br>                itemTop = cuLineTop<br>                val frame = allItemFrames.get(i) ?: Rect()<br>                frame.set(itemLeft, itemTop, itemLeft + childWidth, itemTop + childHeight)<br>                allItemFrames.put(i, frame)<br>                cuLineWidth += childWidth<br>                maxHeightItem = maxHeightItem.coerceAtLeast(childHeight)<br>                row.views.add(Item(childHeight, childAt, frame))<br>                row.cuTop = cuLineTop<br>                row.maxHeight = maxHeightItem<br>            } else {<br>                // 换行<br>                formatAboveRow()<br>                cuLineTop += maxHeightItem<br>                totalHeight += maxHeightItem<br>                itemTop = cuLineTop<br>                itemLeft = left<br>                val frame = allItemFrames.get(i) ?: Rect()<br>                frame.set(itemLeft, itemTop, itemLeft + childWidth, itemTop + childHeight)<br>                allItemFrames.put(i, frame)<br>                cuLineWidth = childWidth<br>                maxHeightItem = childHeight<br>                row.views.add(Item(childHeight, childAt, frame))<br>                row.cuTop = cuLineTop<br>                row.maxHeight = maxHeightItem<br>            }<br>            //不要忘了最后一行进行刷新下布局<br>            if (i == itemCount - 1) {<br>                formatAboveRow()<br>                totalHeight += maxHeightItem<br>            }<br>        }<br>        totalHeight = totalHeight.coerceAtLeast(getVerticalSpace())<br>        Log.d(TAG, "onLayoutChildren totalHeight:$totalHeight")<br>        fillLayout(state)<br>    }<br>    private fun fillLayout(state: RecyclerView.State?) {<br>        if (state?.isPreLayout == true || itemCount == 0) {<br>            // 跳过preLayout,preLayout主要用于支持动画<br>            return<br>        }<br>        //对所有的行信息进行遍历<br>        for (j in 0 until lineRows.size) {<br>            val row = lineRows[j]<br>            val views = row.views<br>            for (i in 0 until views.size) {<br>                val scrap = views[i].view<br>                measureChildWithMargins(scrap, 0, 0)<br>                addView(scrap)<br>                val frame = views[i].rect<br>                //将这个item布局出来<br>                layoutDecoratedWithMargins(<br>                    scrap,<br>                    frame.left ,<br>                    frame.top - verticalScrollOffset,<br>                    frame.right ,<br>                    frame.bottom - verticalScrollOffset<br>                )<br>            }<br>        }<br>    }<br>    private fun formatAboveRow() {<br>        var lineNeedWidth = 0<br>        val views = row.views<br>        for (i in 0 until views.size) {<br>            //计算行高居中<br>            val item = views[i]<br>            val view = item.view<br>            val position = getPosition(view)<br>            if (allItemFrames[position].top < row.cuTop + (row.maxHeight - item.useHeight) / 2) {<br>                val frame = allItemFrames[position] ?: Rect()<br>                frame.set(<br>                    allItemFrames[position].left,<br>                    row.cuTop + (row.maxHeight - item.useHeight) / 2,<br>                    allItemFrames[position].right,<br>                    row.cuTop + (row.maxHeight - item.useHeight) / 2 + getDecoratedMeasuredHeight(view)<br>                )<br>                allItemFrames.put(position,frame)<br>                item.rect = frame<br>                views[i] = item<br>            }<br>            //计算行宽居中<br>            lineNeedWidth += (item.rect.right - item.rect.left)<br>        }<br>        val off = (useMaxWidth - lineNeedWidth) / 2<br>        for (item in views) {<br>            item.rect.left += off<br>            item.rect.right += off<br>        }<br>        lineRows.add(row)<br>        row = Row()<br>    }<br>    override fun canScrollVertically(): Boolean {<br>        return true<br>    }<br>    override fun scrollVerticallyBy(<br>        dy: Int,<br>        recycler: RecyclerView.Recycler?,<br>        state: RecyclerView.State?<br>    ): Int {<br>        return super.scrollVerticallyBy(dy, recycler, state)<br>    }<br>    private fun getVerticalSpace(): Int {<br>        return height - paddingBottom - paddingTop<br>    }<br>    //行信息的定义<br>    class Row(val views: MutableList<Item> = mutableListOf()) {<br>        //每一行的头部坐标<br>        var cuTop: Int = 0<br>        //每一行需要占据的最大高度<br>        var maxHeight: Int = 0<br>    }<br>    //每个item的定义<br>    class Item(val useHeight: Int, val view: View, var rect: Rect)<br>}

以上就是直播网站程序源码,FlowLayoutManager 流式布局, 更多内容欢迎关注之后的文章

 

posted @   云豹科技-苏凌霄  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2021-12-20 直播源码网站,菜单栏的横向滑动
2021-12-20 短视频直播系统,简单实现个人主页背景图片和文字颜色的更改
2021-12-20 android短视频开发,实现动态点赞出现的点赞动画
点击右上角即可分享
微信分享提示