zoukankan      html  css  js  c++  java
  • Android流式布局控件

    1,自定义flowlayout代码

    package com.hyang.administrator.studentproject.widget;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.View;
    import android.view.ViewGroup;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by Administrator on 2017/6/20.
     */
    public class FlowGroupView extends ViewGroup {
        /**
         * 储存所有的view 按行记录
         */
        private List<List<View>> mAllViews = new ArrayList<List<View>>();
        /**
         * 记录每一行的高度
         */
        private List<Integer> mLineHeight = new ArrayList<Integer>();
        private String TAG = "TAG";
    
        public FlowGroupView(Context context, AttributeSet attrs,
                             int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        public FlowGroupView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public FlowGroupView(Context context) {
            super(context);
        }
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            // 置空 view 容器 和 lineHeight 容器  重新赋值
            //因为OnMeasure方法会走两次,第一次是实例化这个对象的时候高度和宽度都是0
            //之后走了OnSizeChange()方法后 又走了一次OnMeasure,所以要把第一次加进去的数据清空。
            mAllViews.clear();
            mLineHeight.clear();
            //得到上级容器为其推荐的宽高和计算模式
            int specWidthMode = MeasureSpec.getMode(widthMeasureSpec);
            int specHeighMode = MeasureSpec.getMode(heightMeasureSpec);
            int specWidthSize = MeasureSpec.getSize(widthMeasureSpec);
            int specHeighSize = MeasureSpec.getSize(heightMeasureSpec);
            // 计算出所有的 child 的 宽和高
    //      measureChildren(specWidthSize, specHeighSize);
            // 记录如果是 warp_content 是设置的宽和高
            int width = 0;
            int height = 0;
            // 得到子view的个数
            int cCount = getChildCount();
            /**
             * 记录每一行的宽度,width不断取最大宽度
             */
            int lineWidth = 0;
            /**
             * 每一行的高度,累加至height
             */
            int lineHeight = 0;
    
            // 存储每一行所有的childView
            List<View> lineViews = new ArrayList<View>();
    
            for (int i = 0; i < cCount; i++) {
                // 得到每个子View
                View child = getChildAt(i);
                // 测量每个子View的宽高
                measureChild(child, widthMeasureSpec, heightMeasureSpec);
                // 当前子view的lp
                MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
                // 子view的宽和高
                int cWidth = 0;
                int cheight = 0;
                // 当前子 view 实际占的宽
                cWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
                // 当前子View 实际占的高
                cheight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
                lineHeight=cheight;
                // 需要换行
                if(lineWidth + cWidth > specWidthSize){
                    width = Math.max(lineWidth, cWidth);// 取最大值
                    lineWidth = cWidth; // 开启新行的时候重新累加width
                    // 开启新行时累加 height
    //              lineHeight = cheight; // 记录下一行的高度
                    mAllViews.add(lineViews);
                    mLineHeight.add(cheight);
                    lineViews = new ArrayList<>();
                    // 换行的时候把该 view 放进 集合里
                    lineViews.add(child);// 这个  view(child) 是下一行的第一个view
                    height += cheight; //每个View高度是一样的,直接累加
                    Log.e("需要换行", "hight--" + height);
                    Log.e("onMeasure", "AllViews.size()  --  > " + mAllViews.size());
                }else {
                    // 不需要换行
                    lineWidth += cWidth;//
                    Log.e("不需要换行","hight--"+height);
                    // 不需要换行时 把子View add 进集合
                    lineViews.add(child);
                }
    
                if(i == cCount-1){
                    // 如果是最后一个view
                    width = Math.max(lineWidth, cWidth);
                    height += cheight;
                    Log.e("最后一个view","hight--"+height);
                }
            }
            // 循环结束后 把最后一行内容add进集合中
            mLineHeight.add(lineHeight); // 记录最后一行
            mAllViews.add(lineViews);
            // MeasureSpec.EXACTLY 表示设置了精确的值
            // 如果 mode 是 MeasureSpec.EXACTLY 时候,则不是 warp_content 用计算来的值,否则则用上级布局分给它的值
            setMeasuredDimension(
                    specWidthMode == MeasureSpec.EXACTLY ? specWidthSize : width,
                    specHeighMode == MeasureSpec.EXACTLY ? specHeighSize : height
            );
            Log.e("onMeasure", "mAllViews.size() -- > " + mAllViews.size() + "   mLineHeight.size() -- > " + mLineHeight.size() + "Height -- > "+height);
        }
    
        /**
         * 所有childView的位置的布局
         */
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            // 当前行的最大高度
            int lineHeight = 0;
            // 存储每一行所有的childView
            List<View> lineViews = new ArrayList<View>();
            int left = 0;
            int top = 0;
            // 得到总行数
            int lineNums = mAllViews.size();
            for (int i = 0; i < lineNums; i++)
            {
                // 每一行的所有的views
                lineViews = mAllViews.get(i);
                // 当前行的最大高度
                lineHeight = mLineHeight.get(i);
    
                Log.e("onLayout" , "第" + i + "行 :" + lineViews.size()+"-------lineHeight"+ lineHeight);
    
                // 遍历当前行所有的View
                for (int j = 0; j < lineViews.size(); j++)
                {
                    View child = lineViews.get(j);
                    if (child.getVisibility() == View.GONE)
                    {
                        continue;
                    }
                    MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
    
                    //计算childView的left,top,right,bottom
                    int lc = left + lp.leftMargin;
                    int tc = top + lp.topMargin;
                    int rc =lc + child.getMeasuredWidth();
                    int bc = tc + child.getMeasuredHeight();
    
                    child.layout(lc, tc, rc, bc);
    
                    left += child.getMeasuredWidth() + lp.rightMargin + lp.leftMargin;
                }
                left = 0;
                top += lineHeight;
            }
            Log.v("onLayout", "onLayout   mAllViews.size() -- > " + mAllViews.size() + "   mLineHeight.size() -- > "+ mLineHeight.size());
        }
    
    
        /**
         * 这个一定要设置,否则会包强转错误
         * 设置它支持 marginLayoutParams
         */
        @Override
        public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
    
            return new MarginLayoutParams(getContext(),attrs);
        }
    }

    2.在布局文件中使用

    1 <com.hyang.administrator.studentproject.widget.FlowGroupView
    2     android:id="@+id/flow_view_group"
    3     android:layout_width="match_parent"
    4     android:layout_height="wrap_content">
    5 </com.hyang.administrator.studentproject.widget.FlowGroupView>

    3.TextView的样式文件

    <?xml version="1.0" encoding="utf-8"?>
    <shape xmlns:android="http://schemas.android.com/apk/res/android" >
    
        <solid android:color="#E7E7E7" >
        </solid>
        <corners
            android:radius="30dp"
            />
    
        <padding
            android:bottom="2dp"
            android:left="10dp"
            android:right="10dp"
            android:top="2dp" />
    </shape>

    4.在Activity中使用

     1 package com.hyang.administrator.studentproject.activity;
     2 
     3 import android.graphics.Color;
     4 import android.os.Bundle;
     5 import android.support.v7.app.AppCompatActivity;
     6 import android.view.View;
     7 import android.view.ViewGroup;
     8 import android.widget.Button;
     9 import android.widget.TextView;
    10 import android.widget.Toast;
    11 
    12 import com.hyang.administrator.studentproject.R;
    13 import com.hyang.administrator.studentproject.widget.FlowGroupView;
    14 
    15 import org.xutils.view.annotation.ViewInject;
    16 import org.xutils.x;
    17 
    18 import java.util.ArrayList;
    19 
    20 public class FlowLayoutActivity extends AppCompatActivity {
    21 
    22     @ViewInject(R.id.flow_button)
    23     private Button addTextButton;
    24     @ViewInject(R.id.flow_view_group)
    25     private FlowGroupView flowView;
    26 
    27     private ArrayList<String> names;
    28 
    29 
    30     @Override
    31     protected void onCreate(Bundle savedInstanceState) {
    32         super.onCreate(savedInstanceState);
    33         setContentView(R.layout.activity_flow_layout);
    34         x.view().inject(this);
    35 
    36         setTwoFlowLayout();
    37 
    38         addTextButton.setOnClickListener(new View.OnClickListener() {
    39             @Override
    40             public void onClick(View v) {
    41                 addTextView("添加1");
    42             }
    43         });
    44     }
    45 
    46     private void setTwoFlowLayout() {
    47         //添加数据
    48         names = new ArrayList<String>();
    49         names.add("降龙十八掌");
    50         names.add("黯然销魂掌");
    51         names.add("左右互搏术");
    52         names.add("七十二路空明拳");
    53         names.add("小无相功");
    54         names.add("拈花指");
    55         names.add("打狗棍法");
    56         names.add("蛤蟆功");
    57         names.add("九阴白骨爪");
    58         names.add("一招半式闯江湖");
    59         names.add("醉拳");
    60         names.add("龙蛇虎豹");
    61         names.add("葵花宝典");
    62         names.add("吸星大法");
    63         names.add("如来神掌警示牌");
    64         //为布局添加内容
    65         for (int i = 0; i < names.size(); i++) {
    66             addTextView(names.get(i));
    67         }
    68     }
    69 
    70     /**
    71      * 动态添加布局
    72      * @param str
    73      */
    74     private void addTextView(String str) {
    75         TextView child = new TextView(this);
    76         ViewGroup.MarginLayoutParams params = new ViewGroup.MarginLayoutParams(ViewGroup.MarginLayoutParams.WRAP_CONTENT, ViewGroup.MarginLayoutParams.WRAP_CONTENT);
    77         params.setMargins(5, 5, 5, 5);
    78         child.setLayoutParams(params);
    79         child.setBackgroundResource(R.drawable.flag);
    80         child.setText(str);
    81         child.setTextColor(Color.WHITE);
    82         initEvents(child);//监听
    83         flowView.addView(child);
    84     }
    85 
    86     /**
    87      * 为每个view 添加点击事件
    88      */
    89     private void initEvents(final TextView tv){
    90         tv.setOnClickListener(new View.OnClickListener() {
    91 
    92             @Override
    93             public void onClick(View v) {
    94                 Toast.makeText(FlowLayoutActivity.this, tv.getText().toString(), Toast.LENGTH_SHORT).show();
    95             }
    96         });
    97     }
    98 }
  • 相关阅读:
    C/C++中volatile关键字详解(转)
    Spring中 @Autowired标签与 @Resource标签 的区别(转)
    [转]各种互斥量的总结
    nginx限制ip访问(转)
    HDU 4833 Best Financing (DP)
    HDU 4832 Chess (DP)
    HDU 4831 Scenic Popularity
    POJ 2155 Matrix (二维线段树)
    POJ 2155 Matrix (二维树状数组)
    HDU 4819 Mosaic (二维线段树)
  • 原文地址:https://www.cnblogs.com/yoyohong/p/7056727.html
Copyright © 2011-2022 走看看