Tôi đưa cái này thử và vất vả một chút. Tôi nghĩ tôi sẽ chia sẻ kinh nghiệm của mình.
Lúc đầu, tôi đã thử câu trả lời bằng XGouchet vì nó có số phiếu bầu cao nhất. Giải pháp khá phức tạp và yêu cầu sử dụng preference headers rất tuyệt nhưng không phù hợp với những gì tôi đang làm. Tôi quyết định điều đơn giản nhất để tôi làm là kết thúc sở thích của mình trong một đoạn thông thường và giả mạo tùy chọn chuyển đổi với chế độ xem thông thường.Tôi đào lên nguồn android cho một sở thích và đến với điều này
<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>
Các FrameLayout ở đầu được một đoạn ưu tiên như vậy
getChildFragmentManager()
.beginTransaction()
.replace(R.id.fragment_container, new SettingsPreferencesFragment(), "SettingsPreferencesFragment")
.commit();
Sau đó, tôi có thể nhận được gán nghe nhấp chuột của tôi như là tôi sẽ trong bất kỳ chế độ xem thông thường nào. SettingsPreferencesFragment chỉ là phân đoạn ưu tiên hoàn toàn tiêu chuẩn.
Giải pháp này có vẻ khá tốt, nhưng sau đó tôi nhận thấy các vấn đề bố cục lạ trên máy tính bảng. Tôi nhận ra rằng tôi sẽ gặp khó khăn khi nhận được giải pháp này để nhìn ngay trên tất cả các thiết bị và tôi cần phải sử dụng một switchPreference thực sự không phải là một giả mạo.
============== Giải pháp 2 ===============
AlikElzin-kilaka's solution là tốt đẹp và đơn giản nhưng không làm việc khi tôi thử. Tôi đã thử lần thứ 2 để chắc chắn rằng tôi đã không làm sai. Tôi tiếp tục chơi đùa và nghĩ ra thứ gì đó có vẻ hiệu quả. Anh ấy có một điểm tốt về
2 câu hỏi ở đây: 1. Cách nghe tùy chọn nhấp bên ngoài khu vực chuyển đổi ? 2. Làm thế nào để đặt một công tắc trong thanh hành động?
Thật chỉ hỏi (1) là giá trị trả lời vì câu hỏi 2 đã được trả lời here và other places
tôi nhận ra con đường duy nhất để có được quyền truy cập vào các quan điểm trong một sở thích là để tạo ra một lớp trẻ và override onBind. Vì vậy, tôi đã đưa ra lớp con này của SwitchPreference tạo trình xử lý nhấp chuột riêng biệt cho nút chuyển làm toàn bộ chế độ xem. Nó vẫn là một hack mặc dù.
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();
}
});
}
}
Sử dụng hàm đệ quy findSwitchWidget để đi bộ cho đến khi tìm thấy nút chuyển. Tôi muốn viết mã như thế này:
Switch switchView = view.findViewById(android.R.id.switchView);
nhưng dường như không có cách nào để đạt được giá trị id nội bộ mà tôi biết. Nhưng dù sao khi chúng tôi có công tắc thực tế, chúng tôi có thể chỉ định người nghe cho nó và chế độ xem vùng chứa. Tùy chọn chuyển đổi sẽ không tự động cập nhật, do đó, tùy chọn cần thiết để tự lưu tùy chọn.
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
}
});
Hy vọng lần hack thứ hai này sẽ không trở lại để cắn tôi.
Có ai thấy bất kỳ cạm bẫy tiềm ẩn nào của phương pháp này không?
Tôi cũng đặt một phiên bản cải tiến nhỏ của mã trên github https://gist.github.com/marchold/45e22839eb94aa14dfb5
Làm thế nào xml của bạn trông như thế nào? – Jokahero
Tôi đã cập nhật câu hỏi của mình. – Zul
Bạn đã tìm thấy phương án thay thế nhanh hơn chưa? Chỉ cần xác định thời điểm người dùng nhấp vào hộp kiểm hay không? – MatheusJardimB