安卓自定义控件之仅可以显示一行视图的view控件(类似 HorizontalScrollView但不可滑动一行排满不在排)

该控件的功能是显示一行视图,这一行可以无限添加view,以及添加Headview、footview;当本行呗view排列满之后不在排列,如果添加了footview,那么footview肯定会在最后显示。
代码如下:


import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by wangliang on 0022/2016/9/22.
 * 功能:显示一行view,水平的,多个view,最多显示一行
 * 思路:动态添加view,如果添加了尾view的话,则在绘制onlayout的时候余留除尾view的空间,
 * 所有的view取最小view的高度进行压缩显示显示足一整行,显示不足就显示能显示的部分,显示超过,则就显示一行
 */
public class MyHorizontalView extends ViewGroup {
    private Context context;
    private int windowWidth = 0;
    private int nowAllViewWidth = 0;
    private boolean whetherAddHeadView = false;
    private boolean whetherAddFootView = false;
    private String TAG = "MyHorizontalView";
    private List allViews = new ArrayList<>();
    private int maxHeight = 0;
    private View footView;

    public MyHorizontalView(Context context) {
        super(context);
        initSetting(context);
    }

    public MyHorizontalView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public MyHorizontalView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initSetting(context);
    }

    private void initSetting(Context context){
        this.context = context;
        DisplayMetrics dm = new DisplayMetrics();
        //取得窗口属性
        ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(dm);
        windowWidth = dm.widthPixels;

    }

    /**
     * 添加头view
     * @param view
     */
    public void addHeadView(View view, ViewGroup.LayoutParams params){
        if(!whetherAddHeadView) {
            whetherAddHeadView = true;
            allViews.add(0,view);
            super.addView(view, -1,params);
        }
    }

    /**
     * 添加末尾view
     * @param view
     */
    public void addFootView(View view, ViewGroup.LayoutParams params){
        if(!whetherAddFootView) {
            whetherAddFootView = true;
            footView = view;
            super.addView(view, -1,params);
        }
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        super.addView(child, -1,params);
        allViews.add(child);
    }

    @Override
    public void addView(View child) {
        addView(child,-1,null);
    }

    @Override
    public void addView(View child, int index) {
        addView(child, index,null);
    }

    @Override
    public void addView(View child, LayoutParams params) {
        addView(child,-1, params);
    }

    @Override
    protected LayoutParams generateLayoutParams(
            LayoutParams p)
    {
        return new MarginLayoutParams(p);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs)
    {
        return new MarginLayoutParams(getContext(), attrs);
    }

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

    /**
     * 负责设置子控件的测量模式和大小 根据所有子控件设置自己的宽和高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int minHeight = Integer.MAX_VALUE ;

        // 遍历每个子元素
        for (int i = 0; i < getChildCount(); i++)
        {
            View child = getChildAt(i);
            // 测量每一个child的宽和高
            child.measure(0,0);
            // 得到child的lp
            MarginLayoutParams lp = (MarginLayoutParams) child
                    .getLayoutParams();

            minHeight = Math.min(lp.height  + lp.topMargin
                    + lp.bottomMargin,minHeight);

        }
        setMeasuredDimension(widthMeasureSpec, Math.max(minHeight,heightMeasureSpec));

    }

    private boolean whetherLayout;
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {

        if(whetherLayout){
            whetherLayout = false;
        }else {
            whetherLayout = true;
            return;
        }

        //判断是否有尾视图,如果有则需要计算尾视图,为尾视图预留显示空间
        int footViewWidth = 0;
        int footViewBc = 0;
        int footViewLc = 0;
        int footViewTc = 0;
        int footViewRc = 0;
        if(whetherAddFootView && footView != null){
            MarginLayoutParams lp = (MarginLayoutParams) footView.getLayoutParams();
            footView.measure(0,0);
            double beiShu = getHeight() * 1.0 / (footView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
            footViewLc = (int) (lp.leftMargin * beiShu);
            footViewTc = (int) (lp.topMargin * beiShu);
            footViewRc = (int) (footViewLc + (footView.getMeasuredWidth() * beiShu));
            footViewBc = (int) (footViewTc + (footView.getMeasuredHeight() * beiShu));
            footViewWidth = footViewRc - footViewLc;
        }
        //判断是否有尾视图,如果有则需要计算尾视图,为尾视图预留显示空间

        //绘制尾视图其他部分
        int left = 0;
        int nowWidth = 0;
        for(int i = 0 ; i < allViews.size() ; i++){
            View child = allViews.get(i);
            child.measure(0,0);
            if (child.getVisibility() == View.GONE)
            {
                continue;
            }
            MarginLayoutParams lp = (MarginLayoutParams) child
                    .getLayoutParams();
            double beiShu = getMeasuredHeight() * 1.0 / (child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
            //计算childView的left,top,right,bottom
            int lc = (int) (left + lp.leftMargin * beiShu);
            int tc = (int) (lp.topMargin * beiShu);
            int rc = (int) (lc + child.getMeasuredWidth() * beiShu);
            int bc = (int) (tc + child.getMeasuredHeight() * beiShu);
            nowWidth += child.getMeasuredWidth() * beiShu + lp.rightMargin * beiShu
                    + lp.leftMargin * beiShu;
            if(nowWidth + footViewWidth > getMeasuredWidth()){
                break;
            }

            child.layout(lc, tc, rc, bc);
            left += child.getMeasuredWidth() * beiShu + lp.rightMargin * beiShu
                    + lp.leftMargin * beiShu;
        }
        //绘制尾视图其他部分

        //绘制尾视图
        if(whetherAddFootView && footView != null){
            footView.layout(left + footViewLc, footViewTc, left + footViewRc, footViewBc);
        }

    }
}

调用代码(其中RoundRectangleImageView可以更换为其他view):

ViewGroup.MarginLayoutParams lp = null;
        lp = new ViewGroup.MarginLayoutParams(
                80, 80);
        lp.leftMargin = 10;
        lp.rightMargin = 10;
        lp.topMargin = 50;
        lp.bottomMargin = 50;


        RoundRectangleImageView roundRectangleImageView = new RoundRectangleImageView(getContext());
        Picasso.with(getContext()).load(R.drawable.people_head)
                .placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).resize(500,500).into(roundRectangleImageView);
        hv.addHeadView(roundRectangleImageView,lp);
        hv.addFootView(roundRectangleImageView,lp);


        for(int i = 0; i < 10 ; i++){
            roundRectangleImageView = new RoundRectangleImageView(getContext());

            Picasso.with(getContext()).load(R.drawable.ic_launcher)
                    .placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).resize(500,500).into(roundRectangleImageView);
            hv.addView(roundRectangleImageView,lp);
        }

你可能感兴趣的:(自定义控件)