我給這一個嘗試,有點掙扎。我想我會分享我的經驗。
起初我試了XGouchet的答案,因爲它的票數最多。該解決方案相當複雜,需要使用preference headers這是非常酷,但不適合我在做什麼。我決定最簡單的做法是將我的preferenceFragment包裝在一個普通的片段中,然後用常規的視圖僞裝switch preference。我挖了Android源的偏好以及與此
<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's solution是好的和簡單,但沒有奏效當我嘗試。我第二次嘗試確保我沒有犯錯。我一直玩耍,想出了一些似乎可行的東西。他有一個好點
2個問題在這裏:1.如何聽取偏好點擊 開關區域之外? 2.如何在操作欄中放置一個開關?
真的只是時間問題(1)是值得回答,因爲問題2已經回答了here和other places
我意識到以訪問的偏好的意見,唯一的辦法就是創建一個子類,並覆蓋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
}
});
希望這第二黑客不會回來咬我。
任何人都可以看到這種方法的任何潛在缺陷?
我也把代碼輕微改進版在github https://gist.github.com/marchold/45e22839eb94aa14dfb5
你的XML怎麼樣子? – Jokahero 2012-04-19 12:11:39
我已更新我的問題。 – Zul 2012-04-19 12:26:23
您是否找到了更快捷的替代方案?只是爲了確定用戶何時點擊複選框? – MatheusJardimB 2014-02-03 16:50:57