2012-04-19 18 views
8

Come faccio a rendere le impostazioni di navigazione per SwitchReference come app impostazioni native Android?android: come rendere le impostazioni di navigazione come l'app delle impostazioni native

Dove quando u fare clic sulla regione di connessione Wi-Fi (non sull'interruttore) sarà passare a una nuova schermata:

Click on WiFi

mia app modificare solo il passaggio da ON a OFF e viceversa anche quando ho Non sto facendo clic sull'interruttore.

Sto usando PreferenceFragment e xml per lo schermo. E la mia preferenza è seguire l'esempio da Android PreferenceFragment documentation. Sviluppo la mia app su ICS 4.0 API 14.

Qualcuno sa come fare?

Modificato:

mio aspetto XML come questo:

<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

Come il tuo XML assomiglia? – Jokahero

+0

Ho aggiornato la mia domanda. – Zul

+0

Hai trovato un'alternativa più rapida? Solo per determinare quando l'utente ha fatto clic sulla casella di controllo o no? – MatheusJardimB

risposta

5

Dando un'occhiata alla fonte della app Impostazioni azionari, si possono trovare come hanno fatto.

In pratica, utilizzano un ArrayAdapter personalizzato (proprio come si farebbe con un ListView) per visualizzare le righe con i pulsanti Switch. E per il secondo schermo, usano semplicemente CustomView disponibile in ActionBar.

Ho scritto an article with a sample code per mostrare come è possibile farlo nel progetto. Fai attenzione però, questo può solo eseguire il wirk in API Livello 14 o versioni successive, quindi se scegli come target i dispositivi più vecchi, mantieni uno schermo di preferenze stile precedente.

+0

Bel lavoro. Questo mi ha davvero aiutato molto. Grazie Xavier. :) – Zul

+0

Bello. Detto questo, è ridicolo avere molto codice per una semplice schermata delle preferenze e per farlo funzionare per vecchi, nuovi e tablet. Uno dovrebbe solo dichiararlo in un file xml e DOVREBBE funzionare ovunque. Periodo! – powder366

+0

Questa soluzione sembra troppo grande per un problema così piccolo.C'è qualche alternativa per determinare quando l'utente ha fatto clic sulla casella di controllo o nell'area di testo? – MatheusJardimB

1

Vedo 2 domande qui: 1. Come ascoltare la preferenza fai clic all'esterno dell'area switch? 2. Come inserire un interruttore nella barra delle azioni?

Risponderò domanda 1:

ho creato un nuovo SwitchPreference classe ed escludeva il metodo onClick di non fare nulla. Ciò impedisce la modifica delle impostazioni quando si fa clic all'esterno dell'interruttore.

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

Usage (xml):

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

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

Mi piace come sia una bella risposta semplice, ma quando ho provato questo codice il ramo "Passato dall'interruttore e dall'impostazione modificata" non è stato preso anche se clicco sulla parte dello switch. – Marc

+0

Non funziona su lollipuk. –

1

ho dato questa una prova e faticato un po '. Ho pensato di condividere la mia esperienza.

All'inizio ho provato la risposta con XGouchet poiché aveva ottenuto i voti migliori. La soluzione era abbastanza complicata e richiesta usando preference headers che sono molto interessanti ma non si adattavano a quello che stavo facendo. Ho deciso che la cosa più facile da fare per me è quella di racchiudere la mia preferenza Frammento in un frammento regolare e rendere falsa la preferenza dell'interruttore con una vista normale.Ho scavato fino alla sorgente di Android per una preferenza e si avvicinò con questo

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

Il FrameLayout in alto ottiene un frammento di preferenza in questo modo

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

Poi posso ottenere assegnare i miei click ascoltatori come vorrei in qualsiasi vista normale. SettingsPreferencesFragment è un frammento di preferenza completamente standard.

Questa soluzione sembrava abbastanza buona, ma poi ho notato strani problemi di layout sui tablet. Mi sono reso conto che avrei avuto problemi a trovare questa soluzione in modo corretto su tutti i dispositivi e avevo bisogno di usare un vero switchPreference non falso.

============== Soluzione 2 ===============

AlikElzin-kilaka's solution era bello e semplice, ma non ha funzionato quando ci ho provato Ho provato una seconda volta per assicurarmi di non averlo sbagliato. Ho continuato a giocare e mi è venuto in mente qualcosa che sembra funzionare. Ha una buona opinione su

2 domande qui: 1. Come ascoltare la preferenza clicca all'esterno dell'area di commutazione ? 2. Come inserire un interruttore nella barra delle azioni?

Davvero unica questione (1) vale la pena di rispondere, perché la domanda 2 è stato risposto here e other places

ho capito l'unico modo per ottenere l'accesso alle viste di una preferenza era quella di creare una classe figlia e di override onBind. Così mi è venuta in mente questa classe figlia di SwitchPreference che crea gestori di clic separati per lo switch come l'intera vista. Comunque è ancora un hack.

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(); 
     } 
    }); 

} 
} 

Utilizza la funzione ricorsiva findSwitchWidget per percorrere l'albero finché non trova un interruttore. Avrei preferito scrivere codice come questo:

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

, ma non sembra essere un modo per arrivare a quel valore ID interno, che io sappia. In ogni caso, una volta ottenuto il passaggio effettivo, possiamo assegnare gli ascoltatori e la vista del contenitore. La preferenza dello switch non si aggiornerà automaticamente, quindi è necessario salvarla autonomamente.

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 
     } 
    }); 

Speriamo che questa seconda modifica non ritorni a mordermi.

Qualcuno vede qualche potenziale insidia di questo metodo?

ho anche messo una versione leggermente migliorata del codice su GitHub https://gist.github.com/marchold/45e22839eb94aa14dfb5

Problemi correlati