2012-03-16 1 views
11

私が実装しようとしているのは、下の画像(私が二乗した設定)の基本的かつ正確な複製です。環境設定の左側にある何かを押すと、ダイアログが開きます。トグルボタンを押すと、この設定で設定しているものを無効/有効にします。EditTextPreferenceとTogglebuttonを使用して1つのプリファレンスを作成するにはどうすればよいですか?

私は何時間も試してきましたが、私は空手になってきました。これをPreferenceActivityに実装するにはどうすればよいですか?

Preference

EDIT:それは人々が私の質問を誤解しているようです。 PreferenceActivityを使用して私の問題を解決する方法を理解することは非常に重要です。アクティビティではありません。私はそれをXMLで行うのかプログラムで行うのかは気にしない。似たようなものの中で私が使うことのできない答えを私に提供することを控えてください。

EDIT 2:報奨金を追加しました - それはトグルボタンですが、それであれば、あなただけのアンドロイド言うことができるならば、私は本当にこの

+0

嬉しいように見えますSwitchPreference

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > <SwitchPreference android:key="test" android:title="This is test toggle switch" /> </PreferenceScreen>

を使用! :) – Roylee

答えて

17

地獄の男、私は

:-)あなたのアイデアが好きこれはMHの答え@としてちょうど同じですが、より簡潔な。

私は、Switchではなく、ToggleButtonでテストしました。

package android.dumdum; 

import android.content.Context; 
import android.preference.Preference; 
import android.util.AttributeSet; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.LinearLayout; 
import android.widget.TextView; 
import android.widget.ToggleButton; 

public class TogglePreference extends Preference { 

    public TogglePreference(Context context) { 
     super(context); 
    } 

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

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

    public View getView(View convertView, ViewGroup parent) { 
     if (convertView == null) { 
      convertView = new LinearLayout(getContext()); 
      ((LinearLayout) convertView) 
        .setOrientation(LinearLayout.HORIZONTAL); 

      TextView txtInfo = new TextView(getContext()); 

      txtInfo.setText("Test"); 
      ((LinearLayout) convertView).addView(txtInfo, 
        new LinearLayout.LayoutParams(
          LinearLayout.LayoutParams.MATCH_PARENT, 
          LinearLayout.LayoutParams.WRAP_CONTENT, 1)); 

      ToggleButton btn = new ToggleButton(getContext()); 
      ((LinearLayout) convertView).addView(btn); 
     } 

     return convertView; 
    } 
} 

そしてpreferences.xml

<?xml version="1.0" encoding="utf-8"?> 
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > 

    <PreferenceCategory android:title="Test custom preferences" > 
     <android.dumdum.EncryptorEditTextPreference /> 
     <android.dumdum.TogglePreference /> 
    </PreferenceCategory> 

</PreferenceScreen> 

EncryptorEditTextPreferenceは、あなたの質問に関連していないが、それは(EditTextPreferenceを拡張する)同じ技術を使用しています。

0

ない一定の答えを必要とする:テクストンやアンドロイドを:上textoff。 xml。それがJavaの部分にある場合、おそらくsetTextOnのようなものです。それがトグルボタンであるかどうかはわかりませんが、もしそうなら、単にandroid:textOnまたはandroid:textoff on .xmlと言うことができます。それがJavaの部分にある場合は、おそらくtoggleButton.setCheckedのようなものです。

0

私はあなたが私はちょうどあなたが参照しているかのようなダミーのビューを作成し、私はあなたがあなたの県では、このXMLコードを使用することができます任意の問題

<TableRow 
    android:id="@+id/tableRow1" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" > 

    <TextView 
     android:id="@+id/textView1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Large Text" 
     android:textAppearance="?android:attr/textAppearanceLarge" /> 


    <Switch 
     android:id="@+id/switch1" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="right" 
     android:text="Switch" /> 

</TableRow> 
+0

