客户定制 音量控制 Preference

参考网上代码自己做了一个客户定制 Preference,没有使用 preference的 android:layout 属性,因为总觉得在不同版本系统上难以和其他preference的控件对齐,所以采用仅设置 android:widget_layout 的方式。

先创建自己要定制的 widget_layout 文件“preference_widget_seekbar.xml”:

 

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:paddingRight="?android:attr/scrollbarSize" >

    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:max="60"
        android:minWidth="240dip"
        android:paddingRight="5dp"
        android:progress="20"
        android:textIsSelectable="true" >
    </SeekBar>
    
    <TextView
        android:id="@+id/seekBarPrefValue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/seekBar1"
        android:layout_centerHorizontal="true"
        android:textIsSelectable="true" >
	</TextView>
	
    <TextView
        android:id="@+id/seekBarPrefUnitsLeft"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/seekBar1"
        android:layout_toLeftOf="@id/seekBarPrefValue"
        android:textIsSelectable="true" >
	</TextView>

    <TextView
        android:id="@+id/seekBarPrefUnitsRight"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textIsSelectable="true"
        android:layout_below="@id/seekBar1" 
        android:layout_toRightOf="@id/seekBarPrefValue" >
	</TextView>

</RelativeLayout>

 

 

建立 com.sample.preference.SeekBarPreference 类,用来初始化界面,同步音量滑块表示的preference数据

 

package com.sample.preference;

import com.sample.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.preference.Preference;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class SeekBarPreference extends Preference 
implements OnSeekBarChangeListener
{
    
    private final String TAG = "SeekBarPreference";
    
    //private static final String ANDROIDNS="http://schemas.android.com/apk/res/android";
    private static final String SEEKBAR_PREFS="SeekBarPreference";
    private static final int DEFAULT_VALUE = 50;
    
    Context mContext;
	private int mMaxValue      = 100;
	private int mMinValue      = 0;
	private int mInterval      = 1;
	private int mCurrentValue  = 50;
	private String mUnitsLeft  = "";
	private String mUnitsRight = "";
	private SeekBar mSeekBar;
    
	private TextView mCurrentValueText;

    public SeekBarPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        initPreference(context, attrs);
    }

    public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initPreference(context, attrs);
    }

    private void initPreference(Context context, AttributeSet attrs) {
    	Log.v(TAG,"initPreference");
    	mContext = context;
        updateValuesFromXml(attrs);
        this.setWidgetLayoutResource(R.layout.preference_widget_seekbar);
    }
    
    private void updateValuesFromXml(AttributeSet attrs) {
        mMaxValue = attrs.getAttributeIntValue(SEEKBAR_PREFS, "max", 100);
        mMinValue = attrs.getAttributeIntValue(SEEKBAR_PREFS, "min", 0);
       
        mUnitsLeft = getAttributeStringValue(attrs, SEEKBAR_PREFS, "unitsLeft", "");
        String value = getAttributeStringValue(attrs, SEEKBAR_PREFS, "value", "");
        mUnitsRight = getAttributeStringValue(attrs, SEEKBAR_PREFS, "unitsRight", "");
        
        try {
        	mInterval = attrs.getAttributeIntValue(SEEKBAR_PREFS, "interval", 1);
            if( mInterval <= 0 )
            {
            	mInterval = 1;
            }
        }
        catch(Exception e) {
            Log.e(TAG, "Invalid interval value", e);
        }
        
    }
    
    private String getAttributeStringValue(AttributeSet attrs, String namespace, String name, String defaultValue) {
        String value = attrs.getAttributeValue(namespace, name);
        if(value == null)
            value = defaultValue;
        
        return value;
    }
    
    @Override
    protected View onCreateView(ViewGroup parent){
    	Log.v(TAG, "onCreateView()");
        return super.onCreateView(parent);
    }
    
    @Override
    public void onBindView(View view) {
        super.onBindView(view);
        
        View layout = view;

        Log.v(TAG, "onBindView()");
        mSeekBar = (SeekBar)view.findViewById(R.id.seekBar1);
        mCurrentValueText = (TextView)view.findViewById(R.id.seekBarPrefValue);
        if( null != mCurrentValueText ){
        	mCurrentValueText.setText(String.valueOf(mCurrentValue));
        	mCurrentValueText.setMinimumWidth(30);
        }
        if( null != mSeekBar )
        {
        	mSeekBar.setMax(mMaxValue - mMinValue);
        	mSeekBar.setProgress(mCurrentValue - mMinValue);
        	mSeekBar.setOnSeekBarChangeListener(this);
        }

        TextView unitsRight = (TextView)view.findViewById(R.id.seekBarPrefUnitsRight);
        if( null != unitsRight ){
        	unitsRight.setText(mUnitsRight);
        }
        
        TextView unitsLeft = (TextView)view.findViewById(R.id.seekBarPrefUnitsLeft);
        if( null != unitsLeft ){
        	unitsLeft.setText(mUnitsLeft);  
        }

    }
    
    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        int newValue = progress + mMinValue;
        
        if(newValue > mMaxValue)
            newValue = mMaxValue;
        else if(newValue < mMinValue)
            newValue = mMinValue;
        else if(mInterval != 1 && newValue % mInterval != 0)
            newValue = Math.round(((float)newValue)/mInterval)*mInterval;  
        
        // change rejected, revert to the previous value
        if(!callChangeListener(newValue)){
            seekBar.setProgress(mCurrentValue - mMinValue); 
            return; 
        }

        // change accepted, store it
        mCurrentValue = newValue;
        if( null != mCurrentValueText ){
        	mCurrentValueText.setText(String.valueOf(newValue));
        }
        persistInt(newValue);

    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {}

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        notifyChanged();
    }


    @Override 
    protected Object onGetDefaultValue(TypedArray ta, int index){
        
        int defaultValue = ta.getInt(index, DEFAULT_VALUE);
        return defaultValue;
        
    }

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {

        if(restoreValue) {
            mCurrentValue = getPersistedInt(mCurrentValue);
        }
        else {
            int temp = 0;
            try {
                temp = (Integer)defaultValue;
            }
            catch(Exception ex) {
                Log.e(TAG, "Invalid default value: " + defaultValue.toString());
            }
            
            persistInt(temp);
            mCurrentValue = temp;
        }
        
    }
    
} 

 

 

最后,在preference xml中加入对应项

 

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
	android:title="audioSetting">
	<!-- ... 其他 preference 项 -->

	<com.sample.preference.SeekBarPreference
	    android:key="key_nes_volume_option" 
	    android:title="volumeSetting" 
	    android:summary="volumeSettingSummary" />	

	<!-- ... 其他 preference 项 -->	
</PreferenceScreen>

posted @ 2013-05-10 20:51  javawebsoa  Views(200)  Comments(0Edit  收藏  举报