废话不多说,先上效果图。
这样的效果图,在我们日常的开发需求中比较常见,尤其是商城类型,凡是有列表,有排序的都离不了。
借此,练习一下自定义viewgroup。
首先,自定义的第一步,实现四个构造函数。
以此为例。
此处,简单介绍一下,这几个构造函数。
第一个,如果我们是在Java代码中使用的 new 对象,多是调用的第一个方法。
第二个,一般情况下,我们将控件写到xml 中,会调用这个方法。以我们最熟悉的TextView,ImageView等为例,都是有默认的
AttributeSet ,所以我们可以在xml中设置背景,字体大小,图片等。
第三个,第四个用到的比较少,目前我也不是很了解,下面贴上我拷贝过来的内容,进行解释。
自定义View的时候,自然要和它的构造函数打交道,目前 一共有四个构造函数,大多数情况下,使用第二个就够了,第一个没什么大用,第三个和第四个都是跟style和theme有关的。
在View类中有四个构造函数,涉及到多个参数,
Context:上下文
AttributeSet attrs: 从xml中定义的参数
int defStyleAttr :主题中优先级最高的属性
int defStyleRes : 优先级次之的内置于View的style
他们的优先级是:
Xml直接定义 > xml中style引用 > defStyleAttr > defStyleRes > theme直接定义
接下来,第二不,就是在第二个构造函数中的一些操作。下面贴出具体的代码
public MySelectView(Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater.from(context).inflate(R.layout.merge_select_layout, this, true); ivListType = findViewById(R.id.ivListType); imageTime = findViewById(R.id.imageTime); imagePrice = findViewById(R.id.imagePrice); textViewTime = findViewById(R.id.tvSelectTime); textViewPrice = findViewById(R.id.tvSelectPrice); relativeOuter = findViewById(R.id.relativeOuter); ivListType.setOnClickListener(this::onClick); imageTime.setOnClickListener(this::onClick); imagePrice.setOnClickListener(this::onClick); TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MySelectView); if (attributes != null) { //设置左边按钮的文字 int bgRes = attributes.getResourceId(R.styleable.MySelectView_title_background_color,-1); if (bgRes != -1) { relativeOuter.setBackgroundResource(bgRes); } //设置左边按钮的文字 String TextTime = attributes.getString(R.styleable.MySelectView_title_text_time); if (!TextUtils.isEmpty(TextTime)) { textViewTime.setText(TextTime); //设置左边按钮文字颜色 } //设置右边按钮的文字 String TextPrice = attributes.getString(R.styleable.MySelectView_title_text_price); if (!TextUtils.isEmpty(TextPrice)) { textViewPrice.setText(TextPrice); //设置左边按钮文字颜色 } //切换时间 int imgTime = attributes.getResourceId(R.styleable.MySelectView_image_time_default_res, -1); if (imgTime != -1) { imageTime.setBackgroundResource(imgTime); } //切换价格 int imgPrice = attributes.getResourceId(R.styleable.MySelectView_image_price_default_res, -1); if (imgPrice != -1) { imagePrice.setBackgroundResource(imgPrice); } //切换横竖排 int imgSelect = attributes.getResourceId(R.styleable.MySelectView_image_select_default_res, -1); if (imgSelect != -1) { ivListType.setBackgroundResource(imgSelect); } attributes.recycle();//释放资源 } }
一个个来解释:
LayoutInflater.from(context).inflate(R.layout.merge_select_layout, this, true); ivListType = findViewById(R.id.ivListType); imageTime = findViewById(R.id.imageTime); imagePrice = findViewById(R.id.imagePrice); textViewTime = findViewById(R.id.tvSelectTime); textViewPrice = findViewById(R.id.tvSelectPrice); relativeOuter = findViewById(R.id.relativeOuter); ivListType.setOnClickListener(this::onClick); imageTime.setOnClickListener(this::onClick); imagePrice.setOnClickListener(this::onClick);
这部分代码是 整个组合控件 布局的引入,以及控件的初始化,也包括设置点击事件等。
TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MySelectView);
这句代码的意思是,拿到我们自定义的属性,其中MySelectView这个是我们自己自定义的,其位置如图所示。
在values下创建,attrs 文件。属性可以根据自己的需要命名,属性根据自己的需要灵活命名,创建。
接下来就是按钮的点击事件的处理。
此处我为了方便使用,创建了一个接口,可以供外部灵活调用。具体实现如下。
到此,自定义view 已经结束,下面看看 在使用的地方如何使用。
自定义的view 在使用的时候,记得加上自己的包名。此处可以根据自己创建的 属性文件 灵活的添加属性设置,根据自己的情况需要。
到此为止,简单的 自定义viewgroup就实现了。妈妈再也不用担心我的代码了,哈哈。
下面贴出完整的代码,供大家参考。
package com.example.mylibrary.weight; import android.content.Context; import android.content.res.TypedArray; import android.os.Build; import android.support.annotation.RequiresApi; import android.text.TextUtils; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.RelativeLayout; import android.widget.TextView; import com.example.mylibrary.R; /** * Time:2019/5/12 * Author:pengzhen * Description:自定义的view 用于解决升序降序与单双排排序的问题 */ public class MySelectView extends RelativeLayout implements View.OnClickListener { private ImageView ivListType;//单双排的排序切换 private ImageView imageTime;//时间的升降选择 private ImageView imagePrice;//价格的升降排序选择 private TextView textViewTime;//时间 private TextView textViewPrice;//价格 private RelativeLayout relativeOuter;//布局 private boolean isSelectTime = true; private boolean isSelectPrice = false; private boolean isSingle = true;//默认是单排 private String typeId;//请求类型的ID private String condition;//请求条件 是时间还是价格 private SelectInterFace selectInterFace; public void setSelectInterFace(SelectInterFace selectInterFace) { this.selectInterFace = selectInterFace; } public MySelectView(Context context) { super(context); } public MySelectView(Context context, AttributeSet attrs) { super(context, attrs); LayoutInflater.from(context).inflate(R.layout.merge_select_layout, this, true); ivListType = findViewById(R.id.ivListType); imageTime = findViewById(R.id.imageTime); imagePrice = findViewById(R.id.imagePrice); textViewTime = findViewById(R.id.tvSelectTime); textViewPrice = findViewById(R.id.tvSelectPrice); relativeOuter = findViewById(R.id.relativeOuter); ivListType.setOnClickListener(this::onClick); imageTime.setOnClickListener(this::onClick); imagePrice.setOnClickListener(this::onClick); TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MySelectView); if (attributes != null) { //设置左边按钮的文字 int bgRes = attributes.getResourceId(R.styleable.MySelectView_title_background_color,-1); if (bgRes != -1) { relativeOuter.setBackgroundResource(bgRes); } //设置左边按钮的文字 String TextTime = attributes.getString(R.styleable.MySelectView_title_text_time); if (!TextUtils.isEmpty(TextTime)) { textViewTime.setText(TextTime); //设置左边按钮文字颜色 } //设置右边按钮的文字 String TextPrice = attributes.getString(R.styleable.MySelectView_title_text_price); if (!TextUtils.isEmpty(TextPrice)) { textViewPrice.setText(TextPrice); //设置左边按钮文字颜色 } //切换时间 int imgTime = attributes.getResourceId(R.styleable.MySelectView_image_time_default_res, -1); if (imgTime != -1) { imageTime.setBackgroundResource(imgTime); } //切换价格 int imgPrice = attributes.getResourceId(R.styleable.MySelectView_image_price_default_res, -1); if (imgPrice != -1) { imagePrice.setBackgroundResource(imgPrice); } //切换横竖排 int imgSelect = attributes.getResourceId(R.styleable.MySelectView_image_select_default_res, -1); if (imgSelect != -1) { ivListType.setBackgroundResource(imgSelect); } attributes.recycle();//释放资源 } } public MySelectView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public MySelectView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public void setTypeId(String typeId) { this.typeId = typeId; } @Override public void onClick(View v) { int i = v.getId(); if (i == R.id.ivListType) { if (isSingle) { ivListType.setImageResource(R.mipmap.ic_list_one); } else { ivListType.setImageResource(R.mipmap.ic_list_two); } isSingle = !isSingle; selectInterFace.whenSelectDirectionChange();//调用相应的方法 } else if (i == R.id.imageTime) { if (isSelectTime) { imageTime.setImageResource(R.mipmap.ic_select_up); } else { imageTime.setImageResource(R.mipmap.ic_select_down); } isSelectTime = !isSelectTime; imagePrice.setImageResource(R.mipmap.ic_select); selectInterFace.whenSelectTimeChange(); } else if (i == R.id.imagePrice) { if (!isSelectPrice) { imagePrice.setImageResource(R.mipmap.ic_select_up); } else { imagePrice.setImageResource(R.mipmap.ic_select_down); } isSelectPrice = !isSelectPrice; imageTime.setImageResource(R.mipmap.ic_select); selectInterFace.whenSelectPriceChange(); } } /**自定义接口,情况分别为 在时间排序变化时,价格排序变化时,横竖排切换排序变化时*/ public interface SelectInterFace { void whenSelectTimeChange(); void whenSelectPriceChange(); void whenSelectDirectionChange(); } }