Brendan Weinstein
Brendan Weinstein

Reputation: 7220

setOnPreferenceChangeListener not working for custom checkboxpreference

I made a simple extension of CheckBoxPreference so that I could have my own custom view with an image icon to the left of the title. The code is below:

public class CustomCheckBoxPreference extends CheckBoxPreference {

private Drawable icon;

public CustomCheckBoxPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.CustomCheckBoxPreference, 0, 0);
    icon = arr.getDrawable(R.styleable.CustomCheckBoxPreference_icon);
    setLayoutResource(R.layout.custom_checkbox_pref);
}

@Override
protected void onBindView(View view) {
    super.onBindView(view);
    ImageView prefsIcon = (ImageView) view.findViewById(R.id.prefs_icon);
    prefsIcon.setImageDrawable(icon);
}

The problem is that for some reason the OnPreferenceChangeListener I set to any CustomCheckboxPreference has no effect and is not stored. I tried overriding some of the android methods for the implementation calling super and then printing a line to see what gets called. Notably callChangeListener does not get called. It is this method that leads to the callback for onPreferenceChanged. I tried throwing in a call to onPreferenceChanged inside of setChecked just to see what would happen and the OnPreferenceChangeListener is null:

            getOnPreferenceChangeListener().onPreferenceChange(this, checked);

This is how I set the preferencechangelistener:

        mTwitterPref.setChecked(!mTwitter.needsAuth());
    mTwitterPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            System.out.println("Twitter Preference Changed!");
            if ((Boolean) newValue) {
                if (mTwitter.needsAuth()) {
                    System.out.println("We Need To Login To Twitter!");
                    IntentUtils.startActivityForResult(ProfileAccountsActivity.this,
                            TwLoginActivity.class, ACTIVITY_OAUTH);
                }
            } else {
              showDialog(DIALOG_LOGOUT_TWITTER);
            }
            return false;
        }
    });

I am a bit confused as to why the preferencechangelistener is not working properly as I only overwrite onBindView and the constructor; I call super in both. Any thoughts?

Upvotes: 2

Views: 4930

Answers (3)

Kazuhiko Nakayama
Kazuhiko Nakayama

Reputation: 801

I found solution ! In my case, I extends DialogPreference to my custom Dialog class,

public class SvDialogPreference extends DialogPreference

I also confuse, because in PreferenceFragment, onPreferenceChange never worked.

SvDialogPreference pref= (SvDialogPreference) findPreference("mainKey");
if( pref != null ) {
pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
// Never execute !
}}

To resolve this. I called "super.callChangeListener" in onDialogClosed.

public class SvDialogPreference extends DialogPreference{
....
@Override
protected void onDialogClosed(boolean positiveResult) {

double InputValue = Double.parseDouble(KEY.getText().toString());
     super.callChangeListener(InputValue);
     super.onDialogClosed(positiveResult);
}

Now, onPreferenceChange worked fine !

Upvotes: 0

Nolesh
Nolesh

Reputation: 7018

I had the same issue with custom button. I tried the solution provided by @jeanh and it works. But my button was not pressed, only area around it was highlighted. Moreover, what if you have a few buttons? Obviously, that this solution won't work. So, I decided to dig deeper and my solution was below:

xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/widget_frame" android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingTop="5dp"
android:paddingRight="10dp"
android:paddingBottom="5dp"    
>
<!-- define my button -->
<Button android:id="@android:id/title"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:typeface="sans"
        android:textStyle="bold"
        android:textColor="#000000"
></Button>    

</RelativeLayout>

Java class:

public class ButtonPreference extends Preference {

    private final String TAG = getClass().getName();

    public interface ButtonListener {      
        public void onCustomClick();
    }

    public ButtonListener buttonListener;

    public void setButtonListener(ButtonListener buttonListener){
        this.buttonListener = buttonListener;
    }

    public ButtonPreference(Context context, AttributeSet attrs) {
        super(context, attrs);       
    }

    public ButtonPreference(Context context, AttributeSet attrs, int  defStyle) {
        super(context, attrs, defStyle);        
    }

    @Override
    protected View onCreateView(ViewGroup parent){

        RelativeLayout layout =  null;

        try {
            LayoutInflater mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            layout = (RelativeLayout)mInflater.inflate(R.layout.button_preference, parent, false);
            //FIND OUR BUTTON IN LAYOUT
            Button button = (Button) layout.findViewById(android.R.id.title);
            if(button!=null){
            Log.e(TAG, "button found");
            button.setOnClickListener(new OnClickListener() {                   
                @Override
                public void onClick(View v) {                       
                    if(buttonListener!=null){                           
                        buttonListener.onCustomClick(); //INVOKE OUR EVENT!
                    }
                }
            });
            }            
       }
       catch(Exception e)
       {
           Log.e(TAG, "Error creating info preference", e);
       }        
       return layout;        
   }    
}

HOW TO USE IT? Simple!

public class WallpaperSettings extends PreferenceActivity {

protected void onCreate(Bundle savedInstanceState) {        
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.prefs);    

    ButtonPreference defaultSettingsButton = (ButtonPreference) findPreference(EngineCore.pref+"defaultSettings");      
    defaultSettingsButton.setButtonListener(new ButtonListener() {          
        @Override
        public void onCustomClick() {
            Gdx.app.log("ButtonListener", "onCustomClick");             
        }
    });
}   
}

I hope it helps someone else.

Upvotes: 0

jeanh
jeanh

Reputation: 228

Set android:focusable="false" and android:clickable="false" on the CheckBox:

<CheckBox
    android:id="@+android:id/checkbox"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" 
    android:focusable="false"
    android:clickable="false" />

More info on this thread: Clickable rows on custom ArrayAdapter

Upvotes: 4

Related Questions