2012-04-19 42 views
8

Làm cách nào để đặt điều hướng cài đặt cho SwitchReference như ứng dụng cài đặt gốc của Android?android: Cách tạo điều hướng cài đặt như ứng dụng cài đặt gốc

đâu khi u bấm vào khu vực WiFi (không phải trên switch) nó sẽ hướng đến một màn hình mới:

Click on WiFi

Ứng dụng của tôi chỉ thay đổi chuyển từ ON OFF và ngược lại ngay cả khi tôi không nhấp vào nút chuyển.

Tôi đang sử dụng PreferenceFragment và xml cho màn hình. Và sở thích của tôi là làm theo ví dụ từ Android PreferenceFragment documentation. Tôi phát triển ứng dụng của mình trên API ICS 4.0 14.

Bất kỳ ai biết cách thực hiện việc này?

được sửa đổi:

tôi nhìn XML như thế này:

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

Làm thế nào xml của bạn trông như thế nào? – Jokahero

+0

Tôi đã cập nhật câu hỏi của mình. – Zul

+0

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

Trả lời

5

Bằng cách nhìn vào nguồn gốc của ứng dụng Settings chứng khoán, bạn có thể tìm thấy cách họ đã làm điều đó.

Về cơ bản, họ sử dụng một ArrayAdapter tùy chỉnh (giống như bạn sẽ làm với một ListView) để hiển thị các hàng có nút Switch. Và đối với màn hình thứ hai, họ chỉ cần sử dụng CustomView có sẵn trong ActionBar.

Tôi đã viết an article with a sample code để cho biết cách bạn có thể làm điều đó trong dự án của mình. Tuy nhiên, hãy cẩn thận, điều này chỉ có thể ẩn trong API cấp 14 trở lên, vì vậy nếu bạn nhắm mục tiêu các thiết bị cũ hơn, hãy giữ màn hình tùy chọn kiểu cũ.

+0

Công việc hay. Điều đó thực sự đã giúp tôi rất nhiều. Cảm ơn Xavier. :) – Zul

+0

Rất đẹp. Có nói rằng nó là vô lý có nhiều bạn phải mã cho một màn hình Preference đơn giản và làm cho nó hoạt động cho cũ, mới và máy tính bảng. Một trong những chỉ cần phải khai báo nó trong một tập tin xml và nó NÊN làm việc ở khắp mọi nơi. Giai đoạn! – powder366

+0

Giải pháp này có vẻ quá lớn đối với một vấn đề nhỏ như vậy.Có cách nào khác để xác định thời điểm người dùng nhấp vào hộp kiểm hoặc trong vùng văn bản không? – MatheusJardimB

1

Tôi thấy 2 câu hỏi ở đây: 1. Cách nghe tùy chọn nhấp bên ngoài vùng chuyển đổi? 2. Làm thế nào để đặt một công tắc trong thanh hành động?

Tôi sẽ trả lời câu hỏi 1:

Tôi tạo ra một lớp mới SwitchPreference và overrode các onClick phương pháp để làm gì cả. Điều này ngăn thay đổi cài đặt khi nhấp vào bên ngoài nút gạt.

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

sử dụng (xml):

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

sử dụng (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; 
    } 
}); 
+0

Tôi thích câu trả lời đơn giản của nó như thế nào, nhưng khi tôi thử mã này, nhánh "Clicked inside switch and setting changed" không được lấy ngay cả khi tôi nhấp vào phần chuyển đổi. – Marc

+0

Không hoạt động trên lollipuk. –

1

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

Các vấn đề liên quan