gladman
gladman

Reputation: 1266

How to start a fragment when preference clicked

I want start a fragment on clicking a preference item. Refer below:

   <PreferenceSreen
        android:key="zd_pref"
        android:summary="@string/zd_summary_no"
        android:title="@string/zd_platform" >
        <intent
            android:action="com.example.prefs.PREFS_ONE"
            android:targetClass="com.android.settings.bussiness.AuthCertifyConfirm"
            android:targetPackage="com.example.settings" />
    </PreferenceSreen>
    <PreferenceSreen
        android:key="hw_pref"
        android:summary="@string/hw_summary"
        android:title="@string/hw_platform" >
        <intent
            android:action="com.example.prefs.PREFS_ONE"
            android:targetClass="com.android.settings.bussiness.AuthCertifyConfirm"
            android:targetPackage="com.example.settings" />
    </PreferenceSreen>

The AuthCertifyConfirm is a fragment,

public class AuthCertifyConfirm extends Fragment {}

BUT, this method caused error, when click the preference. The errors:

E/AndroidRuntime(28027): FATAL EXCEPTION: main
E/AndroidRuntime(28027): android.view.InflateException: Binary XML file line #21: Error inflating class PreferenceSreen
E/AndroidRuntime(28027):    at android.preference.GenericInflater.createItemFromTag(GenericInflater.java:441)
E/AndroidRuntime(28027):    at android.preference.GenericInflater.rInflate(GenericInflater.java:481)
E/AndroidRuntime(28027):    at android.preference.GenericInflater.inflate(GenericInflater.java:326)
E/AndroidRuntime(28027):    at android.preference.GenericInflater.inflate(GenericInflater.java:263)
E/AndroidRuntime(28027):    at android.preference.PreferenceManager.inflateFromResource(PreferenceManager.java:269)
E/AndroidRuntime(28027):    at android.preference.PreferenceFragment.addPreferencesFromResource(PreferenceFragment.java:285)
E/AndroidRuntime(28027):    at com.android.settings.bussiness.BussinessSettings.onCreate(BussinessSettings.java:78)
E/AndroidRuntime(28027):    at android.app.Fragment.performCreate(Fragment.java:1673)
E/AndroidRuntime(28027):    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:854)
E/AndroidRuntime(28027):    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1057)
E/AndroidRuntime(28027):    at android.app.BackStackRecord.run(BackStackRecord.java:682)
E/AndroidRuntime(28027):    at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1435)
E/AndroidRuntime(28027):    at android.app.FragmentManagerImpl$1.run(FragmentManager.java:441)
E/AndroidRuntime(28027):    at android.os.Handler.handleCallback(Handler.java:725)
E/AndroidRuntime(28027):    at android.os.Handler.dispatchMessage(Handler.java:92)
E/AndroidRuntime(28027):    at android.os.Looper.loop(Looper.java:137)
E/AndroidRuntime(28027):    at android.app.ActivityThread.main(ActivityThread.java:5041)
E/AndroidRuntime(28027):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(28027):    at java.lang.reflect.Method.invoke(Method.java:511)
E/AndroidRuntime(28027):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
E/AndroidRuntime(28027):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
E/AndroidRuntime(28027):    at dalvik.system.NativeStart.main(Native Method)
E/AndroidRuntime(28027): Caused by: java.lang.ClassNotFoundException: Didn't find class "android.preference.PreferenceSreen" on path: /data/app/com.android.settings-1.apk

Why this method can't start a fragment?

Upvotes: 2

Views: 5279

Answers (2)

MatJB
MatJB

Reputation: 155

If you've arrived here in 2021, chances are you are using Kotlin and Navigation Component.

So you can do the following:

In your settings.xml:

<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">    
    
<Preference
            app:key="@string/fragment_settings_key"
            app:title="Go to Fragment!"/>

</PreferenceScreen>

And in your SettingsFragment:

class SettingsFragment : PreferenceFragmentCompat() { 
    
        override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
            setPreferencesFromResource(R.xml.settings, rootKey)
    
            val preferenceFragment: Preference? = findPreference(getString(R.string.fragment_settings_key))
    
            preferenceFragment?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
                view?.findNavController()?.navigate(R.id.MyFragment)
                true
            }
        }
  }

        

Upvotes: 3

Valkova.V
Valkova.V

Reputation: 243

Intents are for starting activities, services, content providers and broadcast receivers. So if the fragment you want to add is in the same activity as the preference fragment it wouldn't be the ideal use case for an intent. Maybe try something of the sorts:

public class MyPreferenceFragment extends PreferenceFragmentCompat{

   OpenFragmentListener openFragmentListener;

   public interface OpenFragmentListener{
      void openFragment();
   }

    @Override
    public void onAttach(Activity activity){
       super.onAttach(activity);
       openFragmentListener = (OpenFragmentListener)activity;

    }

    @Override
    public void onCreatePreferences(Bundle bundle, String s) {
        getPreferenceManager().setSharedPreferencesName(Constants.PREFERENCES);
        addPreferencesFromResource(R.xml.preferences);
        preference = this.findPreference("key"); 
        preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener(){
           @Override
           public boolean onPreferenceClick(Preference preference){
              openFragmentListener.openFragment();
              return true;
           }
        });
   }

}

And then in the Activity implement MyPreferenceFragment.OpenFragmentListener and override the method something like this:

@Override
public void openFragment(){
   getSupportFragmentManager()
             .beginTransaction()
             .remove(myPreferenceFragment)
             .add(R.id.placeHolderForTheFragmentYouWant, theFragmentYouWant)
             .addToBackStack("setting")
             .commit();
}

Upvotes: 1

Related Questions