私が取り組んでいる問題は、私がPreferenceActivityで働いているという事実です。アクティビティではありません。 PreferenceActivityは、各「行」がまたはのようなPreferencetagによってXMLで定義されるように異なって動作します。私の問題は、これら2つの好みを組み合わせることにあります。 tablerowにスイッチとテキストビューを作成するだけではありません。 – CodePrimate

0

が表示されていない、に走った何の問題を確認していませんxmlファイル

<PreferenceCategory> 
     <EditTextPreference 
      android:key="myEditText" 
      android:title="Hi" 
      android:inputType="Mine"></EditTextPreference> 
    </PreferenceCategory> 

、あなたが代わりにこのコードのトグルボタン、チェックボックスを使用することができます。

<CheckBoxPreference 
     android:key="testmode" 
     android:title="@string/test_mode"></CheckBoxPreference> 

場合あなたはこのコードを使用することができ、チェックボックスを使用したくない:

+1

ありがとう、あなたのコードはかなり良いです:-) –

8

先行ジャスト注:これは、長い答えのビットになるだろうが、私の意図は提供することですが文字通りコピー&ペーストして始めることができます。

これは実際に達成するのが難しくありません。あなたの最善の出発点は、ICSのSwichPreferenceの実装を調べることです。あなたはそれがかなりシンプルで、ほとんどの作業はTwoStatePreferenceスーパークラスによって行われていることがわかります。それは順番にICSしか利用できません。幸運にも、文字通りその文字セットをコピーして貼り付けることができます(この解答の最後まで参照してください)。SwitchPreferenceの実装を参考にして、独自のTogglePreferenceを作成してください。

これを行うことで得られることは、以下のようなものです。私はここで私の文章を制限することができるように、各メソッドにいくつかの説明を追加しました。

TogglePreference。Javaの

package mh.so.pref; 

import mh.so.R; 
import android.content.Context; 
import android.preference.Preference; 
import android.util.AttributeSet; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.CompoundButton; 
import android.widget.ToggleButton; 

/** 
* A {@link Preference} that provides a two-state toggleable option. 
* <p> 
* This preference will store a boolean into the SharedPreferences. 
*/ 
public class TogglePreference extends TwoStatePreference { 
    private final Listener mListener = new Listener(); 
    private ExternalListener mExternalListener; 

