自定义控件中的组合控件

自定义控件之组合控件

写Android代码一直都是用的自带控件,有时候一些部分有重复使用,改起来有麻烦。如果把这部分组装起来,形成一个独立的控件,那不是非常爽。于是,就可以使用组合控件。

就比如:一个搜索框里面带有一些按钮,toolbar等等

其实自定义控件分为两种:

  • 一种是这种组合控件,将原有的控件组装为一个常用的控件;

  • 另一种是完全自己画出来的控件,无法使用自带的控件实现

1.把重复使用的布局抽出来

为你的重复使用一组控件,单独写一个xml文件

例如:一个图片和一个文字组成一个组合控件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
      xmlns:android="http://schemas.android.com/apk/res/android"    
      android:layout_width="match_parent"   
      android:layout_height="match_parent"    
      xmlns:app="http://schemas.android.com/apk/res-auto">    

<ImageView        
	android:id="@+id/image"        
	android:layout_width="wrap_content"        
	android:layout_height="wrap_content"           	
	app:layout_constraintTop_toTopOf="parent"        
	app:layout_constraintLeft_toLeftOf="parent"/>    
	
<TextView        
	android:id="@+id/text"        
	android:layout_width="wrap_content"        
	android:layout_height="wrap_content"        
	android:layout_marginTop="2dp"        						
	app:layout_constraintTop_toBottomOf="@+id/image"        	
	app:layout_constraintLeft_toLeftOf="@+id/image"     
	app:layout_constraintRight_toRightOf="@+id/image"/>

</androidx.constraintlayout.widget.ConstraintLayout>

这样就不用在一个布局文件多次重复写一个东西了。不过,也可以使用merge,这样就不会多一层布局了。当前是在一个constrainlayout布局里面,自定义也是一个constraintlayout。在自定义里面,又去插入xml文件的布局,就多了一层。使用merge的话,就少一层。相应,应该会提高效率。

2.把抽出来的布局与自定义view绑起来
  • 先自定义一个view继承自constraintlayout

  • 在构造函数中,绑定布局文件

    public class MyView extends ConstraintLayout {    
    	
          private String text;    
    	private Drawable image;   
    	private TextView textView;  
    	private ImageView imageView;  
    
          public MyView(Context context) {    
    	      this(context, null);  
          }  
    
          public MyView(Context context, AttributeSet attrs) {     
    	      this(context, attrs, -1);  
          }   
    
          public MyView(Context context, AttributeSet attrs, int defStyleAttr) {        		
                super(context, attrs, defStyleAttr);     
    	      //获取布局       
    	      inflate(context, R.layout.my_view, this);     
    	      textView = findViewById(R.id.text);     
    	      imageView = findViewById(R.id.image);     
    
    	      }  
    	
    	public void setText(String text){     
    	      this.text = text;    
    	      textView.setText(text);  
    	}   
    
    	public void setImage(Drawable drawable){    
    		this.image = drawable;       
    		this.imageView.setImageDrawable(drawable);  
    	}
    }
    
3.设置组合控件的属性

在values文件下,新建一个attrs.xml , 声明自己的属性和属性类型。name为自定义控件的类名,attr的name为属性名,formart为属性类型,(图片这种就是对象引用了)。

<?xml version="1.0" encoding="utf-8"?>
<resources>    
	<declare-styleable name="MyView" >        
		//自定义属性        
		<attr name="myText" format="string"/>        
		<attr name="myImage" format="reference"/>    
	</declare-styleable>
</resources>

然后,在代码中去解析这个自定义的属性。

public MyView(Context context, AttributeSet attrs, int defStyleAttr) {    	
	super(context, attrs, defStyleAttr);    
	//1.获取布局    
	inflate(context, R.layout.my_view, this);   
	textView = findViewById(R.id.text);    
	imageView = findViewById(R.id.image); 
    
	//2.获取属性   
	TypedArray typedArray; 
	typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyView); 
    
    //获取到属性值
	text = typedArray.getString(R.styleable.MyView_myText);    		
	textView.setText(text);   
    //设置属性值
	image = typedArray.getDrawable(R.styleable.MyView_myImage);    		
	imageView.setImageDrawable(image);  
    //记得回收
	typedArray.recycle();
}

自定义属性,其实也是由于你要重复使用,因此一些控件的显示内容要是动态的。要是能像这个textview一样可以在xml中配置,或者使用代码setText(),于是就可以使用自定义属性来配置(纯属个人猜想)。突然想到,如果看了源码,textview的源码,这个textview的属性是不是也都是这么弄。后面再来研究一下。

4.引用自定义组合控件

在main_activity.xml文件中添加如下控件引用:

<com.example.transition.MyView   
	android:layout_width="wrap_content"  
	android:layout_height="wrap_content"  
	app:myImage="@drawable/tol"  
	app:myText="组合控件"/>

然后,运行一下,就可以看到效果了。那么这个图片和text就合成了一个控件。但是应该还有很多细节,需要考虑,让它成为一个真的可以完美使用view。

posted @ 2020-07-04 23:51  sky-walker  阅读(479)  评论(0编辑  收藏  举报