diff --git a/app/src/main/java/com/hippo/ehviewer/ui/legacy/RadioGridGroup.kt b/app/src/main/java/com/hippo/ehviewer/ui/legacy/RadioGridGroup.kt index 0bc0e2357..912f130cc 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/legacy/RadioGridGroup.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/legacy/RadioGridGroup.kt @@ -13,252 +13,234 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package com.hippo.ehviewer.ui.legacy -package com.hippo.ehviewer.ui.legacy; - -import android.content.Context; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CompoundButton; -import android.widget.RadioButton; - -import androidx.annotation.IdRes; - -import com.hippo.ehviewer.yorozuya.ViewUtils; - -public class RadioGridGroup extends SimpleGridLayout { - - private static final int[] RADIO_ATTRS = new int[]{ - android.R.attr.checkedButton - }; - - // holds the checked id; the selection is empty by default - private int mCheckedId = -1; - // tracks children radio buttons checked state - private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener; - // when true, mOnCheckedChangeListener discards events - private boolean mProtectFromCheckedChange = false; - private OnCheckedChangeListener mOnCheckedChangeListener; - private PassThroughHierarchyChangeListener mPassThroughListener; - - public RadioGridGroup(Context context, AttributeSet attrs) { - super(context, attrs); - init(context, attrs); - } - - public RadioGridGroup(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(context, attrs); - } - - private void init(Context context, AttributeSet attrs) { - final TypedArray a = context.obtainStyledAttributes(attrs, RADIO_ATTRS); - int value = a.getResourceId(0, View.NO_ID); - if (value != View.NO_ID) { - mCheckedId = value; - } - a.recycle(); - - mChildOnCheckedChangeListener = new CheckedStateTracker(); - mPassThroughListener = new PassThroughHierarchyChangeListener(); - super.setOnHierarchyChangeListener(mPassThroughListener); - } - +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.CompoundButton +import android.widget.RadioButton +import androidx.annotation.IdRes +import com.hippo.ehviewer.yorozuya.ViewUtils +class RadioGridGroup : SimpleGridLayout { /** - * {@inheritDoc} - */ - @Override - public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) { - // the user listener is delegated to our pass-through listener - mPassThroughListener.mOnHierarchyChangeListener = listener; - } - - /** - * {@inheritDoc} - */ - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - - // checks the appropriate radio button as requested in the XML file - if (mCheckedId != -1) { - mProtectFromCheckedChange = true; - setCheckedStateForView(mCheckedId, true); - mProtectFromCheckedChange = false; - setCheckedId(mCheckedId); - } - } - - @Override - public void addView(View child, int index, ViewGroup.LayoutParams params) { - if (child instanceof final RadioButton button) { - if (button.isChecked()) { - mProtectFromCheckedChange = true; - if (mCheckedId != -1) { - setCheckedStateForView(mCheckedId, false); - } - mProtectFromCheckedChange = false; - setCheckedId(button.getId()); - } - } - - super.addView(child, index, params); - } - - /** - *
Sets the selection to the radio button whose identifier is passed in - * parameter. Using -1 as the selection identifier clears the selection; - * such an operation is equivalent to invoking {@link #clearCheck()}.
* - * @param id the unique id of the radio button to select in this group - * @see #getCheckedRadioButtonId() - * @see #clearCheck() - */ - public void check(@IdRes int id) { - // don't even bother - if (id != -1 && (id == mCheckedId)) { - return; - } - - if (mCheckedId != -1) { - setCheckedStateForView(mCheckedId, false); - } - - if (id != -1) { - setCheckedStateForView(id, true); - } - - setCheckedId(id); - } - - private void setCheckedId(@IdRes int id) { - mCheckedId = id; - if (mOnCheckedChangeListener != null) { - mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId); - } - } - - private void setCheckedStateForView(int viewId, boolean checked) { - View checkedView = findViewById(viewId); - if (checkedView instanceof RadioButton) { - ((RadioButton) checkedView).setChecked(checked); - } - } - - /** - *Returns the identifier of the selected radio button in this group. - * Upon empty selection, the returned value is -1.
+ * Returns the identifier of the selected radio button in this group. + * Upon empty selection, the returned value is -1. * * @return the unique id of the selected radio button in this group - * @see #check(int) - * @see #clearCheck() + * @see .check + * @see .clearCheck */ - @IdRes - public int getCheckedRadioButtonId() { - return mCheckedId; + // holds the checked id; the selection is empty by default + @get:IdRes + var checkedRadioButtonId = -1 + private set + + // tracks children radio buttons checked state + private var mChildOnCheckedChangeListener: CompoundButton.OnCheckedChangeListener? = null + + // when true, mOnCheckedChangeListener discards events + private var mProtectFromCheckedChange = false + private var mOnCheckedChangeListener: OnCheckedChangeListener? = null + private var mPassThroughListener: PassThroughHierarchyChangeListener? = null + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + init(context, attrs) + } + + constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super( + context, + attrs, + defStyle + ) { + init(context, attrs) + } + + private fun init(context: Context, attrs: AttributeSet?) { + val a = context.obtainStyledAttributes(attrs, RADIO_ATTRS) + val value = a.getResourceId(0, NO_ID) + if (value != NO_ID) { + checkedRadioButtonId = value + } + a.recycle() + mChildOnCheckedChangeListener = CheckedStateTracker() + mPassThroughListener = PassThroughHierarchyChangeListener() + super.setOnHierarchyChangeListener(mPassThroughListener) + } + + /** + * {@inheritDoc} + */ + override fun setOnHierarchyChangeListener(listener: OnHierarchyChangeListener) { + // the user listener is delegated to our pass-through listener + mPassThroughListener!!.mOnHierarchyChangeListener = listener + } + + /** + * {@inheritDoc} + */ + override fun onFinishInflate() { + super.onFinishInflate() + + // checks the appropriate radio button as requested in the XML file + if (checkedRadioButtonId != -1) { + mProtectFromCheckedChange = true + setCheckedStateForView(checkedRadioButtonId, true) + mProtectFromCheckedChange = false + setCheckedId(checkedRadioButtonId) + } + } + + override fun addView(child: View, index: Int, params: LayoutParams) { + if (child is RadioButton) { + if (child.isChecked) { + mProtectFromCheckedChange = true + if (checkedRadioButtonId != -1) { + setCheckedStateForView(checkedRadioButtonId, false) + } + mProtectFromCheckedChange = false + setCheckedId(child.getId()) + } + } + super.addView(child, index, params) } /** - *Clears the selection. When the selection is cleared, no radio button - * in this group is selected and {@link #getCheckedRadioButtonId()} returns - * null.
* - * @see #check(int) - * @see #getCheckedRadioButtonId() + * Sets the selection to the radio button whose identifier is passed in + * parameter. Using -1 as the selection identifier clears the selection; + * such an operation is equivalent to invoking [.clearCheck]. + * + * @param id the unique id of the radio button to select in this group + * @see .getCheckedRadioButtonId + * @see .clearCheck */ - public void clearCheck() { - check(-1); + fun check(@IdRes id: Int) { + // don't even bother + if (id != -1 && id == checkedRadioButtonId) { + return + } + if (checkedRadioButtonId != -1) { + setCheckedStateForView(checkedRadioButtonId, false) + } + if (id != -1) { + setCheckedStateForView(id, true) + } + setCheckedId(id) + } + + private fun setCheckedId(@IdRes id: Int) { + checkedRadioButtonId = id + if (mOnCheckedChangeListener != null) { + mOnCheckedChangeListener!!.onCheckedChanged(this, checkedRadioButtonId) + } + } + + private fun setCheckedStateForView(viewId: Int, checked: Boolean) { + val checkedView = findViewByIdRegister a callback to be invoked when the checked radio button - * changes in this group.
+ * + * Clears the selection. When the selection is cleared, no radio button + * in this group is selected and [.getCheckedRadioButtonId] returns + * null. + * + * @see .check + * @see .getCheckedRadioButtonId + */ + fun clearCheck() { + check(-1) + } + + /** + * + * Register a callback to be invoked when the checked radio button + * changes in this group. * * @param listener the callback to call on checked state change */ - public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { - mOnCheckedChangeListener = listener; + fun setOnCheckedChangeListener(listener: OnCheckedChangeListener?) { + mOnCheckedChangeListener = listener } /** - *Interface definition for a callback to be invoked when the checked - * radio button changed in this group.
+ * + * Interface definition for a callback to be invoked when the checked + * radio button changed in this group. */ - public interface OnCheckedChangeListener { + interface OnCheckedChangeListener { /** - *Called when the checked radio button has changed. When the - * selection is cleared, checkedId is -1.
+ * + * Called when the checked radio button has changed. When the + * selection is cleared, checkedId is -1. * * @param group the group in which the checked radio button has changed * @param checkedId the unique identifier of the newly checked radio button */ - void onCheckedChanged(RadioGridGroup group, @IdRes int checkedId); + fun onCheckedChanged(group: RadioGridGroup?, @IdRes checkedId: Int) } - private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener { - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + private inner class CheckedStateTracker : CompoundButton.OnCheckedChangeListener { + override fun onCheckedChanged(buttonView: CompoundButton, isChecked: Boolean) { // prevents from infinite recursion if (mProtectFromCheckedChange) { - return; + return } - - mProtectFromCheckedChange = true; - if (mCheckedId != -1) { - setCheckedStateForView(mCheckedId, false); + mProtectFromCheckedChange = true + if (checkedRadioButtonId != -1) { + setCheckedStateForView(checkedRadioButtonId, false) } - mProtectFromCheckedChange = false; - - int id = buttonView.getId(); - setCheckedId(id); + mProtectFromCheckedChange = false + val id = buttonView.id + setCheckedId(id) } } /** - *A pass-through listener acts upon the events and dispatches them + * + * A pass-through listener acts upon the events and dispatches them * to another listener. This allows the table layout to set its own internal - * hierarchy change listener without preventing the user to setup his.
+ * hierarchy change listener without preventing the user to setup his. */ - private class PassThroughHierarchyChangeListener implements - ViewGroup.OnHierarchyChangeListener { - private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener; + private inner class PassThroughHierarchyChangeListener : OnHierarchyChangeListener { + var mOnHierarchyChangeListener: OnHierarchyChangeListener? = null /** * {@inheritDoc} */ - @Override - public void onChildViewAdded(View parent, View child) { - if (parent == RadioGridGroup.this && child instanceof RadioButton) { - int id = child.getId(); + override fun onChildViewAdded(parent: View, child: View) { + if (parent === this@RadioGridGroup && child is RadioButton) { + var id = child.getId() // generates an id if it's missing - if (id == View.NO_ID) { - id = ViewUtils.generateViewId(); - child.setId(id); + if (id == NO_ID) { + id = ViewUtils.generateViewId() + child.setId(id) } - ((RadioButton) child).setOnCheckedChangeListener( - mChildOnCheckedChangeListener); - } - - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewAdded(parent, child); + child.setOnCheckedChangeListener( + mChildOnCheckedChangeListener + ) } + mOnHierarchyChangeListener?.onChildViewAdded(parent, child) } /** * {@inheritDoc} */ - @Override - public void onChildViewRemoved(View parent, View child) { - if (parent == RadioGridGroup.this && child instanceof RadioButton) { - ((RadioButton) child).setOnCheckedChangeListener(null); - } - - if (mOnHierarchyChangeListener != null) { - mOnHierarchyChangeListener.onChildViewRemoved(parent, child); + override fun onChildViewRemoved(parent: View, child: View) { + if (parent === this@RadioGridGroup && child is RadioButton) { + child.setOnCheckedChangeListener(null) } + mOnHierarchyChangeListener?.onChildViewRemoved(parent, child) } } + + companion object { + private val RADIO_ATTRS = intArrayOf(android.R.attr.checkedButton) + } }