自定义组合控件的使用(含有自定义属性)
功能:用一个类充当一个布局,然后在另一个布局中引用该类,显示出充当的那个布局的效果
布局文件:user_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <!-- 该布局为定义的一个布局,图片为小机器人,文字默认 --> <ImageView android:id="@+id/user_imageView" android:src="@drawable/ic_launcher" android:layout_width="100dp" android:layout_height="100dp"/> <TextView android:id="@+id/user_textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="30sp" android:text="默认的文字"/> </LinearLayout>
自定义类:UserView.java
/** * 目的:将布局文件中的user_layout添加到自定义类中 * 因为user_layout.xml为LinearLayout布局,所以这里也继承它 */ public class UserView extends LinearLayout{ /** * 在xml中使用的时候调用该构造方法 * 步骤: * 1.用该类代表所添加的布局文件 * 2.找到布局中的控件 * View.inflate(context, R.layout.user_layout, UserView.this) * 这样UserView就可以充当user_layout.xml这个布局了,最主要的是在布局中引用 * 这个类就可以显示出user_layout.xml这个布局的效果 * * View view = View.inflate(context, R.layout.user_layout, UserView.this); * 这样通过view.findViewById()也可以找到对应的控件,不过UserView这类就不能充当user_layout.xml这个布局 * 也就不能在布局中引用这个类显示出user_layout.xml的效果 */ public UserView(Context context, AttributeSet attrs) { super(context, attrs); //将user_layout这个布局文件添加到这个类中,传null,获取返回的view也是可以找到里面的控件的 View view = View.inflate(context, R.layout.user_layout, UserView.this); //这里view等于UserView.this,所以可以直接使用this.findViewById ImageView imageView=(ImageView) this.findViewById(R.id.user_imageView); TextView textView=(TextView) this.findViewById(R.id.user_textView); System.out.println("图片id:"+imageView.getId()); System.out.println("文字:"+textView.getText().toString()); } }
在主布局中使用:activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <com.example.user.UserView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/main_userView" /> </RelativeLayout>
然后在主活动中显示上面这个布局.
效果如下:
2.使用自定义属性:
res->values->attrs.xml下的自定义属性:
<?xml version="1.0" encoding="utf-8"?> <!-- name自己随便定义 format的格式定义可以看安卓系统怎么定义的 方法见图: --> <resources> <!-- 声明属性集的名称 根据这个name来解析 --> <declare-styleable name="MyView_parser"> <!-- 声明一个属性 name是 text 类型为 字符串类型 --> <attr name="text" format="string"/> <!-- 声明一个属性 name是img 类型为 引用类型 引用资源id --> <attr name="img" format="reference"/> </declare-styleable> </resources>
activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tang="http://schemas.android.com/apk/res/com.example.user" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <!-- 使用自定义属性设置文本和一个图片 --> <com.example.user.UserView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/main_userView" tang:text="我是在布局中改变后的文本" tang:img="@drawable/image2"/> </RelativeLayout>
UserView.java
/** * 目的:将布局文件中的user_layout添加到自定义类中 * 因为user_layout.xml为LinearLayout布局,所以这里也继承它 */ public class UserView extends LinearLayout{ private ImageView imageView; private TextView textView; /** * 在xml中使用的时候调用该构造方法 * 步骤: * 1.用该类代表所添加的布局文件 * 2.找到布局中的控件 * View.inflate(context, R.layout.user_layout, UserView.this) * 这样UserView就可以充当user_layout.xml这个布局了,最主要的是在布局中引用 * 这个类就可以显示出user_layout.xml这个布局的效果 * * View view = View.inflate(context, R.layout.user_layout, UserView.this); * 这样通过view.findViewById()也可以找到对应的控件,不过UserView这类就不能充当user_layout.xml这个布局 * 也就不能在布局中引用这个类显示出user_layout.xml的效果 */ public UserView(Context context, AttributeSet attrs) { super(context, attrs); //将user_layout这个布局文件添加到这个类中,传null,获取返回的view也是可以找到里面的控件的 View view = View.inflate(context, R.layout.user_layout, UserView.this); imageView = (ImageView) this.findViewById(R.id.user_imageView); textView = (TextView) this.findViewById(R.id.user_textView); System.out.println("最开始--图片对象id:"+imageView.getId()); System.out.println("最开始--文字:"+textView.getText().toString()); //结果:最开始--图片对象id:2131230721 最开始--文字:默认的文字 //获在主布局文件中设置的内容 String namespace="http://schemas.android.com/apk/res/com.example.user"; //得到文本内容 String text = attrs.getAttributeValue(namespace, "text"); //得到图片资源id int id = attrs.getAttributeResourceValue(namespace, "img", -1); System.out.println("主布局中的内容-----"+text+", 图片id:"+id); //结果:主布局中的内容-----我是在布局中改变后的文本, 图片id:2130837505(跟R文件中该图片id一致) //将得到的数据设置到控件上 textView.setText(text); imageView.setImageResource(id); } /** * 修改TextView的方法,便于在别的类中对控件内容进行修改 */ public void setText(String str){ textView.setText(str); } /** * 将方法暴露出去,利用该类对象就可以修改该类里面的控件内容 */ public void setImg(int id){ imageView.setImageResource(id); } }
MainActivity.java
/** * 自定义组合控件的使用: */ public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //找打该布局中使用的自定义类的id UserView userView=(UserView) findViewById(R.id.main_userView); //通过该类提供的方法修改控件的内容 userView.setText("我是在主布局中调用方法修改后的文字"); userView.setImg(R.drawable.a); } }
效果图: