如何使用EditTextPreference和Togglebutton创建一个Preference?

时间:2012-03-16 14:02:08

标签: android preferences togglebutton preferenceactivity

我正在尝试实现的是下面图像的基本和精确的复制品(我已经平方的偏好)。按下首选项左侧的任何内容都应该打开一个对话框。按下togglebutton将禁用/启用我在此首选项中设置的任何内容。

我一直在努力工作几个小时,而且我空手而归。如何在PreferenceActivity中实现它?

Preference

编辑:似乎人们误解了我的问题。我弄清楚如何使用PreferenceActivity解决我的问题非常重要。不是活动。我不在乎我是需要用XML还是以编程方式来做。请不要向我提供我不能在类似内容中使用的答案。

编辑2:增加了赏金 - 我真的需要一个答案

6 个答案:

答案 0 :(得分:17)

天哪,我喜欢你的想法: - )

这与@ MH的答案相同,但更简洁。

我使用ToggleButton进行了测试,而不是Switch

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)。

答案 1 :(得分:9)

前言只是一个注意事项:这将是一个很长的答案,但我的目的是为您提供一个易于理解的答案,您可以直接复制并粘贴以开始使用。

这实际上并不难实现。您最好的出发点是在ICS上查找SwichPreference的实现。你会发现它非常简单,大多数工作都是由一个TwoStatePreference超类完成的,而这个超类也只是可用的ICS。幸运的是,你几乎可以复制粘贴(在这个答案中一直看到)该类并构建你自己的TogglePreference(为了清楚起见,我们称之为),使用{{ 1}}实施指南。

通过这样做你会得到什么,如下所示。我为每种方法添加了一些解释,以便我可以限制我的写作。

<强> TogglePreference.java

SwitchPreference

此示例的布局文件只是一个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); } } } ,其中包含三个元素,其中最有趣的一个是LinearLayoutToggleButtonImageView通过在Android命名空间中使用适当的ID来利用TextView基类已经完成的工作。这样,我们不必担心这些。请注意,我非常确定在Honeycomb之前没有添加图标选项,因此您可能只想将其作为自定义属性添加到Preference并手动设置它以便它始终存在。如果你需要更具体的指针来解决这个问题,请点击我的评论。

无论如何,显然你可以在任何范围内修改布局,并根据自己的喜好应用样式。例如,要让TogglePreference模仿ToggleButton,您可以将背景更改为其他Switch和/或更改或完全删除开/关文本。

<强> toggle_preference_layout.xml

StateListDrawable

然后,您可以像<?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> 中的任何其他TogglePreference一样使用Preference。通过连接监听器,您可以在用户选择首选项时执行任何操作,同时单击实际PreferenceActivity将切换ToggleButton中的布尔值。

<强> DemoPreferenceActivity.java

SharedPreferences

Prefs.xml仅仅是上述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(); } }); } } 的单一定义。您可以在Android的命名空间中提供所有常用属性。或者,您也可以声明一些自定义属性,以利用TogglePreference的内置功能来处理TwoStatePreferencesummaryOn文本。

<强>的prefs.xml

summaryOff

最后,来自ICS的反向移植的TwoStatePreference类。它与原始版本几乎没有任何不同,您可以找到源overhere

<?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>

TogglePreference without any fancy styling applied

答案 2 :(得分:0)

不确定这是否是切换按钮,但如果是,你可以在.xml上说android:textOn或android:textoff。如果它在java部分,它可能就像setTextOnNot肯定,如果这是一个切换按钮,但如果它是你可以只说android:textOn或android:textoff on .xml。如果它在java部分,它可能就像toggleButton.setChecked。

答案 3 :(得分:0)

我不确定你遇到了什么问题,我只是创建了一个虚拟视图,就像你所指的那样,我没有看到任何问题

<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>

答案 4 :(得分:0)

您可以在pref xml文件中使用此xml代码

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

您可以使用复选框来改为使用此代码togglebutton:

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

如果您不想使用复选框,可以使用以下代码:

答案 5 :(得分:0)

只需使用SwitchPreference

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

看起来像这样(只是我的应用程序中的一个示例,不用担心其他prefs) enter image description here