android 动态添加View

项目中遇到动态添加view的需求来展示视频画面,整理一下供大家参考
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.cloudroom.cloudroomvideosdk.model.UsrVideoId;
import com.example.chenhe.s.sxlivevideo.R;
import com.example.chenhe.s.sxlivevideo.common.Constants;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author:chenhe
 * @date:2019/4/1 11:44
 */
public class FlowTagLayout extends ViewGroup {

    private Context context;
    private Rect[] childrenBounds;

//    private List<String> tagList;
    private ArrayList<UsrVideoId> tagWatchableVideos;
    ArrayList<UsrVideoId> WatchVideos = new ArrayList<UsrVideoId>();//所有视频流
    private OnTagClickListener onTagClickListener;

    private int defaultColor = Color.parseColor("#666666");
    private float defaultTextSize = Utils.spToPx(16);

    /****************** 自定义的Attribute *************************/
    private int leftMargin;
    private int rightMargin;
    private int topMargin;
    private int bottomMargin;
    private int leftPadding;
    private int rightPadding;
    private int topPadding;
    private int bottomPadding;
    private int background;
    private int textColor;
    private float textSize;
    public static int devd_w = 2;
    public static int devd_h = 1;
    private int screenWidth;
    private int screenHeight;

    public FlowTagLayout(Context context) {
        super(context);
        this.context = context;
    }

