ListPreference,DialogPreference、PreferenceActivity、RadioButton、RadioGroup、RingtonePreference、TextView、View、ViewGroup
package com.hyz;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
public class TypedefRadioButton extends RadioButton implements OnCheckedChangeListener
{
private String mValue;
public String getValue() {
return this.mValue;
}
public void setValue(String value) {
this.mValue = value;
}
public TypedefRadioButton(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public TypedefRadioButton(Context context, AttributeSet attrs)
{
super(context, attrs);
try
{
/**
* TypedArray其实就是一个存放资源的Array,
* 首先从上下文中获取到R.styleable.RadioButton这个属性资源的资源数组。
* attrs是构造函数传进来,应该就是对应attrs.xml文件。
* a.getString(R.styleable.RadioButton_value);
* 这句代码就是获取attrs.xml中定义的属性,并将这个属性的值传给本控件的mValue.最后,
* 返回一个绑定结束的信号给资源:a.recycle();绑定结束。
*/
TypedArray a = context.obtainStyledAttributes(attrs,R.styleable.RadioButton);
this.mValue = a.getString(R.styleable.RadioButton_value);
a.recycle();
} catch (Exception e)
{
e.printStackTrace();
}
setOnCheckedChangeListener(this);
}
public TypedefRadioButton(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
TypedefRadioGroup group = (TypedefRadioGroup) getParent();
group.setTheValue(this.getValue());
}
}
package com.hyz;import android.content.Context;import android.preference.DialogPreference;import android.util.AttributeSet;import android.view.View;import android.widget.TextView;import android.widget.Toast;public class TypedefDialogPreference extends DialogPreference{private int dialogMessage ;public TypedefDialogPreference(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}//程序首先执行此函数public TypedefDialogPreference(Context context, AttributeSet attrs){super(context, attrs);//通过此句得到布局里的自定义变量dialogMessage里的值,括号里第2个参数其实//是一个resId,要得到其字符串值,在布局里只能用dialogMessage = "@string/dialogMessage"形式,//不能用dialogMessage = "字符串"形式。否则得到的是R.string.empty默认值。dialogMessage = attrs.getAttributeResourceValue(null, "dialogMessage", R.string.empty);}//这个函数是为对话框中引用的其它布局而起作用的@Overrideprotected void onBindDialogView(View view)//view 其实代表的就是slider_dialog.xml{TextView tv1 = (TextView)view.findViewById(R.id.slider_message1);tv1.setText("你好呀^_^");TextView tv2 = (TextView)view.findViewById(R.id.slider_message2);tv2.setText(dialogMessage);}@Overrideprotected void onDialogClosed(boolean positiveResult) {super.onDialogClosed(positiveResult);if(positiveResult)Toast.makeText(getContext(), "点击了对话框的确定按钮", Toast.LENGTH_LONG).show();} }
package com.hyz;
import android.app.AlertDialog.Builder;
import android.content.Context;
import android.content.DialogInterface;
import android.preference.ListPreference;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.Toast;
public class TypedefListPreference extends ListPreference
{
//用来保存ListPreference中的列表项的是否选择值
private boolean[] checkedItems;
CharSequence[] entries ;//ListPreference.getEntries(),显示 在列表中的数据
CharSequence[] entryValues;//显示在summary里的值
public TypedefListPreference(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
public TypedefListPreference(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
//点击ok或cancel后触发的事件,自定义视图事件
@Override
protected void onDialogClosed(boolean positiveResult)
{
if(positiveResult)
{
CharSequence[] entryValues = getEntryValues();
StringBuilder str = new StringBuilder();
for(int i = 0 ; i < 7 ; i++)
{
if(checkedItems[i])
{
str.append(entryValues[i]);
}
}
setSummary(str);
}
}
/*此函数复写后,如果函数体为空,则ListPreference对话框内容为空
* 删除此函数的话,系统将自动加载entryValues和entries为对话框的内容
* 因为为自定义的ListPreference,所以复写下面的方法为的就是可以自定义ListPreference对话框的显示内容
*/
@Override
protected void onPrepareDialogBuilder(Builder builder)
{
checkedItems = new boolean[7];
CharSequence[] entries = getEntries();
CharSequence[] entryValues = getEntryValues();
//删除preference.xml中的entries、entryValues将显示Toast
if (entries == null || entryValues == null)
{
Toast.makeText(getContext(), "getEntries()或getEntryValues()为空", Toast.LENGTH_LONG).show();
}
builder.setMultiChoiceItems(entries, checkedItems, new DialogInterface.OnMultiChoiceClickListener()
{
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked)
{
checkedItems[which] = isChecked;
}
});
}
}
public class TypedefPreferenceActivity extends PreferenceActivity
{
private TypedefDialogPreference TDialogPreference;
private TypedefListPreference TListPreference;
@Override
protected void onCreate(Bundle savedInstanceState)
{
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preference);
}
}
package com.hyz;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
public class TypedefRadioGroup extends RadioGroup implements OnCheckedChangeListener
{
private String mValue;
public TypedefRadioGroup(Context context, AttributeSet attrs)
{
super(context, attrs);
this.setOnCheckedChangeListener(this);
}
public TypedefRadioGroup(Context context)
{
super(context);
this.setOnCheckedChangeListener(this);
}
// 设置子控件的值
private void setChildValue()
{
int n = this.getChildCount();
for(int i=0;i<n;i++)
{
TypedefRadioButton radio = (TypedefRadioButton)this.getChildAt(i);
if(radio.getValue().equals(this.mValue))
{
radio.setChecked(false);
}
else
{
radio.setChecked(true);
}
}
}
// 获取子类的值
private void getChildValue()
{
int n = this.getChildCount();
for(int i=0;i<n;i++){
TypedefRadioButton radio = (TypedefRadioButton)this.getChildAt(i);
if(radio.isChecked()){
this.mValue=radio.getValue();
}
}
}
public void setTheValue(String value) {
this.mValue = value;
}
public String getTheValue(){
getChildValue();
return this.mValue;
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
setChildValue();
}
}
package com.hyz;
import android.content.Context;
import android.net.Uri;
import android.preference.RingtonePreference;
import android.util.AttributeSet;
import android.content.Intent;
import android.media.RingtoneManager;
import android.util.Log;
public class TypedefRingtonePreference extends RingtonePreference
{
private boolean mShowDefault;//是否在铃声列表中显示默认铃声选项,否则隐藏
private Uri mUri;
public TypedefRingtonePreference(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
Log.i("cd", "a");
}
//程序首先调用这个函数,其次onRestoreRingtone,再次onPrepareRingtonePickerIntent,最后onSaveRingtone
public TypedefRingtonePreference(Context context, AttributeSet attrs) {
super(context, attrs);
//preference.xml里android:showDefault="true"设置显示“默认铃声”项,而下一句又可以将它隐藏
mShowDefault = getShowDefault();
//是否在铃声列表中显示默认铃声选项,否则隐藏
//getRingtoneType();
//getShowSilent();是否在铃声列表中显示静音选项,否则隐藏
Log.i("cd", "b");
}
public TypedefRingtonePreference(Context context) {
super(context);
// TODO Auto-generated constructor stub
Log.i("cd", "c");
}
//此函数主要用来显示或隐藏铃声列表中某些铃声项
@Override
protected void onPrepareRingtonePickerIntent(Intent ringtonePickerIntent)
{
// TODO Auto-generated method stub
super.onPrepareRingtonePickerIntent(ringtonePickerIntent);
Log.i("cd", "onPrepareRingtonePickerIntent");
//mShowDefault若为false,从列表隐藏”默认铃声“选项
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, mShowDefault);
//虽然android:showSilent="false",但下一句将”静音“选项显示在列表中
ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT,true);
// if(mShowDefault)
// {
// Uri uri = Uri.parse(Settings.System.DEFAULT_RINGTONE_URI.toString());
// ringtonePickerIntent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, uri);
// }
}
//此函数得到所有铃声项及上次所选铃声项
@Override
protected Uri onRestoreRingtone() {
// TODO Auto-generated method stub
Log.i("cd", "onRestoreRingtone");
//此句话能够得到上一次设置的铃声列表以及上次所选铃声项
return RingtoneManager.getActualDefaultRingtoneUri(getContext(), getRingtoneType());
}
//点击确定按钮后将保存铃声路径至自定义变量
@Override
protected void onSaveRingtone(Uri ringtoneUri)
{//注意这个方法 他是实现铃声设置的核心方法
Log.i("cd", "onSaveRingtone");
if(ringtoneUri!=null)
{
mUri = ringtoneUri;
}
//注意添加权限"android.permission.WRITE_SETTINGS"
//保存所选铃声
//第一个参数表示上下文、第二个参数表示设置的铃声状态,第三个表示当前的歌曲uri
RingtoneManager.setActualDefaultRingtoneUri(getContext(), getRingtoneType(), ringtoneUri);
}
}
package com.hyz;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class TypedefTextView extends TextView
{
public TypedefTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
/*
* 当手指从按钮擡起,ACTION_UP
取消,ACTION_CANCEL
手指移出按钮,ACTION_OUTSIDE
另外,要返回false,因为返回true,系统将不会调用drawable/button.xml的效果,
因为true表示自己已经处理了onTouche事件,不需要别的逻辑再处理了。
*/
public TypedefTextView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// TODO Auto-generated constructor stub
this.setOnTouchListener(new OnTouchListener(){
public boolean onTouch(View v, MotionEvent event)
{
if (event.getAction()==MotionEvent.ACTION_CANCEL
||event.getAction()==MotionEvent.ACTION_UP
||event.getAction()==MotionEvent.ACTION_OUTSIDE)
{
Toast.makeText(getContext(), "touch", Toast.LENGTH_LONG).show();
}
return false;
}
});
}
public TypedefTextView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
}
package com.hyz;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.view.View;
//这个出现在main.xml里
/**
* 这个是自定义的TextView.
* 至少需要重载构造方法和onDraw方法
* 对于自定义的View如果没有自己独特的属性,可以直接在xml文件中使用就可以了
* 如果含有自己独特的属性,那么就需要在构造函数中获取属性文件attrs.xml中自定义属性的名称
* 并根据需要设定默认值,放在在xml文件中没有定义。
* 如果使用自定义属性,那么在应用xml文件中需要加上新的schemas,
* 比如这里是xmlns:my="http://schemas.android.com/apk/res/com.hyz"
* 其中xmlns后的“my”是自定义的属性的前缀,res后的是我们自定义View所在的包
*/
public class TypedefView extends View
{
Paint mPaint; //画笔,包含了画几何图形、文本等的样式和颜色信息
public TypedefView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public TypedefView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
//TypedArray是一个用来存放由context.obtainStyledAttributes获得的属性的数组
//在使用完成后,一定要调用recycle方法
//属性的名称是styleable中的名称+“_”+属性名称
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyView);
int textColor = array.getColor(R.styleable.MyView_textColor, 0XFF00FF00); //提供默认值,放置未指定
float textSize = array.getDimension(R.styleable.MyView_textSize, 36);
mPaint.setColor(textColor);
mPaint.setTextSize(textSize);
array.recycle(); //一定要调用,否则这次的设定会对下次的使用造成影响
}
public TypedefView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public void onDraw(Canvas canvas){
super.onDraw(canvas);
//Canvas中含有很多画图的接口,利用这些接口,我们可以画出我们想要的图形
//mPaint = new Paint();
//mPaint.setColor(Color.RED);
mPaint.setStyle(Style.FILL); //设置填充
canvas.drawRect(10, 10, 100, 100, mPaint); //绘制矩形
mPaint.setColor(Color.BLUE);
canvas.drawText("我是被画出来的", 10, 120, mPaint);
}
}
package com.hyz;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
public class TypedefViewGroup extends ViewGroup
{
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
int count = this.getChildCount();
for(int i = 0;i < count;i++)
{
View child = this.getChildAt(i);
child.setVisibility(View.VISIBLE);
child.measure(r-l, b-t);
int x = l;
int y = t;// ??? 心中疑惑:我认为我只要在这里调用child的layout(int,int,int,int)方法给出它的位置和宽高就可以了//如果child本身是一个ViewGroup的话它是否应该自己去管理它本身内部的child的位置和宽度呢???
child.layout(x,y,x + getWidth(),y + getHeight());
}
}
public TypedefViewGroup(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public TypedefViewGroup(Context context, AttributeSet attrs)
{
super(context, attrs);
// TODO Auto-generated constructor stub
}
public TypedefViewGroup(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
}
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<com.hyz.TypedefListPreference
android:key="TListPreference"
android:title="TypedefListPreference"
android:dialogTitle="对话框标题"
android:summary="Summary"
android:dialogIcon="@drawable/hippo"
android:positiveButtonText="OK"
android:entries="@array/days_of_week"
android:entryValues="@array/days_of_week_short"/>
<com.hyz.TypedefDialogPreference
android:key="TDialogPreferecnce"
android:title="TypedefDialogPreference"
android:dialogTitle="对话框标题"
android:dialogLayout="@layout/slider_dialog"
dialogMessage = "@string/dialogMessage"/>
<com.hyz.TypedefRingtonePreference
android:key="TRingtonePreference"
android:title="TypedefRingtonePreference"
android:ringtoneType="alarm"
android:showDefault="true"
android:showSilent="false"/>
</PreferenceScreen>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hello">Hello World, ddd!</string>
<string name="app_name">自定义布局</string>
<string-array name="days_of_week">
<item>"周一"</item>
<item>"周二"</item>
<item>"周三"</item>
<item>"周四"</item>
<item>"周五"</item>
<item>"周六"</item>
<item>"周日"</item>
</string-array>
<string-array name="days_of_week_short">
<item>"一"</item>
<item>"二"</item>
<item>"三"</item>
<item>"四"</item>
<item>"五"</item>
<item>"六"</item>
<item>"日"</item>
</string-array>
<string name="empty">strings.xml</string>
<string name="dialogMessage">在布局里自定义的变量</string>
<style name="CustomWindowTitleBackground">
<item name="android:background">#aa0000</item>
</style>
<!-- 自定义标题栏样式,在程序的android manifest.xml中对应activity中添加属性 android:theme = "@style/test" 就可以了
-->
<style name="test" parent="android:Theme">
<item name="android:windowTitleSize">50dp</item>
<item name="android:windowTitleBackgroundStyle">@style/CustomWindowTitleBackground</item>
</style>
<declare-styleable name="RadioButton"><!-- 控件名称-->
<attr name="value" format="string"/><!-- 属性名称,类型-->
</declare-styleable>
<declare-styleable name="MyView">
<attr name="textColor" format="color"/>
<attr name="textSize" format="dimension"/>
</declare-styleable>
</resources>