    /** 
    * Construct a new TogglePreference with the given style options. 
    * 
    * @param context The Context that will style this preference 
    * @param attrs Style attributes that differ from the default 
    * @param defStyle Theme attribute defining the default style options 
    */ 
    public TogglePreference(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    /** 
    * Construct a new TogglePreference with the given style options. 
    * 
    * @param context The Context that will style this preference 
    * @param attrs Style attributes that differ from the default 
    */ 
    public TogglePreference(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    /** 
    * Construct a new TogglePreference with default style options. 
    * 
    * @param context The Context that will style this preference 
    */ 
    public TogglePreference(Context context) { 
     this(context, null); 
    } 

    /** Inflates a custom layout for this preference, taking advantage of views with ids that are already 
    * being used in the Preference base class. 
    */ 
    @Override protected View onCreateView(ViewGroup parent) { 
     LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
     return inflater.inflate(R.layout.toggle_preference_layout, parent, false); 
    } 

    /** Since the Preference base class handles the icon and summary (or summaryOn and summaryOff in TwoStatePreference) 
    * we only need to handle the ToggleButton here. Simply get it from the previously created layout, set the data 
    * against it and hook up a listener to handle user interaction with the button. 
    */ 
    @Override protected void onBindView(View view) { 
     super.onBindView(view); 

     ToggleButton toggleButton = (ToggleButton) view.findViewById(R.id.toggle_togglebutton); 
     toggleButton.setChecked(isChecked()); 
     toggleButton.setOnCheckedChangeListener(mListener); 
    } 

    /** This gets called when the preference (as a whole) is selected by the user. The TwoStatePreference 
    * implementation changes the actual state of this preference, which we don't want, since we're handling 
    * preference clicks with our 'external' listener. Hence, don't call super.onClick(), but the onPreferenceClick 
    * of our listener. */ 
    @Override protected void onClick() { 
     if (mExternalListener != null) mExternalListener.onPreferenceClick(); 
    } 

    /** Simple interface that defines an external listener that can be notified when the preference has been 
    * been clicked. This may be useful e.g. to navigate to a new activity from your PreferenceActivity, or 
    * display a dialog. */ 
    public static interface ExternalListener { 
     void onPreferenceClick(); 
    } 

    /** Sets an external listener for this preference*/ 
    public void setExternalListener(ExternalListener listener) { 
     mExternalListener = listener; 
    } 

    /** Listener to update the boolean flag that gets stored into the Shared Preferences */ 
    private class Listener implements CompoundButton.OnCheckedChangeListener { 
     @Override 
     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
      if (!callChangeListener(isChecked)) { 
       // Listener didn't like it, change it back. 
       // CompoundButton will make sure we don't recurse. 
       buttonView.setChecked(!isChecked); 
       return; 
      } 

      TogglePreference.this.setChecked(isChecked); 
     } 
    } 

} 

この例のレイアウトファイルは、最も興味深いものがToggleButtonことで、単にその中に、3つの要素を持つLinearLayoutです。 ImageViewTextViewは、Android名前空間の適切なIDを使用して、基本クラスが既に行っている作業を利用します。そうすれば、それらについて心配する必要はありません。 Honeycombまでアイコンオプションが追加されていないことは確かですので、カスタム属性としてTogglePreferenceに追加して、手動で設定して常にそこに収まるようにしてください。このアプローチのための具体的なポインタが必要な場合は、私にコメントを書き込んでください。

とにかく、レイアウトを任意の長さに変更して、好みに合わせてスタイリングを適用できます。たとえば、ToggleButtonの模倣をSwitchにするには、背景を別のStateListDrawableに変更したり、オン/オフのテキストを変更したり完全に取り除いたりできます。あなたは、あなたのPreferenceActivityにも他のPreferenceようTogglePreferenceを使用することができます

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="?android:attr/listPreferredItemHeight" > 

    <ImageView 
     android:id="@android:id/icon" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center_vertical" 
     android:focusable="false" 
     android:focusableInTouchMode="false" /> 

    <TextView 
     android:id="@android:id/summary" 
     android:layout_width="0dp" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center_vertical" 
     android:layout_weight="1" 
     android:focusable="false" 
     android:focusableInTouchMode="false" 
     android:textAppearance="?android:attr/textAppearanceMedium" /> 

    <ToggleButton 
     android:id="@+id/toggle_togglebutton" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center_vertical" 
     android:focusable="false" 
     android:focusableInTouchMode="false" /> 

</LinearLayout> 

toggle_preference_layout.xml

。リスナーを接続することで、ユーザーが設定を選択したときに好きなことをすることができます。同時に、実際のToggleButtonをクリックすると、SharedPreferencesのブール値が切り替わります。

DemoPreferenceActivity.java

package mh.so.pref; 

import mh.so.R; 
import android.os.Bundle; 
import android.preference.PreferenceActivity; 
import android.widget.Toast; 

public class DemoPreferenceActivity extends PreferenceActivity { 

    @Override protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     addPreferencesFromResource(R.xml.prefs); 

     TogglePreference toggle = (TogglePreference) findPreference("toggle_preference"); 
     toggle.setExternalListener(new TogglePreference.ExternalListener() { 
      @Override public void onPreferenceClick() { 
       Toast.makeText(DemoPreferenceActivity.this, "You clicked the preference without changing its value", Toast.LENGTH_LONG).show(); 
      } 
     }); 
    } 

} 

Prefs.xmlは、より多くの何もなく、TogglePreference上記の単一の定義はありません。あなたはAndroidのネームスペース内のすべての通常の属性を提供することができます。オプションで、TwoStatePreferenceの組み込み機能を利用してsummaryOnsummaryOffのテキストを扱うカスタム属性を宣言することもできます。

