博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
可以展开和收起的的LinearLayout
阅读量:5351 次
发布时间:2019-06-15

本文共 12070 字,大约阅读时间需要 40 分钟。

package com.loaderman.expandablelinearlayout;import android.animation.ObjectAnimator;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Color;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;/** * 可以展开的LinearLayout */public class ExpandableLinearLayout extends LinearLayout implements View.OnClickListener {    private static final String TAG = ExpandableLinearLayout.class.getSimpleName();    private TextView tvTip;    private ImageView ivArrow;    private boolean isExpand = false;//是否是展开状态,默认是隐藏    private int defaultItemCount;//一开始展示的条目数    private String expandText;//待展开显示的文字    private String hideText;//待隐藏显示的文字    private boolean useDefaultBottom;//是否使用默认的底部,默认为true使用默认的底部    private boolean hasBottom;//是否已经有底部,默认为false,没有    private View bottomView;    private float fontSize;    private int textColor;    private int arrowResId;    public ExpandableLinearLayout(Context context) {        this(context, null);    }    public ExpandableLinearLayout(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public ExpandableLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ExpandableLinearLayout);        defaultItemCount = ta.getInt(R.styleable.ExpandableLinearLayout_defaultItemCount, 2);        expandText = ta.getString(R.styleable.ExpandableLinearLayout_expandText);        hideText = ta.getString(R.styleable.ExpandableLinearLayout_hideText);        fontSize = ta.getDimension(R.styleable.ExpandableLinearLayout_tipTextSize, UIUtils.sp2px(context, 14));        textColor = ta.getColor(R.styleable.ExpandableLinearLayout_tipTextColor, Color.parseColor("#666666"));        arrowResId = ta.getResourceId(R.styleable.ExpandableLinearLayout_arrowDownImg, R.mipmap.arrow_down);        useDefaultBottom = ta.getBoolean(R.styleable.ExpandableLinearLayout_useDefaultBottom, true);        ta.recycle();        setOrientation(VERTICAL);    }    /**     * 渲染完成时初始化默认底部view     */    @Override    protected void onFinishInflate() {        super.onFinishInflate();        findViews();    }    /**     * 初始化底部view     */    private void findViews() {        bottomView = View.inflate(getContext(), R.layout.item_ell_bottom, null);        ivArrow = (ImageView) bottomView.findViewById(R.id.iv_arrow);        tvTip = (TextView) bottomView.findViewById(R.id.tv_tip);        tvTip.getPaint().setTextSize(fontSize);        tvTip.setTextColor(textColor);        ivArrow.setImageResource(arrowResId);        bottomView.setOnClickListener(this);    }    public void addItem(View view) {        int childCount = getChildCount();        if (!useDefaultBottom){            //如果不使用默认底部            addView(view);            if (childCount > defaultItemCount){                hide();            }            return;        }        //使用默认底部        if (!hasBottom) {            //如果还没有底部            addView(view);        } else {            addView(view, childCount - 2);//插在底部之前        }        refreshUI(view);    }    @Override    public void setOrientation(int orientation) {        if (LinearLayout.HORIZONTAL == orientation) {            throw new IllegalArgumentException("ExpandableTextView only supports Vertical Orientation.");        }        super.setOrientation(orientation);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int childCount = getChildCount();        Log.i(TAG, "childCount: " + childCount);        justToAddBottom(childCount);        super.onMeasure(widthMeasureSpec, heightMeasureSpec);    }    /**     * 判断是否要添加底部     * @param childCount     */    private void justToAddBottom(int childCount) {        if (childCount > defaultItemCount) {            if (useDefaultBottom && !hasBottom) {                //要使用默认底部,并且还没有底部                addView(bottomView);//添加底部                hide();                hasBottom = true;            }        }    }    /**     * 刷新UI     *     * @param view     */    private void refreshUI(View view) {        int childCount = getChildCount();        if (childCount > defaultItemCount) {            if (childCount - defaultItemCount == 1) {                //刚超过默认,判断是否要添加底部                justToAddBottom(childCount);            }            view.setVisibility(GONE);//大于默认数目的先隐藏        }    }    /**     * 展开     */    private void expand() {        for (int i = defaultItemCount; i < getChildCount(); i++) {            //从默认显示条目位置以下的都显示出来            View view = getChildAt(i);            view.setVisibility(VISIBLE);        }    }    /**     * 收起     */    private void hide() {        int endIndex = useDefaultBottom ? getChildCount() - 1 : getChildCount();//如果是使用默认底部,则结束的下标是到底部之前,否则则全部子条目都隐藏        for (int i = defaultItemCount; i < endIndex; i++) {            //从默认显示条目位置以下的都隐藏            View view = getChildAt(i);            view.setVisibility(GONE);        }    }    // 箭头的动画    private void doArrowAnim() {        if (isExpand) {            // 当前是展开,将执行收起,箭头由上变为下            ObjectAnimator.ofFloat(ivArrow, "rotation", -180, 0).start();        } else {            // 当前是收起,将执行展开,箭头由下变为上            ObjectAnimator.ofFloat(ivArrow, "rotation", 0, 180).start();        }    }    @Override    public void onClick(View v) {        toggle();    }    public void toggle() {        if (isExpand) {            hide();            tvTip.setText(expandText);        } else {            expand();            tvTip.setText(hideText);        }        doArrowAnim();        isExpand = !isExpand;        //回调        if (mListener != null){            mListener.onStateChanged(isExpand);        }    }    private OnStateChangeListener mListener;    /**     * 定义状态改变接口     */    public interface OnStateChangeListener {        void onStateChanged(boolean isExpanded);    }    public void setOnStateChangeListener(OnStateChangeListener mListener) {        this.mListener = mListener;    }}

 UIUtil.java

package com.loaderman.expandablelinearlayout;import android.content.Context;public class UIUtils {    /**     * dip-->px     */    public static int dip2Px(Context context,int dip) {        // px/dip = density;        // density = dpi/160        // 320*480 density = 1 1px = 1dp        // 1280*720 density = 2 2px = 1dp        float density = context.getResources().getDisplayMetrics().density;        int px = (int) (dip * density + 0.5f);        return px;    }    /**     * 将sp值转换为px值,保证文字大小不变     *     * @param spValue     * @return     */    public static int sp2px(Context context,float spValue) {        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;        return (int) (spValue * fontScale + 0.5f);    }}

 attr.xml

 item_ell_bottom.xml

 ProductBean.java

package com.loaderman.expandablelinearlayout;public class ProductBean {    private String img;    private String name;    private String intro;    private String price;    public ProductBean(String img, String name, String intro, String price) {        this.img = img;        this.name = name;        this.intro = intro;        this.price = price;    }    public String getImg() {        return img;    }    public void setImg(String img) {        this.img = img;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getIntro() {        return intro;    }    public void setIntro(String intro) {        this.intro = intro;    }    public String getPrice() {        return price;    }    public void setPrice(String price) {        this.price = price;    }}

 MainActivity.java

package com.loaderman.expandablelinearlayout;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import com.bumptech.glide.Glide;import butterknife.Bind;import butterknife.ButterKnife;public class MainActivity extends AppCompatActivity {    @Bind(R.id.ell_product)    ExpandableLinearLayout ellProduct;    private String[] imgUrls = new String[]{            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1496728066&di=e5669ad80a241da52b03301ee0ba2749&imgtype=jpg&er=1&src=http%3A%2F%2Fimg.taopic.com%2Fuploads%2Fallimg%2F121017%2F240425-12101H2202646.jpg",            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1496728145&di=c2ece04e1445eaf91fe3f3bf12ad1080&imgtype=jpg&er=1&src=http%3A%2F%2Fimg1.qunarzz.com%2Ftravel%2Fd6%2F1610%2F33%2F21ce9c91e70ab7b5.jpg_r_720x480x95_b2bcd2c5.jpg",            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1496728182&di=1e06ea8b74863155b9d52736093beda8&imgtype=jpg&er=1&src=http%3A%2F%2Fe.hiphotos.baidu.com%2Fbainuo%2Fcrop%3D0%2C0%2C470%2C285%3Bw%3D470%3Bq%3D79%2Fsign%3Da8aa38e3b73533fae1f9c96e95e3d12f%2F6c224f4a20a44623b885148f9e22720e0df3d794.jpg",            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1496133522433&di=1132cb36274a205f8ce30e21f47a37ee&imgtype=0&src=http%3A%2F%2Fi3.s2.dpfile.com%2Fpc%2Fb68a2a4316ae56373e83ce65ad7dfada%2528249x249%2529%2Fthumb.jpg",            "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1496728305&di=444bfe10c434c09043855e7a6a7f8ace&imgtype=jpg&er=1&src=http%3A%2F%2Fe.hiphotos.baidu.com%2Fbainuo%2Fcrop%3D0%2C0%2C470%2C285%3Bw%3D470%3Bq%3D99%2Fsign%3D65498f21374e251ff6b8beb89ab6e527%2F0df3d7ca7bcb0a46d662a6226c63f6246b60af6c.jpg"    };    private String[] names = new String[]{            "炒河粉",            "炒米粉",            "隆江猪脚饭",            "烧鸭饭",            "叉烧饭"    };    private String[] intros = new String[]{            "好吃又不腻",            "精选上等米粉,绝对好吃",            "隆江猪脚饭,肥而不腻,入口香爽,深受广东人民的喜爱",            "简单而美味,充满烧腊香味",            "色香味俱全"    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.bind(this);        ellProduct.removeAllViews();//清除所有的子View(避免重新刷新数据时重复添加)        //添加数据        for (int i = 0; i < 5; i++) {            View view = View.inflate(this, R.layout.item_product, null);            ProductBean productBean = new ProductBean(imgUrls[i], names[i], intros[i], "12.00");            ViewHolder viewHolder = new ViewHolder(view, productBean);            viewHolder.refreshUI();            ellProduct.addItem(view);//添加子条目        }    }class ViewHolder {        @Bind(R.id.iv_img)        ImageView ivImg;        @Bind(R.id.tv_name)        TextView  tvName;        @Bind(R.id.tv_intro)        TextView  tvIntro;        @Bind(R.id.tv_price)        TextView  tvPrice;        ProductBean productBean;        public ViewHolder(View view, ProductBean productBean) {            ButterKnife.bind(this, view);            this.productBean = productBean;        }        private void refreshUI() {            Glide.with(MainActivity.this)                    .load(productBean.getImg())                    .placeholder(R.mipmap.ic_launcher)                    .into(ivImg);            tvName.setText(productBean.getName());            tvIntro.setText(productBean.getIntro());            tvPrice.setText("¥" + productBean.getPrice());        }    }}

 item_product.xml

 最后添加依赖:

compile 'com.github.bumptech.glide:glide:3.7.0'    compile 'com.jakewharton:butterknife:7.0.0'

 添加网络权限:

 效果图:

 


 

学习来源:


 

转载于:https://www.cnblogs.com/loaderman/p/7153887.html

你可能感兴趣的文章
关于Entity Framework中的Attached报错的完美解决方案终极版
查看>>
Selenium之Web页面滚动条滚操作
查看>>
组合数据类型练习,英文词频统计实例上
查看>>
Uber回馈开源的一些软件
查看>>
day 3 修改haproxy.cfg 作业
查看>>
UIScrollView —— 缩放实现案例(二)
查看>>
【Qt】Qt Linguist介绍【转】
查看>>
sim usim Uim 区别
查看>>
网页中插入透明Flash的方法和技巧
查看>>
动态内存申请函数选择(realloc、malloc 、alloca、 calloc)
查看>>
获取元素属性get_attribute
查看>>
视觉设计师的进化
查看>>
Python/jquery
查看>>
WPF之Binding
查看>>
【BZOJ】【2132】圈地计划
查看>>
Lua 语言基本语法
查看>>
ARM 的Thumb状态测试
查看>>
windows下读取utf-8文件
查看>>
apache 启动不了的排查方法
查看>>
Java有没有goto?
查看>>