java – How to pass a CheckedChange Listener to a custom view-ThrowExceptions

Exception or error:

Update on 2020/02/17
Okay, I find the solution. The reason causes the custom listener stop working in the custom class is the XML file layout. In the past, all my successful experiences are build on the LinearLayout. I missed that in my original problem description. the new custom view XML file I used ConstraintLayout, instead of LinearLayout. This causes the ‘abnormal’ inflate behavior that use to work with the LinearLayout.

In LinearLayout custom view class, init() function, I used

inflate(getContext(), R.layout.my_ll_custom_view,this);

This won’t work with the constraintlayout.
I have to use following code,

View rootView = LayoutInflater.from(context).inflate(R.layout.my_cl_custom_view, this, false);
ConstraintSet constraintSet = new ConstraintSet();
this.addView(rootView);
ConstraintLayout.LayoutParams clp = new ConstraintLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
rootView.setLayoutParams(clp);
constraintSet.clone(this);
constraintSet.connect(rootView.getId(), ConstraintSet.LEFT, this.getId(), ConstraintSet.LEFT, 0);
constraintSet.connect(rootView.getId(), ConstraintSet.RIGHT, this.getId(), ConstraintSet.RIGHT, 0);
constraintSet.connect(rootView.getId(), ConstraintSet.TOP, this.getId(), ConstraintSet.TOP, 0);
constraintSet.connect(rootView.getId(), ConstraintSet.BOTTOM, this.getId(), ConstraintSet.BOTTOM, 0);

More details can be found in https://jordan-dixon.com/2017/12/30/custom-views-with-constraint-layout-and-kotlin/

I read this blog to figure this out. and I appreciate it.

======Original problem description starts from here======

I made a custom view with 3 toggle buttons. In my custom view class I set

public void setMyToggleButton1OnCheckedChangedListener(CompoundButton.OnCheckedChangeListener o) {
    myToggleButton1.setOnCheckedChangeListener(o);
}

but when I try to handle this even in my main activity, it looks like this event never been triggered. In the main activity I tried

myCustomView.setMyToggleButton1OnCheckedChangedListener(new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (isChecked) {
                //TODO something here
            }
            else {
                //TODO something here
            }
        }
    });

I did try my other custom view with regular button and pass the standard button click event to it with the same method. I don’t understand what makes it different to pass a standard button click event to custom view and passing a toggle button checkedchange event listener to a custom view.

PS: Here is what I did for regular button and its OnClickListener. This one works as I expected, that’s why I try to replicate it to Toggle Button and the OnCheckedChangeListener.

in myCustomView2 (the custom view contains regular buttons)

public class myCustomView2 extends ConstraintLayout{
    private Button myRegBtn1;
    ...
    public myCustomView2(Context context) {
        this(context, null);
    }

    public myCustomView2(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
         setAttributes(context, attrs);
    }

    public myCustomView2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setAttributes(context, attrs);
        init(context);
    }

    private void init(Context context) {
        myRegBtn = findViewById(R.id.btn1);
        ...
    }

    private void setAttributes(Context context, AttributeSet attrs) {
        ...
    }

    public void setMyRegBtnOnClickListener(OnClickListener o) {
        myRegBtn.setOnClickListener(o);
    }
}

In my mainActivity,

public class myMainActivity extends AppCompatActivity{
    private MyCustomView2 myCustomView2;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        ...
        myCustomView2.setMyRegBtnOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View view) {
                //TODO: some code execute here when button clicked
            }
        });
    ...
}
How to solve:

You need to call your CheckedChangeListener yourself

i.e lister.onCheckedChange(isChecked)

It would work out of the box only if you extend the CheckBox view.

###

0

Update on 2020/02/17 Okay, I find the solution. The reason causes the custom listener stop working in the custom class is the XML file layout. In the past, all my successful experiences are build on the LinearLayout. I missed that in my original problem description. the new custom view XML file I used ConstraintLayout, instead of LinearLayout. This causes the ‘abnormal’ inflate behavior that use to work with the LinearLayout.

In LinearLayout custom view class, init() function, I used

inflate(getContext(), R.layout.my_ll_custom_view,this);

This won’t work with the constraintlayout. I have to use following code,

View rootView = LayoutInflater.from(context).inflate(R.layout.my_cl_custom_view, this, false);
ConstraintSet constraintSet = new ConstraintSet();
this.addView(rootView);
ConstraintLayout.LayoutParams clp = new 
ConstraintLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 
ViewGroup.LayoutParams.WRAP_CONTENT);
rootView.setLayoutParams(clp);
constraintSet.clone(this);
constraintSet.connect(rootView.getId(), ConstraintSet.LEFT, this.getId(), ConstraintSet.LEFT, 0);
constraintSet.connect(rootView.getId(), ConstraintSet.RIGHT, this.getId(), ConstraintSet.RIGHT, 0);
constraintSet.connect(rootView.getId(), ConstraintSet.TOP, this.getId(), ConstraintSet.TOP, 0);
constraintSet.connect(rootView.getId(), ConstraintSet.BOTTOM, this.getId(), ConstraintSet.BOTTOM, 0);

More details can be found in https://jordan-dixon.com/2017/12/30/custom-views-with-constraint-layout-and-kotlin/

I read this blog to figure this out. and I appreciate it.

Leave a Reply

Your email address will not be published. Required fields are marked *