8

SwitchReference の設定ナビゲーションを Android ネイティブ設定アプリのようにするにはどうすればよいですか?

WiFi リージョン (スイッチではなく) をクリックすると、新しい画面に移動します。

Wi-Fiをクリック

私のアプリは、スイッチをクリックしていないときでも、スイッチをオンからオフに、またはその逆にのみ変更します。

PreferenceFragment画面にxmlを使用しています。そして、私の好みはAndroid PreferenceFragment documentationの例に従っています。ICS 4.0 API 14 でアプリを開発しています。

誰でもこれを行う方法を知っていますか?

編集:

私のXMLは次のようになります。

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >

    <PreferenceCategory
        android:layout="@layout/preference_category"
        android:title="User Settings" >
        <SwitchPreference
            android:key="pref_autorun"
            android:layout="@layout/preference"
            android:summary="Autorun SMODE on boot"
            android:title="Autorun SMODE" />
        <SwitchPreference
            android:key="pref_wifi_control"
            android:layout="@layout/preference"
            android:selectable="false"
            android:summary="Controls your Wi-Fi radio automatically based on hotspot availability"
            android:title="Wi-Fi Radio Control" />
    </PreferenceCategory>
</PreferenceScreen> 
4

3 に答える 3

5

株式設定アプリのソースを見ると、彼らがどのようにそれを行ったかを知ることができます。

基本的に、カスタムArrayAdapterを使用して(ListViewで行うのと同じように)、スイッチボタンで行を表示します。また、2番目の画面では、ActionBarで使用可能なCustomViewを使用するだけです。

プロジェクトでそれを行う方法を示すために、サンプルコードを使用して記事を作成しました。ただし、これはAPIレベル14以上でのみ機能する可能性があるため、古いデバイスをターゲットにする場合は、古いスタイルの設定画面を維持するように注意してください。

于 2012-06-27T05:40:12.407 に答える
1

私はこれを試してみて、少し苦労しました。私の経験を共有したいと思いました。

最初は、XGouchetの回答が最も多かったので試してみました。ソリューションはかなり複雑で、非常にクールな設定ヘッダーを使用する必要がありましたが、私がやっていることには合いませんでした。最も簡単な方法は、preferenceFragment を通常のフラグメントにラップし、通常のビューでスイッチ設定を偽造することだと判断しました。私は好みのためにアンドロイドソースを掘り起こし、これを思いついた

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.lezyne.link.ui.homeScreen.settingsTab.SettingsFragment">

<FrameLayout
    android:id="@+id/fragment_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal">


</FrameLayout>

<View
    android:layout_width="fill_parent"
    android:layout_height="1dp"
    android:layout_marginLeft="15dp"
    android:layout_marginRight="15dp"
    android:background="#e1e1e1" />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?android:attr/selectableItemBackground"
    android:gravity="center_vertical"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:orientation="horizontal"
    android:paddingRight="?android:attr/scrollbarSize">

    <ImageView
        android:id="@+id/icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="6dip"
        android:layout_marginLeft="15dip"
        android:layout_marginRight="6dip"
        android:layout_marginTop="6dip"
        android:layout_weight="1">

        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ellipsize="marquee"
            android:fadingEdge="horizontal"
            android:singleLine="true"
            android:textAppearance="?android:attr/textAppearanceLarge" />

        <TextView
            android:id="@+id/summary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignLeft="@android:id/title"
            android:layout_below="@android:id/title"
            android:maxLines="4"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:textColor="?android:attr/textColorSecondary" />

    </RelativeLayout>

    <!-- Preference should place its actual preference widget here. -->
    <RelativeLayout
        android:id="@+id/widget_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:orientation="vertical"
        android:paddingEnd="36dp">


        <Switch
            android:thumb="@drawable/switch_inner"
            android:id="@+id/switch1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true" />

        <TextView
            android:id="@+id/textView6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="2dp"
            android:text="@string/Notifications"
            android:textAppearance="?android:attr/textAppearanceMedium" />

    </RelativeLayout>

</LinearLayout>


<View
    android:layout_width="fill_parent"
    android:layout_height="1dp"
    android:layout_marginLeft="15dp"
    android:layout_marginRight="15dp"
    android:background="#e1e1e1" />


 </LinearLayout>

上部の FrameLayout は、次のような設定フラグメントを取得します

    getChildFragmentManager()
            .beginTransaction()
            .replace(R.id.fragment_container, new SettingsPreferencesFragment(), "SettingsPreferencesFragment")
            .commit();

次に、通常のビューと同じように、クリック リスナーを割り当てることができます。SettingsPreferencesFragment は、完全に標準的な設定フラグメントです。

