Butterknife: Feature Request: Binding listeners inside PreferenceFragments

Created on 4 Jan 2015  路  2Comments  路  Source: JakeWharton/butterknife

Maybe it's not as useful as I think it would be, but I think it'd be beneficial to provide the listener binding and view injection for Preferences in addition to views. Some of the apps I've seen use a structure of PreferenceFragments to make up all their settings, and finding them and assigning their listeners is basically the same boilerplate as with Buttons and other Views.

I end up with a lot of this:

deletePref = findPreference("delete_images");
deletePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        deleteImages();
        return true;
    }
});

prefixPref = findPreference("image_prefix");
prefixPref.setSummary("Prefix: " + AppSettings.getImagePrefix());
prefixPref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        showDialogForImagePrefix();
        return true;
    }
});

timePref = findPreference("time");
timePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
    @Override
    public boolean onPreferenceClick(Preference preference) {
        changeTime();
        return true;
    }
});

I'm still a beginner in terms of coding, but this should be possible with the current library setup. The @InjectView, @OnClick, etc, would have to accept String keys instead of int IDs and it's basically the same setup, such that the above code could be simplified to this.

@InjectView("delete_images") Preference deletePref;
@InjectView("image_prefix") Preference prefixPref;
@InjectView("time") Preference timePref;

@OnClick("delete_images")
public void deleteImages(){
}

@OnClick("image_prefix")
public void showDialogForImagePrefix() {
}

@OnClick("time")
public void changeTime() {
}

Technically you can replace the @OnClick by iterating over the PreferenceScreen, setting each Preference's OnClickListener to the fragment, and then implementing a massive switch statement, but I still think the @InjectView would be helpful. Or maybe there's a better way of doing this that I don't know of.

Most helpful comment

Didn't see this before when I opened the same issue, chiming in with my vision for it:


Often times when dealing with shared preferences, I end up with a case like this.

public class MyPreferenceFragment extends PreferenceFragment {

    CheckboxPreference someCheckbox;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        someCheckbox = (CheckboxPreference) findPreference("key_some_checkbox");    
        someCheckbox.setOnPreferenceChangeListener(new OnPreferenceChangeListener {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                // Do something
                // Return something
            }
        }
    }

}

It would be very nice to do something like this instead:

public class MyPreferenceFragment extends PreferenceFragment {

    @InjectPreference("key_some_checkbox")
    CheckboxPreference someCheckbox;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @OnPreferenceChange("key_some_checkbox")
    boolean checkboxChanged(Preference preference, Object newValue) {
        // Do something
        // Return something
    }

}

There's also OnPreferenceClickListener, binding multiple keys to a listener, and easy casting of the newValue's type as other pros. It's admittedly a niche use-case, but I think it would be a useful tool. If you're open to a pull request for it, I can take a crack at it this weekend.

All 2 comments

Didn't see this before when I opened the same issue, chiming in with my vision for it:


Often times when dealing with shared preferences, I end up with a case like this.

public class MyPreferenceFragment extends PreferenceFragment {

    CheckboxPreference someCheckbox;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        someCheckbox = (CheckboxPreference) findPreference("key_some_checkbox");    
        someCheckbox.setOnPreferenceChangeListener(new OnPreferenceChangeListener {
            @Override
            public boolean onPreferenceChange(Preference preference, Object newValue) {
                // Do something
                // Return something
            }
        }
    }

}

It would be very nice to do something like this instead:

public class MyPreferenceFragment extends PreferenceFragment {

    @InjectPreference("key_some_checkbox")
    CheckboxPreference someCheckbox;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @OnPreferenceChange("key_some_checkbox")
    boolean checkboxChanged(Preference preference, Object newValue) {
        // Do something
        // Return something
    }

}

There's also OnPreferenceClickListener, binding multiple keys to a listener, and easy casting of the newValue's type as other pros. It's admittedly a niche use-case, but I think it would be a useful tool. If you're open to a pull request for it, I can take a crack at it this weekend.

As far as I can tell there's no override with views or resources here. I think this would be best as a standalone library that's specifically targeted at preferences. I have neither the time nor desire to put it in ButterKnife, but there's no reason something like it shouldn't exist.

Was this page helpful?
0 / 5 - 0 ratings