如何在 Android 中扩展 Button 类?

Posted

技术标签:

【中文标题】如何在 Android 中扩展 Button 类?【英文标题】:How to extend the Button class in Android? 【发布时间】: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。我怎样才能做到这一点? 【参考方案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_
        android:layout_
        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

以上是关于如何在 Android 中扩展 Button 类?的主要内容,如果未能解决你的问题,请参考以下文章

Paypal Native Checkout Button 不断加载,然后在 Android 上消失

Android中Button的五种监听事件

如何使用 android 中的 SQLite 扩展类在数据库中插入值?

Android-Button及其子类详解

你如何扩展像Android.widget包中的DatePicker PagerAdapter这样的Android类?

在 Android 中,如何以编程方式在 dp 中设置边距?