Android流式布局
来源:互联网 发布:十金数据黄金外汇直播 编辑:程序博客网 时间:2024/06/05 17:45
概述
大家都知道,java 图形编程有一个布局叫FlowLayout,即流式布局。但Android没有,所以今天教大家写一个Android版的流式布局。
代码
核心代码(FlowLayout.java)如下:
- package com.example.flowlayout;
- import java.util.ArrayList;
- import java.util.List;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.Button;
- public class FlowLayout extends ViewGroup {
- //记录每个View的位置
- private List<ChildPos> mChildPos = new ArrayList<ChildPos>();
- private class ChildPos {
- int left, top, right, bottom;
- public ChildPos(int left, int top, int right, int bottom) {
- this.left = left;
- this.top = top;
- this.right = right;
- this.bottom = bottom;
- }
- }
- public FlowLayout(Context context) {
- this(context, null);
- }
- public FlowLayout(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
- /**
- * 最终调用这个构造方法
- * @param context 上下文
- * @param attrs xml属性集合
- * @param defStyle Theme中定义的style
- */
- public FlowLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
- /**
- * 测量宽度和高度
- */
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- //获取流式布局的宽度和模式
- int widthSize = MeasureSpec.getSize(widthMeasureSpec);
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- //获取流式布局的高度和模式
- int heightSize = MeasureSpec.getSize(heightMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
- //使用wrap_content的流式布局的最终宽度和高度
- int width = 0, height = 0;
- //记录每一行的宽度和高度
- int lineWidth = 0, lineHeight = 0;
- //得到内部元素的个数
- int count = getChildCount();
- mChildPos.clear();
- for (int i = 0; i < count; i++) {
- //获取对应索引的view
- View child = getChildAt(i);
- //测量子view的宽和高
- measureChild(child, widthMeasureSpec, heightMeasureSpec);
- MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
- //子view占据的宽度
- int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
- //子view占据的高度
- int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
- //换行
- if (lineWidth + childWidth > widthSize - getPaddingLeft() - getPaddingRight()) {
- //取最大的行宽为流式布局宽度
- width = Math.max(width, lineWidth);
- //叠加行高得到流式布局高度
- height += lineHeight;
- //重置行宽度为第一个View的宽度
- lineWidth = childWidth;
- //重置行高度为第一个View的高度
- lineHeight = childHeight;
- //记录位置
- mChildPos.add(new ChildPos(
- getPaddingLeft() + lp.leftMargin,
- getPaddingTop() + height + lp.topMargin,
- getPaddingLeft() + childWidth - lp.rightMargin,
- getPaddingTop() + height + childHeight - lp.bottomMargin));
- } else { //不换行
- //记录位置
- mChildPos.add(new ChildPos(
- getPaddingLeft() + lineWidth + lp.leftMargin,
- getPaddingTop() + height + lp.topMargin,
- getPaddingLeft() + lineWidth + childWidth - lp.rightMargin,
- getPaddingTop() + height + childHeight - lp.bottomMargin));
- //叠加子View宽度得到新行宽度
- lineWidth += childWidth;
- //取当前行子View最大高度作为行高度
- lineHeight = Math.max(lineHeight, childHeight);
- }
- //最后一个控件
- if (i == count - 1)
- {
- width = Math.max(lineWidth, width);
- height += lineHeight;
- }
- }
- setMeasuredDimension(
- widthMode == MeasureSpec.EXACTLY ? widthSize : width + getPaddingLeft() + getPaddingRight(),
- heightMode == MeasureSpec.EXACTLY ? heightSize : height + getPaddingTop() + getPaddingBottom());
- }
- /**
- * 让ViewGroup能够支持margin属性
- */
- @Override
- public LayoutParams generateLayoutParams(AttributeSet attrs) {
- return new MarginLayoutParams(getContext(), attrs);
- }
- /**
- * 设置每个View的位置
- */
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- int count = getChildCount();
- for (int i = 0; i < count; i++) {
- View child = getChildAt(i);
- ChildPos pos = mChildPos.get(i);
- //设置View的左边、上边、右边底边位置
- child.layout(pos.left, pos.top, pos.right, pos.bottom);
- }
- }
- }
- package com.example.flowlayout;
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup.MarginLayoutParams;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.TextView;
- public class MainActivity extends Activity {
- //标签名称
- private String mTvNames[] = {"动漫", "钉宫理惠", "灼眼的夏娜", "绯弹的亚里亚", "零之使魔", "夕阳染红的街道"};
- //流式布局
- private FlowLayout mFlowLayout;
- //用于动态添加TextView到流式布局的按钮
- private Button mBtn;
- //接收新添加TextView的名称
- private EditText mEdit;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- mFlowLayout = (FlowLayout) findViewById(R.id.flow_layout);
- init();
- mEdit = (EditText) findViewById(R.id.edit);
- mBtn = (Button) findViewById(R.id.btn);
- mBtn.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- String s = mEdit.getText().toString();
- addTextView(s);
- }
- });
- }
- public void init() {
- //遍历标签名称数组
- for (String s : mTvNames) {
- addTextView(s);
- }
- }
- public void addTextView(String tvName) {
- //加载TextView并设置名称,并设置名称
- TextView tv = (TextView) LayoutInflater.from(this).inflate(R.layout.tv, mFlowLayout, false);
- tv.setText(tvName);
- //把TextView加入流式布局
- mFlowLayout.addView(tv);
- }
- }
布局文件(activity_main.xml)如下:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <com.example.flowlayout.FlowLayout
- android:id="@+id/flow_layout"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:padding="10dp" >
- </com.example.flowlayout.FlowLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
- <EditText
- android:id="@+id/edit"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:hint="请输入新标签名称" />
- <Button
- android:id="@+id/btn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="添加" />
- </LinearLayout>
- </LinearLayout>
每个标签的布局(tv.xml)如下:
- <?xml version="1.0" encoding="utf-8"?>
- <TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_margin="10dp"
- android:background="@drawable/bg"
- android:text="hello"
- android:textColor="#FFF"
- android:textSize="20sp" >
- </TextView>
标签背景效果(bg.xml)如下:
- <?xml version="1.0" encoding="utf-8"?>
- <shape xmlns:android="http://schemas.android.com/apk/res/android" >
- <solid android:color="#666666" />
- <corners android:radius="15dp" />
- <padding
- android:bottom="5dp"
- android:left="10dp"
- android:right="10dp"
- android:top="5dp" />
- </shape>
0 0
- Android流式布局
- Android 流式布局
- Android流式布局
- Android流式布局
- Android流式布局
- Android流式布局
- android流式布局
- Android 流式布局FlowLayout
- Android流式布局实现
- Android流式布局-FlowLayout
- Android流式布局实现
- Android 自定义流式布局
- Android流式布局实现
- Android流式布局实现
- android流式布局控件
- Android流式布局FlowLayout
- Android:FlowLayout流式布局
- Android 流式布局LinearLayout
- 计算时间和时差
- CentOS6.5环境下配置JDK+Tomcat+MySQL下载链接https://yunpan.cn/cR5WcYqYg8mi3
- 如何从项目中移除CocoaPods(译)
- LeetCode 226. Invert Binary Tree
- 关于使用json数据传递的时候hibernate的懒加载问题
- Android流式布局
- JDK环境变量的设置
- PAT天梯赛练习题——L3-007. 天梯地图(多边权SPFA)
- __stdcall,__cdecl,_declspec,__fastcall的区别
- (OK)(OK) docker-(centos-quagga-ospf-mdr)--NS3--MANET
- 网页浏览器知道我们的哪些信息?(2)
- mac myeclipse2015安装SVN插件
- [cscope] cscope usage
- 8-7History 对象