100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Android 中自定义ViewGroup实现流式布局的效果

Android 中自定义ViewGroup实现流式布局的效果

时间:2021-06-17 17:27:54

相关推荐

Android 中自定义ViewGroup实现流式布局的效果

博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家,

👉点击跳转到网站

前言:

自定义View与自定义ViewGroup的区别:

自定义View:在没有现成的View,需要自己实现的时候,就使用自定义View,一般继承自View,SurfaceView或其他的View。这个是控件。自定义ViewGroup:一般是利用现有的组件根据特定的布局方式来组成新的组件,大多继承自ViewGroup或各种Layout。这个是组件。

自定义View的绘制流程图如下:

下面来实现流式布局,定义一个类FlowLayout继承自ViewGroup,重写里面的相关方法,实现流式布局的效果。

public class FlowLayout extends ViewGroup {//每个item横向间距private int mHorizontalSpacing = dp2px(16);//每个item竖向间距private int mVerticalSpacing = dp2px(8);//记录所有的行,一行一行的存储,用于Layoutprivate List<List<View>> allLines;//记录每一行的行高,用于LayoutList<Integer> lineHeights = new ArrayList<>();//new FlowLayout(传入上下文)//在代码中创建组件时会调用该构造方法//比如创建一个按钮:Button btn=new Button(this),// this 是指当前的 Activity,Activity 是 Context 的子类public FlowLayout(Context context) {super(context);}//在xml中使用 在xml转化为java代码的时候,通过反射调用有两个参数的构造函数//在 layout 布局文件中使用时调//用,参数 attrs 表示当前配置中的属性集合,例如在要 layout.xml 中定义一个按钮://<Button// android:layout_width = "match_parent"// android:layout_height = "wrap_content"//android:text ="OK"/>// Android 会调用第二个构造方法 Inflate 出 Button 对象public FlowLayout(Context context, AttributeSet attrs) {super(context, attrs);}//代码中有不同的主题style,调用有三个参数的构造函数//该方法不会自动调用的,当我们在 Theme 中定义了 Style 属性时通常在第二个//构造方法中手动调用。public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);}//进行集合的初始化private void initMeasureParams() {if (allLines != null) {allLines.clear();} else {allLines = new ArrayList<>();}if (lineHeights != null) {lineHeights.clear();} else {lineHeights = new ArrayList<>();}}//度量@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);//每次进入onMeasure()方法中 都需要将全局变量重新初始化initMeasureParams();//度量子View的宽度和高度int childCount = getChildCount();int paddingLeft = getPaddingLeft();int paddingRight = getPaddingRight();int paddingTop = getPaddingTop();int paddingBottom = getPaddingBottom();//ViewGroup解析的宽度int selfWidth = MeasureSpec.getSize(widthMeasureSpec);//ViewGroup解析的高度int selfHeight = MeasureSpec.getSize(heightMeasureSpec);//保存一行中的所有ViewList<View> lineViews = new ArrayList<>();//记录这一行已经使用了多宽的sizeint lineWidthUsed = 0;//一行的行高int lineHeight = 0;//measure过程中,子View要求的父ViewGroup的宽int parentNeededWidth = 0;//measure过程中,子View要求的父ViewGroup的高int parentNeededHeight = 0;for (int i = 0; i < childCount; i++) {View childView = getChildAt(i);LayoutParams childLP = childView.getLayoutParams();int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, paddingLeft + paddingRight, childLP.width);int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, paddingBottom + paddingTop, childLP.height);childView.measure(childWidthMeasureSpec, childHeightMeasureSpec);//获取子View的宽高int childMeasuredWidth = childView.getMeasuredWidth();int childMeasuredHeight = childView.getMeasuredHeight();//通过宽度来判断是否需要换行,通过换行后的每行的行高来获取//整个ViewGroup的行高if (childMeasuredWidth + lineWidthUsed + mHorizontalSpacing > selfWidth) {allLines.add(lineViews);lineHeights.add(lineHeight);//一旦换行,我们就可以判断当前列需要的宽和高了,所以此时需要记录下来parentNeededHeight = parentNeededHeight + lineHeight + mVerticalSpacing;parentNeededWidth = Math.max(parentNeededWidth, lineWidthUsed + mHorizontalSpacing);lineViews = new ArrayList<>();lineWidthUsed = 0;lineHeight = 0;}//view是分行layout的,所以要记录每一行有哪些View,这样可以方便布局lineViews.add(childView);//每行都会有自己的宽和高lineWidthUsed = lineWidthUsed + childMeasuredWidth + mHorizontalSpacing;lineHeight = Math.max(lineHeight, childMeasuredHeight);}//根据子View的度量结果,来重新度量自己的ViewGroup//作为一个ViewGroup,它自己也是一个View,它的大小也需要根据它的父亲给它提供的宽高来度量int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int realWidth = (widthMode == MeasureSpec.EXACTLY) ? selfWidth : parentNeededWidth;int realHeight = (heightMode == MeasureSpec.EXACTLY) ? selfHeight : parentNeededHeight;//度量自己的宽度和高度setMeasuredDimension(realWidth, realHeight);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {//获取Layout中的行数int lineCount = allLines.size();int curL = getPaddingLeft();int curT = getPaddingTop();for (int i = 0; i < lineCount; i++) {List<View> lineViews = allLines.get(i);int lineHeight = lineHeights.get(i);for (int j = 0; j < lineViews.size(); j++) {View view = lineViews.get(j);int left = curL;int top = curT;int right = left + view.getMeasuredWidth();int bottom = top + view.getMeasuredHeight();view.layout(left, top, right, bottom);curL = right + mHorizontalSpacing;}curL = getPaddingLeft();curT = lineHeight + curT + mVerticalSpacing;}}//dp转为pxpublic static int dp2px(int dp) {return (int) TypedValue.applyDimension(PLEX_UNIT_DIP, dp, Resources.getSystem().getDisplayMetrics());}}

之后我们在xml中,进行引用,就可以了。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".ViewGroupActivity"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="搜索历史"android:textColor="@color/black"android:textSize="17sp" /><com.example.animationtest.view.FlowLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="8dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="水果味孕妇奶粉"android:textColor="@color/black" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童洗衣机"android:textColor="@color/black" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="洗衣机全自动"android:textColor="@color/black" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="手机"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童汽车可坐人111111111111111111"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="抽真空收纳袋"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童滑板车"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="稳定器 电容"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童洗衣机"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="衣服"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="运动鞋"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="手表"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="水果味孕妇奶粉"android:textColor="@color/black" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童洗衣机"android:textColor="@color/black" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="洗衣机全自动"android:textColor="@color/black" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="手机"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="抽真空收纳袋"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童滑板车"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="稳定器 电容"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童洗衣机"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="衣服"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="运动鞋"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="手表"android:textColor="@color/black"android:textSize="16sp" /></com.example.animationtest.view.FlowLayout><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="搜索发现"android:textColor="@color/black"android:textSize="17sp" /><com.example.animationtest.view.FlowLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="8dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="水果味孕妇奶粉"android:textColor="@color/black" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童洗衣机"android:textColor="@color/black" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="洗衣机全自动"android:textColor="@color/black" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="手机"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童汽车可坐人111111111111111111"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="抽真空收纳袋"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童滑板车"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="稳定器 电容"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="儿童洗衣机"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="衣服"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="运动鞋"android:textColor="@color/black"android:textSize="16sp" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@drawable/tv_back_color"android:text="手表"android:textColor="@color/black"android:textSize="16sp" /></com.example.animationtest.view.FlowLayout></LinearLayout>

运行后,效果如下:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。