この解決策はかなり良さそうに見えましたが、タブレットで奇妙なレイアウトの問題があることに気付きました。このソリューションをすべてのデバイスで正しく表示するには問題があり、偽物ではなく本物の switchPreference を使用する必要があることに気付きました。

============== 解決策 2 ===============

AlikElzin-kilaka のソリューションは素晴らしくシンプルでしたが、試してみるとうまくいきませんでした。間違ったことをしていないことを確認するために、もう一度やり直しました。私は遊んで続け、うまくいくと思われるものを思いつきました。彼には良い点がある

ここに 2 つの質問があります: 1. スイッチ領域の外側で設定クリックを聞く方法は? 2. アクションバーにスイッチを入れるには?

質問 2 はここ他の場所で回答されているため、本当に質問 (1) だけが答える価値があります。

設定でビューにアクセスする唯一の方法は、子クラスを作成してonBindをオーバーライドすることだと気付きました。そこで、ビュー全体としてスイッチの個別のクリック ハンドラーを作成する、この SwitchPreference の子クラスを考え出しました。それでもハックです。

public class MySwitchPreference extends SwitchPreference {
public MySwitchPreference(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}


public MySwitchPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
    getView(null,null);

}

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

public interface SwitchClickListener{
    public void onSwitchClicked(boolean checked);
    public void onPreferenceClicked();
}
private SwitchClickListener listener = null;
public void setSwitchClickListener(SwitchClickListener listener){
    this.listener = listener;
}

public Switch findSwitchWidget(View view){
    if (view instanceof  Switch){
        return (Switch)view;
    }
    if (view instanceof ViewGroup){
        ViewGroup viewGroup = (ViewGroup)view;
        for (int i = 0; i < viewGroup.getChildCount();i++){
            View child = viewGroup.getChildAt(i);
            if (child instanceof ViewGroup){
                Switch result = findSwitchWidget(child);
                if (result!=null) return result;
            }
            if (child instanceof Switch){
                return (Switch)child;
            }
        }
    }
    return null;
}

protected void onBindView (View view){
    super.onBindView(view);

    final Switch switchView = findSwitchWidget(view);
    if (switchView!=null){
        switchView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (listener!=null) listener.onSwitchClicked(switchView.isChecked());
            }
        });
        switchView.setFocusable(true);
        switchView.setEnabled(true);
    }

    view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (listener!=null) listener.onPreferenceClicked();
        }
    });

}
} 

再帰関数 findSwitchWidget を使用して、Switch が見つかるまでツリーをたどります。私はむしろ次のようなコードを書きたいと思います:

Switch switchView = view.findViewById(android.R.id.switchView);

しかし、私が知っている内部ID値に到達する方法はないようです。とにかく、実際のスイッチを取得したら、それとコンテナ ビューにリスナーを割り当てることができます。スイッチ設定は自動的に更新されないため、自分で設定を保存する必要があります。

MySwitchPreference switchPreference = (MySwitchPreference) findPreference("whatever");
    switchPreference.setSwitchClickListener(new MySwitchPreference.SwitchClickListener() {
        @Override
        public void onSwitchClicked(boolean checked) {
            //Save the preference value here 
        }

        @Override
        public void onPreferenceClicked() {
            //Launch the new preference screen or activity here
        }
    });

うまくいけば、この 2 番目のハックが戻ってきて私を噛まないことを願っています。

この方法の潜在的な落とし穴を見た人はいますか?

また、わずかに改善されたバージョンのコードを github https://gist.github.com/marchold/45e22839eb94aa14dfb5に置きました。

于 2015-01-11T18:25:08.080 に答える
1

ここに 2 つの質問があります。2. アクションバーにスイッチを入れるには?

質問 1 にお答えします。

新しいSwitchPreferenceクラスを作成し、onClick何もしないようにメソッドをオーバーライドしました。これにより、スイッチの外側をクリックしても設定が変更されなくなります。

public class SwitchPreference extends android.preference.SwitchPreference {
    @Override
    protected void onClick() {
    }
}

使用法 (xml):

<android.util.SwitchPreference
    android:key="whatever"
    android:title="Whatever" />

使用法 (Java):

SwitchPreference switchPreference = (SwitchPreference) findPreference("whatever");
switchPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        DialogUtils.showToast(Preferences.this, "Clicked outside switch");
        return true;
    }
});
switchPreference.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        DialogUtils.showToast(Preferences.this, "Clicked inside switch and setting changed");
        return true;
    }
});
于 2014-06-30T10:04:06.227 に答える