自定义组合控件的使用(含有自定义属性)

功能:用一个类充当一个布局,然后在另一个布局中引用该类,显示出充当的那个布局的效果

布局文件: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);
    }
}

效果图:

    

 

posted @ 2016-08-08 09:04  ts-android  阅读(557)  评论(0编辑  收藏  举报