    public FlowTagLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init(attrs);
        getScreenSize();
    }

    public FlowTagLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init(attrs);
        getScreenSize();
    }

    private void init(AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FlowTagLayout);
        leftMargin = (int) typedArray.getDimension(R.styleable.FlowTagLayout_item_leftMargin, 0);
        rightMargin = (int) typedArray.getDimension(R.styleable.FlowTagLayout_item_rightMargin, 0);
        topMargin = (int) typedArray.getDimension(R.styleable.FlowTagLayout_item_topMargin, 0);
        bottomMargin = (int) typedArray.getDimension(R.styleable.FlowTagLayout_item_bottomMargin, 0);
        leftPadding = (int) typedArray.getDimension(R.styleable.FlowTagLayout_item_leftPadding, 0);
        rightPadding = (int) typedArray.getDimension(R.styleable.FlowTagLayout_item_rightPadding, 0);
        topPadding = (int) typedArray.getDimension(R.styleable.FlowTagLayout_item_topPadding, 0);
        bottomPadding = (int) typedArray.getDimension(R.styleable.FlowTagLayout_item_bottomPadding, 0);
        background = typedArray.getResourceId(R.styleable.FlowTagLayout_item_background, -1);
        textColor = typedArray.getColor(R.styleable.FlowTagLayout_item_textColor, defaultColor);
        textSize = typedArray.getDimension(R.styleable.FlowTagLayout_item_textSize, defaultTextSize);
        typedArray.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.e("onMeasure", "----------------------onMeasure----------------------");
        // 已用宽度
        int widthUsed = getPaddingLeft();
        // 已用高度
        int heightUsed = getPaddingTop();
        // 当前行高度
        int lineHeight = 0;
        // 当前行宽度
        int lineWidth = 0;
        // 本身的宽度
        int parentWidth = 0;
        // 本身的高度
        int parentHeight = 0;

        int specWidth = MeasureSpec.getSize(widthMeasureSpec);
        int specWidthMode = MeasureSpec.getMode(widthMeasureSpec);
        int specHeight = MeasureSpec.getSize(heightMeasureSpec);
        int specHeightMode = MeasureSpec.getMode(heightMeasureSpec);

        int childCount = getChildCount();
        if (childrenBounds == null) {
            childrenBounds = new Rect[childCount];
        } else if (childrenBounds.length < childCount) {
            childrenBounds = Arrays.copyOf(childrenBounds, childCount);
        }

        // 遍历测量子view
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            // 测量子view
            measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
            MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
            // 判断是否换行(1.不是非限制  2.已用宽度+当前添加的child宽度+左右的padding 是否大于 父view自身测量的宽度)
            int paddingRight = getPaddingRight();
            Log.e("20000", paddingRight + ":padding");
            Log.e("20000", lp.leftMargin + ":margin");
            Log.e("20000", child.getMeasuredWidth() + ":width");
            widthUsed = widthUsed + leftMargin;
            if (specWidthMode != MeasureSpec.UNSPECIFIED &&
                    widthUsed + child.getMeasuredWidth() + rightMargin + getPaddingRight() > specWidth) {
                parentWidth = specWidth;
                widthUsed = getPaddingLeft() + leftMargin;
                // 已用高度 = 之前已用高度 + 当前行的高度
                heightUsed = heightUsed + lineHeight;
                measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
                measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
            }

            Rect childBounds = childrenBounds[i];
            if (childBounds == null) {
                childBounds = childrenBounds[i] = new Rect();
            }

            lineHeight = child.getMeasuredHeight() + topMargin + bottomMargin;

            // 保存child的位置
            childBounds.set(widthUsed, heightUsed + topMargin,
                    widthUsed + child.getMeasuredWidth(), heightUsed + lineHeight - bottomMargin);
            // 当前行已用的宽度
            widthUsed = widthUsed + child.getMeasuredWidth() + rightMargin;
        }

        // 因为换行parentWidth会被赋值,所以需要对比是否换行过赋值后的parentWidth
        parentWidth = Math.max(parentWidth, widthUsed + getPaddingRight());
        // 父view的高度 = 已用高度 + 当前行高度 + padding
        parentHeight = heightUsed + lineHeight + getPaddingBottom();

        setMeasuredDimension(resolveSizeAndState(parentWidth, widthMeasureSpec, 0),
                resolveSizeAndState(parentHeight, heightMeasureSpec, 0));
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        for (int i = 0; i < getChildCount(); i++) {
            View view = getChildAt(i);
            Rect childRect = childrenBounds[i];
            view.layout(childRect.left, childRect.top, childRect.right, childRect.bottom);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    /**
     * 必须重写这个方法,不然measure的时候child.getLayoutParams()的margin是为0的
     *
     * @param attrs
     * @return
     */
    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        return new MarginLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    }

    /**
     * 添加tags列表
     *
     * @param watchableVideos
     */
    public void addTags(ArrayList<UsrVideoId> watchableVideos) {
        Log.e("调试方法","--------addTags"+watchableVideos.toString());
        if (tagWatchableVideos == null) {
            tagWatchableVideos = new ArrayList<>();
        } else {
            tagWatchableVideos.clear();
        }
//        tagWatchableVideos.addAll(watchableVideos);
        tagWatchableVideos = watchableVideos;
        setDevid(tagWatchableVideos.size());
        loadTagView();
    }

    /**
     * 添加控件数量
     *
     * @param num
     */
    public void addTags(int num) {
        Log.e("视频","addTags(int num)");
        setDevid(num);

        for (int i = 0; i < num; i++) {
            setTagContent(i);
        }

    }

    /**
     * 初始化tags
     */
    private void setDevid(int num) {


        switch (num) {
            case 0:
            case 1:
                devd_w = 1;
                devd_h = 1;
                break;
            case 2:
                devd_w = 2;
                devd_h = 1;
                break;

            case 3:
                devd_w = 2;
                devd_h = 2;
                break;

            case 4:
                devd_w = 2;
                devd_h = 2;
                break;

            case 5:
                devd_w = 3;
                devd_h = 2;
                break;

            case 6:
                devd_w = 3;
                devd_h = 2;
                break;

            case 7:
                devd_w = 4;
                devd_h = 2;
                break;

            case 8:
                devd_w = 4;
                devd_h = 2;
                break;

            case 9:
                devd_w = 3;
                devd_h = 3;
                break;

            default:
                devd_w = 2;
                devd_h = 2;
                break;

        }

    }


    /**
     * 初始化tags
     */
    private void loadTagView() {
        removeAllViews();
        Log.e("调试方法","--------loadTagView");
        for (int i = 0; i < tagWatchableVideos.size(); i++) {
            setTagContent(i);
        }
    }

    /**
     * 添加到尾部
     *
     * @param label
     */
    public void addTag(UsrVideoId label) {
        Log.e("调试方法","--------addTaglabel");

        if (tagWatchableVideos == null) {
            tagWatchableVideos = new ArrayList<>();
        }

        tagWatchableVideos.add(label);
        setDevid(tagWatchableVideos.size());
        setTagContent(tagWatchableVideos.size() - 1);
    }


    /**
     * 添加到尾部
     *
     * @param videolist
     */
    public void addTag( ArrayList<UsrVideoId> videolist,int pos) {
        Log.e("视频","周到这李addtag");
        WatchVideos.add(videolist.get(pos));
        setDevid(WatchVideos.size());

        setTagContent(WatchVideos.size() - 1);


//        int childCount = getChildCount();
//        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
//        int screenWidth = wm.getDefaultDisplay().getWidth();
//        int screenHeight = wm.getDefaultDisplay().getHeight();
//
//        // 遍历测量子view
//        for (int i = 0; i < childCount; i++) {
//            View child = getChildAt(i);
//            VideoView videoView = child.findViewById(R.id.item_videoview);
//
//            LinearLayout.LayoutParams Params = (LinearLayout.LayoutParams) videoView.getLayoutParams();
//            Params.height = (int) screenHeight / devd_h;
//            Params.width = (int) screenWidth / devd_w;
//            videoView.setLayoutParams(Params);
//
//            if (i<=WatchVideos.size()){
//                videoView.setUsrVideoId(WatchVideos.get(i));
//            }
//
//        }

    }


    /**
     * 添加tag到index位置
     *
     * @param index
     * @param label
     */
    public void addTagOfIndex(int index, UsrVideoId label) {
        if (tagWatchableVideos == null) {
            tagWatchableVideos = new ArrayList<>();
        }
        tagWatchableVideos.add(index, label);
        setTagOfIndex(index);
    }

    /**
     * 初始化item
     *
     * @param i
     */
    @SuppressLint("NewApi")
    private void setTagContent(int i) {

        Log.e("调试方法","--------setTagContent"+i);
        LayoutInflater.from(context).inflate(R.layout.item_videoview, this);
        // 这里用是getChildAt(index)获取子view,不能直接拿上面inflate的view
        VideoView videoView = getChildAt(i).findViewById(R.id.item_videoview);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);




        lp.setMargins(leftPadding, topPadding, rightPadding, bottomPadding);
        lp.height = (int) screenHeight / devd_h;
        lp.width = (int) screenWidth / devd_w;
        videoView.setLayoutParams(lp);
        Log.e("调试方法","--------setTagContent"+tagWatchableVideos.get(i).toString());
        videoView.setUsrVideoId(tagWatchableVideos.get(i));
