【问题标题】:How to extend the Button class in Android?如何在 Android 中扩展 Button 类?
【发布时间】:2021-12-24 01:52:08
【问题描述】:

我正在尝试在 Android 中扩展 Button 类。我有一个flicker.java 和一个MainActivity.java。我想扩展 Button 类并向其添加类似public void flicker_with_current_color(){} 的方法,以便我可以在MainActivity.java 中使用flicker.flicker_with_current_color();。不幸的是,Android Studio 给了我错误(作为提示):

此自定义视图应改为扩展 androidx.appcompat.widget.AppCompatButton

我想做的是添加一个自定义方法,以便我可以在任何地方使用它。我知道这可以通过在MainActivity.java 中创建一个方法来完成,但我正在尝试制作一个与Android 的Button 类相同但具有更多方法的自定义Button 类。我不知道我错在哪里。

flicker.java:

package com.its.me;

import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.provider.CalendarContract;
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.TextView;

import org.w3c.dom.Text;

import java.util.Timer;

public class flicker extends Button{

    public flicker(Context context) {
        super(context);
    }

    public void flicker_with_current_color(Button btn, String color_to_flicker, String color_to_switch_back_to, int time_interval, int times_to_flicker){

        for(int i=0; i<times_to_flicker; i++){

            btn.setTextColor(Color.parseColor(color_to_flicker));

            Timer t = new java.util.Timer();
            t.schedule(
                    new java.util.TimerTask() {
                        @Override
                        public void run() {

                            btn.setTextColor(Color.parseColor(color_to_switch_back_to));

                            t.cancel();
                        }
                    },
                    time_interval
            );

        }
    }

    public void flicker_with_current_color(String color_to_flicker, String color_to_switch_back_to, int time_interval, int times_to_flicker){

        for(int i=0; i<times_to_flicker; i++){

            this.setTextColor(Color.parseColor(color_to_flicker));

            Timer t = new java.util.Timer();
            t.schedule(
                    new java.util.TimerTask() {
                        @Override
                        public void run() {

                            //this.setTextColor(Color.parseColor(color_to_switch_back_to));

                            t.cancel();
                        }
                    },
                    time_interval
            );

        }
    }

    public void flicker_with_current_color(Button btn, int total_time, int times_to_flicker, String color_to_flicker, String color_to_switch_back_to){

        int time_interval = total_time/times_to_flicker;

        for(int i=0; i<times_to_flicker; i++){

            btn.setTextColor(Color.parseColor(color_to_flicker));

            Timer t = new java.util.Timer();
            t.schedule(
                    new java.util.TimerTask() {
                        @Override
                        public void run() {

                            btn.setTextColor(Color.parseColor(color_to_switch_back_to));

                            t.cancel();
                        }
                    },
                    time_interval
            );

        }

    }

}

【问题讨论】:

  • This custom view should extend androidx.appcompat.widget.AppCompatButton instead - 这只是一个警告,但最好使用AppCompat 版本的Button 以实现向后兼容性。请参阅here。当涉及到flicker 按钮时 - 完全预期的行为是什么,您提供的代码是否有效?如果不是,那么发生了什么?请改进您的问题。
  • @sweak,非常感谢!这么晚才回复很抱歉。代码不起作用。当我单击按钮时应用程序崩溃。我只是想为按钮添加一些功能,但我无法在 MainActivity.java 中使用它们。我希望 ExtendedButton 闪烁其参数中的时间和颜色,例如ExtendedButton.flicker_with_current_color(...);。在 XML 中,我想像 Android 的 Button 类一样添加它,例如 &lt;ExtendedButton.../&gt;。在问题中,闪烁类是ExtendedButton。我怎样才能做到这一点?

标签: java android class android-widget extends


【解决方案1】:

首先您必须记住,您将需要额外的重载构造函数。最重要的一项是您提供 XML 属性 attrs - 没有它,甚至无法创建按钮。您可以在您的代码中使用这组构造函数,这样就可以了:

public FlickerButton(Context context) {
    super(context, null, android.R.attr.buttonStyle);
}

