在侦听器中更改 TextView 的文本时出现问题

Problems changing TextView's text inside a listener

我正在尝试让 TextView 看起来像一个计时器,并用 SeekBar 来控制显示的时间。

首先,我收到消息 TextView 必须是最终的,但是当我更改它时,我无法在侦听器中使用 setText 更改 TextView

如何修复此代码?

    SeekBar seekBar = findViewById(R.id.seekBar);
    final TextView timeView = findViewById(R.id.timeView);

    seekBar.setMax(600);
    seekBar.setProgress(30);

    seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            int minutes = progress / 60;
            int seconds = progress - (progress * 60);

            timeView.setText(Integer.toString(minutes), ":", Integer.toString(seconds));
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });
}

尝试创建一个 public Textview。 所以替换这一行

final TextView timeView = findViewById(R.id.timeView); 

timeView = findViewById(R.id.timeView); 

并添加这个

TextView timeView;

超过你的 OnCreate 方法。

您的代码的唯一问题是 setText() 方法的语法。
setText() 接受一个 String (CharSequence) 作为参数,所以改变这个:

timeView.setText(Integer.toString(minutes), ":", Integer.toString(seconds));

对此:

timeView.setText(Integer.toString(minutes) + ":" + Integer.toString(seconds));

替换

timeView.setText(Integer.toString(minutes), ":", Integer.toString(seconds));

timeView.setText(Integer.toString(minutes)+ ":"+ Integer.toString(seconds));

事实上,简单的解决方案是简单地更改 OP 希望在 onProgressChanged() 方法中使用 setText() 的代码行:setText() 方法没有覆盖处理这些参数。简单的解决方案(如许多答案所述):

timeView.setText(Integer.toString(minutes) + ":" + Integer.toString(seconds));



但是...深入挖掘
TL;DR

本来OP只是想在onCreate()方法中使用TextView timeView,但是被编译器警告说他们需要在[=14=前面加上final ]为了能够在匿名内部classSeekBar.OnSeekBarChangeListener()里面使用timeView

但是,一般情况下,关键字final表示变量在初始化后不能改变。尽管在这种特殊情况下 有点混乱 使用 final 将允许使用 setText().

更改 TextView

主要问题是范围。 SeekBar.OnSeekBarChangeListener() 是匿名内部 class 而 onCreate() 是封闭块。这(基本上)意味着内部 class 实际上不属于 onCreate() 并且 timeView 在方法 范围 之外 onProgressChanged().

当然,将 final 添加到方法变量 TextView timeView 将 "fix" 问题--在这种特殊情况下(有些人喜欢它),但不是所有案例;因此,我认为使用 final 是违反直觉的。

考虑在 onCreate() 内部但在匿名内部 class 外部的变量 int count = 0String showTime = "Show time";。编译器将再次发出警告,如果变量要在匿名内部 class 中使用,则必须声明变量 final。但是通过这样做,它们不能再被改变。事实上,如果试图更改值,代码甚至无法编译。通过使 TextView timeView; 成为 class 变量(即将其移出 onCreate() 方法),该字段的范围将增加以包括匿名内部 class。变量 int count = 0String showTime = "Show time"; 也是如此——使它们成为 class 变量也会增加它们的范围以包括匿名内部 class 以便它们可以被使用和在方法内部更改 onProgressChanged()。因此,我认为使用 class 变量而不是 final 更直观。

查看 Java 文档:
Anonymous Classes
Accessing Members of an Enclosing Class