在侦听器中更改 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 = 0
或 String showTime = "Show time";
。编译器将再次发出警告,如果变量要在匿名内部 class 中使用,则必须声明变量 final
。但是通过这样做,它们不能再被改变。事实上,如果试图更改值,代码甚至无法编译。通过使 TextView timeView;
成为 class 变量(即将其移出 onCreate()
方法),该字段的范围将增加以包括匿名内部 class。变量 int count = 0
或 String showTime = "Show time";
也是如此——使它们成为 class 变量也会增加它们的范围以包括匿名内部 class 以便它们可以被使用和在方法内部更改 onProgressChanged()
。因此,我认为使用 class 变量而不是 final
更直观。
查看 Java 文档:
Anonymous Classes
Accessing Members of an Enclosing Class
我正在尝试让 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 = 0
或 String showTime = "Show time";
。编译器将再次发出警告,如果变量要在匿名内部 class 中使用,则必须声明变量 final
。但是通过这样做,它们不能再被改变。事实上,如果试图更改值,代码甚至无法编译。通过使 TextView timeView;
成为 class 变量(即将其移出 onCreate()
方法),该字段的范围将增加以包括匿名内部 class。变量 int count = 0
或 String showTime = "Show time";
也是如此——使它们成为 class 变量也会增加它们的范围以包括匿名内部 class 以便它们可以被使用和在方法内部更改 onProgressChanged()
。因此,我认为使用 class 变量而不是 final
更直观。
查看 Java 文档:
Anonymous Classes
Accessing Members of an Enclosing Class