TypedefViewTest

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>



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章