我不知道为什么没有调用 performClick() 方法
I dont know why the performClick() method not called
我正在编写一个实现 Checkable 接口的按钮。我覆盖了方法:performClick,但它没有被调用。正如文档中提到的那样:
Description copied from class: android.view.View
Call this view's OnClickListener, if it is defined. Performs all normal actions associated with clicking: reporting accessibility event, playing a sound, etc.
我觉得应该是当我点击屏幕上的按钮时系统自动调用的。但没有任何反应。还是必须自己调用?
我有以下代码:
public class MyButton extends Button implements Checkable {
private static final String TAG = "MyButton";
private boolean mChecked;
private boolean mBroadcasting;
private OnCheckedChangeListener mOnCheckedChangeListener;
private OnCheckedChangeListener mOnCheckedChangeWidgetListener;
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
public MyButton(Context context) {
this(context, null);
}
public MyButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i(TAG, "begin to paint lines");
Paint paint = getPaint();
paint.setColor(android.graphics.Color.BLACK);
canvas.drawLine(0, 0, this.getWidth(), 0, paint);
canvas.drawLine(0, 0, 0, this.getHeight(), paint);
canvas.drawLine(this.getWidth(), 0, this.getWidth(), this.getHeight(), paint);
canvas.drawLine(0, this.getHeight(), this.getWidth(), this.getHeight(), paint);
}
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(MyButton.class.getName());
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(MyButton.class.getName());
}
@Override
public boolean performClick() {
toggle();
Log.i(TAG, "the view was clicked");
return super.performClick();
}
@Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
// Avoid infinite recursions if setChecked() is called from a listener
if (mBroadcasting) {
return;
}
mBroadcasting = true;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
}
if (mOnCheckedChangeWidgetListener != null) {
mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
}
mBroadcasting = false;
}
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public void toggle() {
setChecked(!mChecked);
Log.i(TAG, "the view was toggled");
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
int[] drawableState = super.onCreateDrawableState(extraSpace);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
public OnCheckedChangeListener getOnCheckedChangeListener() {
return mOnCheckedChangeListener;
}
public void setOnCheckedChangeListener(OnCheckedChangeListener mOnCheckedChangeListener) {
this.mOnCheckedChangeListener = mOnCheckedChangeListener;
}
public OnCheckedChangeListener getOnCheckedChangeWidgetListener() {
return mOnCheckedChangeWidgetListener;
}
public void setOnCheckedChangeWidgetListener(OnCheckedChangeListener mOnCheckedChangeWidgetListener) {
this.mOnCheckedChangeWidgetListener = mOnCheckedChangeWidgetListener;
}
/**
* Interface definition for a callback to be invoked when the checked state
* of a compound button changed.
*/
public static interface OnCheckedChangeListener {
/**
* Called when the checked state of a compound button has changed.
*
* @param buttonView The compound button view whose state has changed.
* @param isChecked The new checked state of buttonView.
*/
void onCheckedChanged(MyButton buttonView, boolean isChecked);
}
}
布局中的 MyButton:
<com.example.demo.view.MyButton
android:id="@+id/mybtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/checkable_button"
android:textColor="@drawable/button_text"
android:text="checkable" />
在此先感谢您。
下面第一个答案是正确的。
解释:
public MyButton(Context context, AttributeSet attrs) this one is
called. Then it calls MyButton(context, attrs, 0). This is where
defStyleAttr is being set to 0, while by default it would be
com.android.internal.R.attr.buttonStyle.
您需要使用适当的构造函数:
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public MyButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
编辑:
这些是来自 Button
class 的构造函数:
public Button(Context context) {
this(context, null);
}
public Button(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.buttonStyle);
}
public Button(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
看看你能不能找到这些和你的构造函数之间的区别。
我正在编写一个实现 Checkable 接口的按钮。我覆盖了方法:performClick,但它没有被调用。正如文档中提到的那样:
Description copied from class: android.view.View Call this view's OnClickListener, if it is defined. Performs all normal actions associated with clicking: reporting accessibility event, playing a sound, etc.
我觉得应该是当我点击屏幕上的按钮时系统自动调用的。但没有任何反应。还是必须自己调用?
我有以下代码:
public class MyButton extends Button implements Checkable {
private static final String TAG = "MyButton";
private boolean mChecked;
private boolean mBroadcasting;
private OnCheckedChangeListener mOnCheckedChangeListener;
private OnCheckedChangeListener mOnCheckedChangeWidgetListener;
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
public MyButton(Context context) {
this(context, null);
}
public MyButton(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i(TAG, "begin to paint lines");
Paint paint = getPaint();
paint.setColor(android.graphics.Color.BLACK);
canvas.drawLine(0, 0, this.getWidth(), 0, paint);
canvas.drawLine(0, 0, 0, this.getHeight(), paint);
canvas.drawLine(this.getWidth(), 0, this.getWidth(), this.getHeight(), paint);
canvas.drawLine(0, this.getHeight(), this.getWidth(), this.getHeight(), paint);
}
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(MyButton.class.getName());
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(MyButton.class.getName());
}
@Override
public boolean performClick() {
toggle();
Log.i(TAG, "the view was clicked");
return super.performClick();
}
@Override
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
// Avoid infinite recursions if setChecked() is called from a listener
if (mBroadcasting) {
return;
}
mBroadcasting = true;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mChecked);
}
if (mOnCheckedChangeWidgetListener != null) {
mOnCheckedChangeWidgetListener.onCheckedChanged(this, mChecked);
}
mBroadcasting = false;
}
}
@Override
public boolean isChecked() {
return mChecked;
}
@Override
public void toggle() {
setChecked(!mChecked);
Log.i(TAG, "the view was toggled");
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {
int[] drawableState = super.onCreateDrawableState(extraSpace);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
public OnCheckedChangeListener getOnCheckedChangeListener() {
return mOnCheckedChangeListener;
}
public void setOnCheckedChangeListener(OnCheckedChangeListener mOnCheckedChangeListener) {
this.mOnCheckedChangeListener = mOnCheckedChangeListener;
}
public OnCheckedChangeListener getOnCheckedChangeWidgetListener() {
return mOnCheckedChangeWidgetListener;
}
public void setOnCheckedChangeWidgetListener(OnCheckedChangeListener mOnCheckedChangeWidgetListener) {
this.mOnCheckedChangeWidgetListener = mOnCheckedChangeWidgetListener;
}
/**
* Interface definition for a callback to be invoked when the checked state
* of a compound button changed.
*/
public static interface OnCheckedChangeListener {
/**
* Called when the checked state of a compound button has changed.
*
* @param buttonView The compound button view whose state has changed.
* @param isChecked The new checked state of buttonView.
*/
void onCheckedChanged(MyButton buttonView, boolean isChecked);
}
}
布局中的 MyButton:
<com.example.demo.view.MyButton
android:id="@+id/mybtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/checkable_button"
android:textColor="@drawable/button_text"
android:text="checkable" />
在此先感谢您。
下面第一个答案是正确的。
解释:
public MyButton(Context context, AttributeSet attrs) this one is called. Then it calls MyButton(context, attrs, 0). This is where defStyleAttr is being set to 0, while by default it would be com.android.internal.R.attr.buttonStyle.
您需要使用适当的构造函数:
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public MyButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
编辑:
这些是来自 Button
class 的构造函数:
public Button(Context context) {
this(context, null);
}
public Button(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.buttonStyle);
}
public Button(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public Button(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
看看你能不能找到这些和你的构造函数之间的区别。