public class PredicateLayout extends ViewGroup { private int line_height; public static final int DEFAULT_HORIZONTAL_SPACING = 5; public static final int DEFAULT_VERTICAL_SPACING = 5; private int horizontalSpacing; private int verticalSpacing; public PredicateLayout(Context context) { super(context); } public PredicateLayout(Context context, int horizontalSpacing, int verticalSpacing) { super(context); this.horizontalSpacing = horizontalSpacing; this.verticalSpacing = verticalSpacing; } public PredicateLayout(Context context, AttributeSet attrs) { super(context, attrs); //TypedArray styledAttributes = context.obtainStyledAttributes(attrs, R.styleable.PredicateLayout); //horizontalSpacing = styledAttributes.getDimensionPixelSize(R.styleable.PredicateLayout_item_h_space, DEFAULT_HORIZONTAL_SPACING); //verticalSpacing = styledAttributes.getDimensionPixelSize(R.styleable.PredicateLayout_item_v_space, DEFAULT_VERTICAL_SPACING); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { assert (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED); final int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight(); int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom(); final int count = getChildCount(); int line_height = 0; // int line_height = 22; int xpos = getPaddingLeft(); int ypos = getPaddingTop(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { child.measure(MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.UNSPECIFIED)); final int childw = child.getMeasuredWidth(); line_height = Math.max(line_height, child.getMeasuredHeight() + verticalSpacing); if (xpos + childw > width) { xpos = getPaddingLeft(); ypos += line_height; } xpos += childw + horizontalSpacing; } } this.line_height = line_height; if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) { height = ypos + line_height; } else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) { if (ypos + line_height < height) { height = ypos + line_height; } } setMeasuredDimension(width, height); } @Override protected ViewGroup.LayoutParams generateDefaultLayoutParams() { return new LayoutParams(1, 1); // default of 1px spacing } @Override protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { return p instanceof LayoutParams; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); final int width = r - l; int xpos = getPaddingLeft(); int ypos = getPaddingTop(); for (int i = 0; i < count; i++) { final View child = getChildAt(i); if (child.getVisibility() != GONE) { final int childw = child.getMeasuredWidth(); final int childh = child.getMeasuredHeight(); // final int childh = 24; if (xpos + childw > width) { xpos = getPaddingLeft(); ypos += line_height; } child.layout(xpos, ypos, xpos + childw, ypos + childh); xpos += childw + horizontalSpacing; } } } }
相关推荐
为了实现“多个view自动换行”,我们可以考虑使用`GridLayout`或者自定义布局。`GridLayout`允许每个子视图占据固定大小的网格,并会自动换行以填充整个容器。然而,`GridLayout`在处理不同大小的视图时可能会显得...
本示例“Android实现View的排列自动换行”着重讲解如何在自定义View中实现视图元素的自动布局,即当一行无法容纳所有视图时,自动将超出的视图换行到下一行,并保持适当的间距。 首先,我们需要创建一个新的...
然后在布局XML文件中声明并使用这个自定义ViewGroup,通过设置子View和选择模式,即可实现自动换行和选择功能。 总之,"AndroidAutoLayout"是一个强大且灵活的组件,它解决了Android开发中多元素自动布局的问题,...
总的来说,创建一个多标签自动换行的`ViewGroup`需要理解Android布局系统的底层工作原理,以及如何通过自定义`ViewGroup`来实现特定的布局需求。通过这样的实践,开发者可以更灵活地控制界面的布局,以适应各种屏幕...
通过深入研究这个项目,开发者不仅可以学习到自定义View和布局管理的相关知识,还能掌握如何实现自动换行的功能,这对于优化Android应用的界面布局和提高用户体验具有很大的价值。同时,从开源社区获取和贡献代码也...
在这个案例中,我们将自定义一个`ViewGroup`子类,比如命名为`AutoWrapTagLayout`,来实现自动换行的功能。 实现这个功能的关键在于计算每个标签的宽度,并根据屏幕宽度动态调整它们的布局。我们需要覆写`onMeasure...
要实现ListView中的文字编辑自动换行,我们需要结合EditText控件和自定义Adapter来完成这一功能。以下将详细阐述如何实现这一需求。 首先,我们创建一个布局文件,用于定义ListView中每一项的视图。在这个布局中,...
在自定义自动换行的效果时,我们通常会创建一个自定义的ViewGroup来实现这一功能。 在创建自定义控件时,我们首先需要继承ViewGroup,并重写其关键方法。例如,`onMeasure()`方法用于测量每个子View的大小,`...
当我们在设计用户界面时,有时需要创建一个标签样式(Tag-style)的ViewGroup,这种组件通常包含多个标签,它们需要自动换行以适应有限的屏幕宽度,并且整个组件能自适应高度,以显示所有标签而不被截断。"解决自动...
以上代码实现了基本的FlowViewGroup功能,包括自动换行和对padding、margin的支持。为了更好地适应各种场景,还可以添加以下特性: - **垂直对齐**:在每行内支持顶部对齐、底部对齐或居中对齐。 - **动态调整列数*...
这里我们将详细探讨如何实现一个支持自动换行、默认选中首个标签,并且能够进行多选的标签控件。 首先,我们来看"标签选择"这个概念。标签(Tag)是一种常用的数据展示方式,通常用于表示某个对象或内容的特性。在...
在Android开发中,创建自定义ViewGroup以实现自动换行的功能是一个常见的需求,尤其是在构建复杂的用户界面时。这个场景特别适用于邮件应用中的收件人输入框,用户可以连续添加多个收件人,而这些收件人的显示需要...
本篇文章将深入探讨如何实现一个自动换行的View,这种组件通常用于显示一行排满后自动换行的文本或小图标。在Android应用设计中,这样的组件能够提供更灵活的布局和更丰富的用户体验。 首先,我们需要创建一个新的...
本教程将探讨如何实现一个自定义控件,它具有自动换行的效果,使得在有限的屏幕空间内,元素能够整齐地排列成多行。参考链接为:。 首先,我们需要创建一个新的`ViewGroup`子类,例如`AutoWrapLayout`。这个自定义...
本示例将探讨如何创建一个自定义的ViewGroup来实现商品属性显示时的自动换行效果,类似于常见于电商应用的商品详情页。这个过程涉及到布局管理、事件处理以及自定义View的基本原理。 首先,我们需要理解Android中的...
`AutoLineLayoutManager`将接管ViewGroup的布局过程,通过计算每个子View的尺寸和位置,确保它们在达到边界时自动换行。这样的类可能需要重写`onLayout()`方法,以实现自定义的换行逻辑。 这三种自定义类提供了不同...
6. **DeseListView**: 这可能是项目中自定义的ListView库或者类,具体实现可能包含了更多的优化或功能,比如更好的自动换行逻辑,或者是对长列表的优化处理。需要查看源代码或文档来了解其详细功能。 7. **性能优化...
"子控件排列自动换行"这个主题涉及到如何构建一个自定义的ViewGroup,使得其内部的子控件能够根据空间自动进行换行排列,类似于搜索引擎下方的关键字展示。这样的布局可以有效地利用屏幕空间,提供良好的用户体验。...
在Android开发中,有时我们需要创建一个布局,其中包含多个可点击的标签,并且这些标签能够自动换行以适应屏幕宽度。这就是"标签换行"的需求。`FlowLayout`是一种自定义的`ViewGroup`,它允许子视图(标签)根据需要...