android 自定义属性通过反射关联组件与方法

关于Android里自定义属性的使用网上已经有很多介绍了,比如:
在Button组件里有android:onClick属性,其值是点击Button时触发的方法的名称。我这里想说的就是添加这种属性方法的方法。 比如我们现在有这样一个自定义组件:

它是由一个TextView,一个SeekBar,再加一个TextView组成:
//aq_mic_seekbar.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mic_seekbar"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" 
    android:gravity="center"
    android:background="#ff0000"
    >
    <TextView
        android:id="@+id/mic_seekbar_title"
        android:layout_width="100dp"
        android:layout_height="30dp"
        android:hint="title"
        android:gravity="center"
        android:background="#00ff00"
        />
    <SeekBar 
        android:id="@+id/mic_seekbar_seekbar"
        android:layout_width="200dp"
        android:layout_height="30dp"
        android:max="100"
        android:progress="50"
        />
    <TextView
        android:id="@+id/mic_seekbar_value"
        android:layout_width="50dp"
        android:layout_height="30dp"
        android:hint="value"
        android:gravity="center"
        android:background="#00ff00"
        />
</LinearLayout>
//AQmic_seekbar.java
public class AQmic_seekbar extends LinearLayout {
    public AQmic_seekbar(Context context) {
        this(context,null);
        // TODO Auto-generated constructor stub
    }
    public AQmic_seekbar(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        LayoutInflater.from(context).inflate(R.layout.aq_mic_seekbarthis,true);
    }
}
 
//activity_main.xml

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center" >
    <com.example.aqmic.AQmic_seekbar
        android:layout_width="500dp"
        android:layout_height="50dp" />
</RelativeLayout>
 
//MainActivity.java
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
}
 
现在我们为这个组件添加一个onSeekBarChange属性,其值是当组件里的SeekBar改变时触发的方法的名称。
//attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="AQmic_seekbar">
        <attr name="onSeekBarChange" format="string" />     
    </declare-styleable>
</resources>
然后在我们的组件类文件里对该属性进行处理,这也是最关键的地方:
//AQmic_seekbar.xml
public class AQmic_seekbar extends LinearLayout {
    
    Method mMethod;
    SeekBar mSeekBar;
    Context mContext;
    public AQmic_seekbar(Context context) {
        this(context,null);
        // TODO Auto-generated constructor stub
    }
    public AQmic_seekbar(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        LayoutInflater.from(context).inflate(R.layout.aq_mic_seekbarthis,true);
        mSeekBar = (SeekBar)findViewById(R.id.mic_seekbar_seekbar);
        mContext = context;
        
        //获取onSeekBarChange属性的值
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.AQmic_seekbar);
        CharSequence onSeekBarChange = ta.getText(R.styleable.AQmic_seekbar_onSeekBarChange);
        try {
            //根据方法名获取方法
            mMethod = context.getClass().getMethod((String)onSeekBarChange, View.class);
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {            
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress,
                    boolean fromUser) {
                // TODO Auto-generated method stub
                try {
                    //调用方法
                    mMethod.invoke(mContext, seekBar);
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            public void onStartTrackingTouch(SeekBar seekBar) {}
            public void onStopTrackingTouch(SeekBar seekBar) {}
        });
        ta.recycle();
    }
}
 
最后修改activity_main.xml,为我们的组件添加该属性,并在主Activity文件里实现该方法:
//activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:myspace="http://schemas.android.com/apk/res/com.example.aqmic"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center" >
    <com.example.aqmic.AQmic_seekbar
        android:id="@+id/mySeekBar"
        android:layout_width="500dp"
        android:layout_height="50dp" 
        myspace:onSeekBarChange="onMySeekBarChange"
        />
</RelativeLayout>
//MainActivity.java
public class MainActivity extends Activity {
    SeekBar mSeekBar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    
    public void onMySeekBarChange(View view)
    {
        mSeekBar = (SeekBar)view;
        mSeekBar.setProgress(mSeekBar.getMax());
    }
}
 
这样当SeekBar组件进度值发生改变时,其进度值就会变为最大了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值