Prefs.xml

<?xml version="1.0" encoding="utf-8"?> 
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > 

    <PreferenceCategory android:title="Toggle preferences" > 
     <mh.so.pref.TogglePreference xmlns:app="http://schemas.android.com/apk/res/mh.so" 
      android:key="toggle_preference" 
      android:summary="Summary" 
      android:icon="@drawable/icon" /> 
    </PreferenceCategory> 

</PreferenceScreen> 

最後に、ICSからのバックポートTwoStatePreferenceクラス。元のソースとほとんど変わりません。ソースはoverhereです。

package mh.so.pref; 

import android.content.Context; 
import android.content.SharedPreferences; 
import android.content.res.TypedArray; 
import android.os.Parcel; 
import android.os.Parcelable; 
import android.preference.Preference; 
import android.util.AttributeSet; 
import android.view.View; 
import android.widget.TextView; 

/** 
* Common base class for preferences that have two selectable states, persist a 
* boolean value in SharedPreferences, and may have dependent preferences that are 
* enabled/disabled based on the current state. 
*/ 
public abstract class TwoStatePreference extends Preference { 

    private CharSequence mSummaryOn; 
    private CharSequence mSummaryOff; 
    private boolean mChecked; 
    private boolean mDisableDependentsState; 


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

    public TwoStatePreference(Context context, AttributeSet attrs) { 
     this(context, attrs, 0); 
    } 

    public TwoStatePreference(Context context) { 
     this(context, null); 
    } 

    @Override 
    protected void onClick() { 
     super.onClick(); 

     boolean newValue = !isChecked(); 

     if (!callChangeListener(newValue)) { 
      return; 
     } 

     setChecked(newValue); 
    } 

    /** 
    * Sets the checked state and saves it to the {@link SharedPreferences}. 
    * 
    * @param checked The checked state. 
    */ 
    public void setChecked(boolean checked) { 
     if (mChecked != checked) { 
      mChecked = checked; 
      persistBoolean(checked); 
      notifyDependencyChange(shouldDisableDependents()); 
      notifyChanged(); 
     } 
    } 

    /** 
    * Returns the checked state. 
    * 
    * @return The checked state. 
    */ 
    public boolean isChecked() { 
     return mChecked; 
    } 

    @Override 
    public boolean shouldDisableDependents() { 
     boolean shouldDisable = mDisableDependentsState ? mChecked : !mChecked; 
     return shouldDisable || super.shouldDisableDependents(); 
    } 

    /** 
    * Sets the summary to be shown when checked. 
    * 
    * @param summary The summary to be shown when checked. 
    */ 
    public void setSummaryOn(CharSequence summary) { 
     mSummaryOn = summary; 
     if (isChecked()) { 
      notifyChanged(); 
     } 
    } 

    /** 
    * @see #setSummaryOn(CharSequence) 
    * @param summaryResId The summary as a resource. 
    */ 
    public void setSummaryOn(int summaryResId) { 
     setSummaryOn(getContext().getString(summaryResId)); 
    } 

    /** 
    * Returns the summary to be shown when checked. 
    * @return The summary. 
    */ 
    public CharSequence getSummaryOn() { 
     return mSummaryOn; 
    } 

    /** 
    * Sets the summary to be shown when unchecked. 
    * 
    * @param summary The summary to be shown when unchecked. 
    */ 
    public void setSummaryOff(CharSequence summary) { 
     mSummaryOff = summary; 
     if (!isChecked()) { 
      notifyChanged(); 
     } 
    } 

    /** 
    * @see #setSummaryOff(CharSequence) 
    * @param summaryResId The summary as a resource. 
    */ 
    public void setSummaryOff(int summaryResId) { 
     setSummaryOff(getContext().getString(summaryResId)); 
    } 

    /** 
    * Returns the summary to be shown when unchecked. 
    * @return The summary. 
    */ 
    public CharSequence getSummaryOff() { 
     return mSummaryOff; 
    } 

