吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3324|回复: 3
收起左侧

[其他转载] 流式布局demo 安卓2.3也能用

[复制链接]
djwdj 发表于 2018-1-29 22:07
本帖最后由 djwdj 于 2018-1-29 22:11 编辑



先上流式布局
[Java] 纯文本查看 复制代码
package l.f;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/*
 * 本demo源于网络
 *【基哥】修改优化 v1
 * by酷安@基哥科技
 * 2018.1.29
 */

public class FlowLayout extends ViewGroup {
    /**
     * 存储行的集合,管理行
     */
         List<Line> mLines = new ArrayList<>();

    /**
     * 水平和竖直的间距
     */
         float vertical_space;
         float horizontal_space;

    // 当前行的指针
        Line mCurrentLine;

    // 行的最大宽度,除去边距的宽度
        int mMaxWidth;

        FlowLayout(Context context) {
        super(context);
    }
        
        //设置外间距
        void set(int h, int v)
        {
                horizontal_space=h;
                vertical_space=v;
        }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 每次测量之前都先清空集合,不让会覆盖掉以前
        mLines.clear();
        mCurrentLine = null;

        // 获取总宽度
        int width = MeasureSpec.getSize(widthMeasureSpec);
        // 计算最大的宽度
        mMaxWidth = width - getPaddingLeft() - getPaddingRight();

        // ******************** 测量孩子 ********************
        // 遍历获取孩子
        int childCount = this.getChildCount();
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            // 测量孩子
            measureChild(childView, widthMeasureSpec, heightMeasureSpec);

            // 测量完需要将孩子添加到管理行的孩子的集合中,将行添加到管理行的集合中

            if (mCurrentLine == null) {
                // 初次添加第一个孩子的时候
                mCurrentLine = new Line(mMaxWidth, horizontal_space);

                // 添加孩子
                mCurrentLine.addView(childView);
                // 添加行
                mLines.add(mCurrentLine);

            } else {
                // 行中有孩子的时候,判断时候能添加
                if (mCurrentLine.canAddView(childView)) {
                    // 继续往该行里添加
                    mCurrentLine.addView(childView);
                } else {
                    //  添加到下一行
                    mCurrentLine = new Line(mMaxWidth, horizontal_space);
                    mCurrentLine.addView(childView);
                    mLines.add(mCurrentLine);
                }
            }
        }

        // ******************** 测量自己 *********************
        // 测量自己只需要计算高度,宽度肯定会被填充满的
        int height = getPaddingTop() + getPaddingBottom();
        for (int i = 0; i < mLines.size(); i++) {
            // 所有行的高度
            height += mLines.get(i).height;
        }
        // 所有竖直的间距
        height += (mLines.size() - 1) * vertical_space;

        // 测量
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 这里只负责高度的位置,具体的宽度和子孩子的位置让具体的行去管理
        l = getPaddingLeft();
        t = getPaddingTop();
        for (int i = 0; i < mLines.size(); i++) {
            // 获取行
            Line line = mLines.get(i);
            // 管理
            line.layout(t, l);

            // 更新高度
            t += line.height;
            if (i != mLines.size() - 1) {
                // 不是最后一条就添加间距
                t += vertical_space;
            }
        }
    }

    /**
     * 内部类,行管理器,管理每一行的孩子
     */
         class Line {
        // 定义一个行的集合来存放子View
                List<View> views = new ArrayList<>();
        // 行的最大宽度
                int maxWidth;
        // 行中已经使用的宽度
                int usedWidth;
        // 行的高度
                int height;
        // 孩子之间的距离
                float space;

        // 通过构造初始化最大宽度和边距
                Line(int maxWidth, float horizontalSpace) {
            this.maxWidth = maxWidth;
            this.space = horizontalSpace;
        }

        /**
         * 往集合里添加孩子
         */
                 void addView(View view) {
            int childWidth = view.getMeasuredWidth();
            int childHeight = view.getMeasuredHeight();

            // 更新行的使用宽度和高度
            if (views.size() == 0) {
                // 集合里没有孩子的时候
                if (childWidth > maxWidth) {
                    usedWidth = maxWidth;
                    height = childHeight;
                } else {
                    usedWidth = childWidth;
                    height = childHeight;
                }
            } else {
                usedWidth += childWidth + space;
                height = childHeight > height ? childHeight : height;
            }

            // 添加孩子到集合
            views.add(view);
        }


        /**
         * 判断当前的行是否能添加孩子
         *
         * @return
         */
                 boolean canAddView(View view) {
            // 集合里没有数据可以添加
            if (views.size() == 0) {
                return true;
            }

            // 最后一个孩子的宽度大于剩余宽度就不添加
            if (view.getMeasuredWidth() > (maxWidth - usedWidth - space)) {
                return false;
            }

            // 默认可以添加
            return true;
        }

        /**
         * 指定孩子显示的位置
         *
         * @param t
         * @param l
         */
                 void layout(int t, int l) {
            // 平分剩下的空间
            int avg = (maxWidth - usedWidth) / views.size();

            // 循环指定孩子位置
            for (View view : views) {
                // 获取宽高
                int measuredWidth = view.getMeasuredWidth();
                int measuredHeight = view.getMeasuredHeight();
                // 重新测量
                view.measure(MeasureSpec.makeMeasureSpec(measuredWidth + avg, MeasureSpec.EXACTLY),
                                                         MeasureSpec.makeMeasureSpec(measuredHeight, MeasureSpec.EXACTLY));
                // 重新获取宽度值
                measuredWidth = view.getMeasuredWidth();


                int top = t;
                int left = l;
                int right = measuredWidth + left;
                int bottom = measuredHeight + top;
                // 指定位置
                view.layout(left, top, right, bottom);

                // 更新数据
                l += measuredWidth + space;
            }
        }
    }
}