public FlickerButton(Context context, AttributeSet attrs) {
    super(context, attrs, android.R.attr.buttonStyle);
}

public FlickerButton(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

您的代码中可能出现的第二个问题是CalledFromWrongThreadException。当您在不同的线程中设置了一个计时器及其任务时,Android 会抱怨该视图(在本例中为我们的 FlickerButton)正在与创建它的线程不同的线程上进行操作:

只有创建视图层次结构的原始线程才能接触其视图。

为此,我将更改 闪烁 动画的方法。我不会使用计时器,而是使用ValueAnimator 来设置颜色闪烁的动画。仔细分析代码:

private int buttonTextColor = Color.BLACK; // Initially we will set the color to black
private ValueAnimator flickerAnimation; // Animator that will animate between the colors

public void flicker_with_current_color(String colorToFlicker, String colorToSwitchBackTo, int timeInterval, int timesToFlicker) {

    // Animator will animate from the colorToSwitchBackTo 
    // through colorToFlicker and back to the colorToSwitchBackTo
    flickerAnimation = ValueAnimator.ofArgb(
            Color.parseColor(colorToSwitchBackTo),
            Color.parseColor(colorToFlicker),
            Color.parseColor(colorToSwitchBackTo)
    );

    // The duration of one animation interval and how many times teh animation will repeat
    flickerAnimation.setDuration(timeInterval).setRepeatCount(timesToFlicker);

    // Specify what will happen when the animated value will change
    flickerAnimation.addUpdateListener(valueAnimator -> {
        buttonTextColor = (int) valueAnimator.getAnimatedValue();

        // invalidate() will invalidate the view and in turn call the onDraw() method
        invalidate();
    });

    flickerAnimation.start(); // start the animation
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    setTextColor(buttonTextColor);
}

为了向后兼容,所有这些代码都在AppCompatButton 的子类中,您就可以使用该按钮了:

public class FlickerButton extends AppCompatButton {

    // Insert all the code from above here

}

在 XML 文件中:

<com.example.flickerbutton.FlickerButton
        android:id="@+id/flicker_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Flicker Button" />

FlickerButton的父级中:

((FlickerButton) findViewById(R.id.flicker_button)).setOnClickListener(view -> {
        ((FlickerButton) view).flicker_with_current_color(
                "white", "black", 500, 10);
    });

使用所有这些代码,按钮的文本颜色将在半秒内通过黑白闪烁 10 次。

现在我不会只留下这段代码 - 我建议您阅读 Android 中自定义视图的 this 指南,以便更好地了解上述代码中发生的事情并改进您现有的项目。祝你好运:)

【讨论】:

  • 非常感谢您的回答!它不再崩溃,但它不会闪烁。我想我以错误的方式使用它。 This 是 Fl​​ickerButton.java,其中包含您答案中的代码。我尝试仅使用您建议的功能,但我看不到按钮/其文本的颜色有任何变化。然后我复制粘贴了问题中的函数,但也没有用。然后我做了另一个函数,但没有按预期工作。
  • 它(我制作的另一个功能:changecol(...))只在我点击它时改变颜色(即使是我一直按下按钮的时候也不改变;只有当我释放它时,它才会改变颜色一会儿,然后变回黑色)。我在 MainActivity.java 中使用它,例如:flickerbuttonname.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(MainActivity.this, "Changing color now.", Toast.LENGTH_SHORT).show(); flickerbuttonname.changecol("#00ff00"); } });。我是否正确实施了它?再次感谢:D
  • 您必须向我展示您是如何在onClickListener 中使用flicker_with_current_color 函数的。
  • 您已将时间间隔设置为 5000 毫秒,即 5 秒。颜色过渡需要很长时间,因此没有闪烁效果。使其达到 500。
  • 等等,非常抱歉。当我第一次构建它时,我没有注释掉我的 onDragListener 和 onTouchListener。我很抱歉我忘记了这一点。我想这就是问题所在,并且以某种方式干扰了 UI 和按钮的事件。非常感谢 :D
猜你喜欢
  • 2015-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多