    /** 
    * Returns whether dependents are disabled when this preference is on ({@code true}) 
    * or when this preference is off ({@code false}). 
    * 
    * @return Whether dependents are disabled when this preference is on ({@code true}) 
    *   or when this preference is off ({@code false}). 
    */ 
    public boolean getDisableDependentsState() { 
     return mDisableDependentsState; 
    } 

    /** 
    * Sets whether dependents are disabled when this preference is on ({@code true}) 
    * or when this preference is off ({@code false}). 
    * 
    * @param disableDependentsState The preference state that should disable dependents. 
    */ 
    public void setDisableDependentsState(boolean disableDependentsState) { 
     mDisableDependentsState = disableDependentsState; 
    } 

    @Override 
    protected Object onGetDefaultValue(TypedArray a, int index) { 
     return a.getBoolean(index, false); 
    } 

    @Override 
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { 
     setChecked(restoreValue ? getPersistedBoolean(mChecked) 
       : (Boolean) defaultValue); 
    } 

    /** 
    * Sync a summary view contained within view's subhierarchy with the correct summary text. 
    * @param view View where a summary should be located 
    */ 
    void syncSummaryView(View view) { 
     // Sync the summary view 
     TextView summaryView = (TextView) view.findViewById(android.R.id.summary); 
     if (summaryView != null) { 
      boolean useDefaultSummary = true; 
      if (mChecked && mSummaryOn != null) { 
       summaryView.setText(mSummaryOn); 
       useDefaultSummary = false; 
      } else if (!mChecked && mSummaryOff != null) { 
       summaryView.setText(mSummaryOff); 
       useDefaultSummary = false; 
      } 

      if (useDefaultSummary) { 
       final CharSequence summary = getSummary(); 
       if (summary != null) { 
        summaryView.setText(summary); 
        useDefaultSummary = false; 
       } 
      } 

      int newVisibility = View.GONE; 
      if (!useDefaultSummary) { 
       // Someone has written to it 
       newVisibility = View.VISIBLE; 
      } 
      if (newVisibility != summaryView.getVisibility()) { 
       summaryView.setVisibility(newVisibility); 
      } 
     } 
    } 

    @Override 
    protected Parcelable onSaveInstanceState() { 
     final Parcelable superState = super.onSaveInstanceState(); 
     if (isPersistent()) { 
      // No need to save instance state since it's persistent 
      return superState; 
     } 

     final SavedState myState = new SavedState(superState); 
     myState.checked = isChecked(); 
     return myState; 
    } 

    @Override 
    protected void onRestoreInstanceState(Parcelable state) { 
     if (state == null || !state.getClass().equals(SavedState.class)) { 
      // Didn't save state for us in onSaveInstanceState 
      super.onRestoreInstanceState(state); 
      return; 
     } 

     SavedState myState = (SavedState) state; 
     super.onRestoreInstanceState(myState.getSuperState()); 
     setChecked(myState.checked); 
    } 

    static class SavedState extends BaseSavedState { 
     boolean checked; 

     public SavedState(Parcel source) { 
      super(source); 
      checked = source.readInt() == 1; 
     } 

     @Override 
     public void writeToParcel(Parcel dest, int flags) { 
      super.writeToParcel(dest, flags); 
      dest.writeInt(checked ? 1 : 0); 
     } 

     public SavedState(Parcelable superState) { 
      super(superState); 
     } 

     public static final Parcelable.Creator<SavedState> CREATOR = 
       new Parcelable.Creator<SavedState>() { 
      public SavedState createFromParcel(Parcel in) { 
       return new SavedState(in); 
      } 

      public SavedState[] newArray(int size) { 
       return new SavedState[size]; 
      } 
     }; 
    } 
} 

TogglePreference without any fancy styling applied

0

単にあなたがこのスレッドを開始したと思います。この(私のアプリからちょうどサンプル、他のprefsについて悩むいけない) enter image description here

関連する問題