再来个示范:

[Java] 纯文本查看 复制代码
package l.f;

import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import java.util.Random;
import android.app.*;
import android.widget.*;
import android.view.*;

public class MainActivity extends Activity {

    /**
     * 显示的文字
     */
    private String[] mDatas = new String[]{"QQ",
		"视频",
		"放开那三国",
		"电子书",
		"酒店",
		"单机",
		"小说",
		"斗地主",
		"优酷",
		"网游",
		"WIFI万能钥匙",
		"播放器",
		"捕鱼达人2",
		"机票",
		"游戏",
		"熊出没之熊大快跑",
		"美图秀秀",
		"浏览器",
		"单机游戏",
		"我的世界",
		"电影电视",
		"QQ空间",
		"旅游",
		"免费游戏",
		"2048",
		"刀塔传奇",
		"壁纸",
		"节奏大师",
		"锁屏",
		"装机必备",
		"天天动听",
		"备份",
		"网盘",
		"海淘网",
		"大众点评",
		"爱奇艺视频",
		"腾讯手机管家",
		"百度地图",
		"猎豹清理大师",
		"谷歌地图",
		"hao123上网导航",
		"京东",
		"有你",
		"万年历-农历黄历",
		"支付宝钱包"};


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
		
		FlowLayout f=new FlowLayout(this);
		f.setPadding(8,8,8,8);
		f.set(12,12);
		

        Random random = new Random();

        // 循环添加TextView到容器
        for (int i = 0; i < mDatas.length; i++) {
            final TextView view = new Button(this);
            view.setText(mDatas[i]);
            view.setTextColor(Color.WHITE);
            view.setPadding(5, 5, 5, 5);
            view.setGravity(Gravity.CENTER);
            view.setTextSize(14);

            // 设置点击事件
            view.setOnClickListener(new View.OnClickListener() {
					@Override
					public void onClick(View v) {
						Toast.makeText(MainActivity.this, view.getText().toString(), Toast.LENGTH_SHORT).show();
					}
				});

            // 设置彩色背景
            GradientDrawable normalDrawable = new GradientDrawable();
            normalDrawable.setShape(GradientDrawable.RECTANGLE);
            int a = 255;
            int r = 50 + random.nextInt(150);
            int g = 50 + random.nextInt(150);
            int b = 50 + random.nextInt(150);
            normalDrawable.setColor(Color.argb(a, r, g, b));

            // 设置按下的灰色背景
            GradientDrawable pressedDrawable = new GradientDrawable();
            pressedDrawable.setShape(GradientDrawable.RECTANGLE);
            pressedDrawable.setColor(Color.GRAY);

            // 背景选择器
            StateListDrawable stateDrawable = new StateListDrawable();
            stateDrawable.addState(new int[]{android.R.attr.state_pressed}, pressedDrawable);
            stateDrawable.addState(new int[]{}, normalDrawable);

            // 设置背景选择器到TextView上
            view.setBackgroundDrawable(stateDrawable);

            f.addView(view);
        }

		ScrollView s=new ScrollView(this);
		s.addView(f);
		addContentView(s,new WindowManager.LayoutParams());
    }
}


Screenshot_20180129-221024.jpg

flow_demo.zip

15.67 KB, 下载次数: 12, 下载积分: 吾爱币 -1 CB

项目源码

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

zoxoco 发表于 2018-1-29 22:40
感谢楼主分享
15271554324 发表于 2018-1-29 22:58 来自手机
darkmoorice 发表于 2018-6-11 16:15
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-20 22:49

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表