//        textView.setText(tagList.get(i));
//        textView.setTextColor(textColor);
//        textView.setTextSize(Utils.pxToSp(textSize));

        refreshTag(tagWatchableVideos.size());

        final int finalI = i;
        if (background == -1) {
            getChildAt(i).setBackground(null);
        } else {
            getChildAt(i).setBackground(getResources().getDrawable(background));
        }
        getChildAt(i).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (onTagClickListener != null) {
                    onTagClickListener.tagClick(finalI);
                }
            }
        });
    }

    /**
     * 添加到index位置,使用的是addView(view ,index),最后需要把点击事件重置
     *
     * @param i
     */
    @SuppressLint("NewApi")
    private void setTagOfIndex(int i) {
        View view = LayoutInflater.from(context).inflate(R.layout.item_tag, null, false);
        addView(view, i);
        // 这里用是getChildAt(index)获取子view,不能直接拿上面inflate的view
//        TextView textView = getChildAt(i).findViewById(R.id.item_text);
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        lp.setMargins(leftPadding, topPadding, rightPadding, bottomPadding);
//        textView.setLayoutParams(lp);
//        textView.setText(tagList.get(i));
//        textView.setTextColor(textColor);
//        textView.setTextSize(Utils.pxToSp(textSize));

        if (background == -1) {
            getChildAt(i).setBackground(null);
        } else {
            getChildAt(i).setBackground(getResources().getDrawable(background));
        }
        for (int j = 0; j < getChildCount(); j++) {
            // 去掉点击事件
            getChildAt(j).setOnClickListener(null);
            final int finalJ = j;
            // 重新绑定点击监听
            getChildAt(j).setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (onTagClickListener != null) {
                        onTagClickListener.tagClick(finalJ);
                    }
                }
            });
        }
    }

    /**
     * 移除最后一个tag
     */
    public void removeTag(int s) {
//        getChildAt(tagList.size() - 1).setOnClickListener(null);
//        removeViewAt(tagList.size() - 1);
//        tagList.remove(tagList.size() - 1);


        getChildAt(s).setOnClickListener(null);
        removeViewAt(s);
        tagWatchableVideos.remove(s);
    }

    /**
     * 更新布局
     */
    public void refreshTag(int num) {

        Log.e("调试方法","refreshTag----->"+num);
        setDevid(num);
//        this.devd = devd;

        int childCount = getChildCount();

        int randomnum = (int) (Math.random() * 10) + 1;//0到10随机数
        // 遍历测量子view
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            VideoView videoView = child.findViewById(R.id.item_videoview);

            LinearLayout.LayoutParams Params = (LinearLayout.LayoutParams) videoView.getLayoutParams();
            Params.height = (int) screenHeight / devd_h;
            Params.width = (int) screenWidth / devd_w;
            videoView.setLayoutParams(Params);
        }
    }


    /**
     * 更新布局
     */
    public void refreshTag( ArrayList<UsrVideoId> watchableVideos ) {

        setDevid(watchableVideos.size());
//        this.devd = devd;

        int childCount = getChildCount();

        // 遍历测量子view
        for (int i = 0; i < childCount; i++) {
            View child = getChildAt(i);
            VideoView videoView = child.findViewById(R.id.item_videoview);

            LinearLayout.LayoutParams Params = (LinearLayout.LayoutParams) videoView.getLayoutParams();
            Params.height = (int) screenHeight / devd_h;
            Params.width = (int) screenWidth / devd_w;
            videoView.setLayoutParams(Params);

            if (i<=watchableVideos.size()){
                videoView.setUsrVideoId(watchableVideos.get(i));
            }

        }
    }


    /**
     * 移除index位置的tag
     *
     * @param usrVideoId
     */
    public void removeTagOfIndex(UsrVideoId usrVideoId) {

        int index = 0;
        for (int i = 0;i<tagWatchableVideos.size();i++){
            if (tagWatchableVideos.get(i).userId.equals(usrVideoId.userId)){
                index = i;
            }
        }

        getChildAt(index).setOnClickListener(null);
        removeViewAt(index);
        tagWatchableVideos.remove(index);
        for (int j = index; j < getChildCount(); j++) {
            // 去掉点击事件
            getChildAt(j).setOnClickListener(null);
            final int finalJ = j;
            // 重新绑定点击监听
            getChildAt(j).setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (onTagClickListener != null) {
                        onTagClickListener.tagClick(finalJ);
                    }
                }
            });
        }

        refreshTag(tagWatchableVideos.size());
    }


    public void removeAllViews(){

        for (int i = 0;i<tagWatchableVideos.size();i++){
            getChildAt(i).setOnClickListener(null);
            removeViewAt(i);
//            tagWatchableVideos.remove(i);
            for (int j = i; j < getChildCount(); j++) {
                // 去掉点击事件
                getChildAt(j).setOnClickListener(null);
                final int finalJ = j;
                // 重新绑定点击监听
                getChildAt(j).setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (onTagClickListener != null) {
                            onTagClickListener.tagClick(finalJ);
                        }
                    }
                });
            }
        }

        tagWatchableVideos.clear();
        refreshTag(0);
    }

    public void setTagClickListener(OnTagClickListener onTagClickListener) {
        this.onTagClickListener = onTagClickListener;
    }

    public interface OnTagClickListener {
        void tagClick(int position);
    }

    private void getScreenSize(){
        DisplayMetrics dm = getResources().getDisplayMetrics();
        screenHeight = dm.heightPixels;
        screenWidth = dm.widthPixels;


        int realScreenH = 0;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {//获取真实高度 包括导航栏 状态栏

            WindowManager wmManager=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            wmManager.getDefaultDisplay().getRealMetrics(dm);
            screenHeight = dm.heightPixels;
        }
    }
}

 

 

//新增
flowTagLayout.addTag(new_otherWatchVideos.get(i));

//移除

flowTagLayout.removeTagOfIndex(old_otherWatchVideos.get(j));

//删除所有

flowTagLayout.removeAllViews();

 

demo

https://download.csdn.net/download/csdndouniwan/11081839

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值