如何更新TextView文本(解码文本效果)
本文关键字:文本 解码 何更新 TextView 更新 | 更新日期: 2023-09-27 18:14:19
我需要标题中提到的帮助。
我有一个计时器例程,它将更新标签的文本。这是一种解码文本效果,但当计时器例程执行时,它似乎不会更新。我正在使用c#。
MainActivity.cs
using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using System.Text;
using System.Timers;
using System.Linq;
namespace ValidateCreditCardNumber_Android
{
[Activity (Label = "ValidateCreditCardNumber_Android", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
EditText editText;
DecodeTextView resultLabel;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
editText = FindViewById<EditText> (Resource.Id.editText);
Button validateButton = FindViewById<Button> (Resource.Id.validateButton);
resultLabel = FindViewById<DecodeTextView> (Resource.Id.resultLabel);
editText.KeyListener = Android.Text.Method.DigitsKeyListener.GetInstance("0123456789" + System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalDigits);
validateButton.Click += OnNumberEntryCompleted;
}
void OnNumberEntryCompleted(object sender, EventArgs args)
{
var entry = editText;
var resultText = "";
if (Mod10Check (entry.Text)) {
// resultLabel.SetTextColor(Android.Graphics.Color.White);
resultText = "__VALID NUMBER";
} else {
resultText = "INVALID NUMBER";
}
// entry.Enabled = false;
// resultLabel.AnimateText (true, resultText, 10);
RunOnUiThread(() => resultLabel.AnimateText (true, resultText, 10));
}
public static bool Mod10Check(string creditCardNumber)
{
// Check whether input string is null or empty.
if (string.IsNullOrEmpty(creditCardNumber)) {
return false;
}
char[] charArray = creditCardNumber.ToCharArray();
// 1. Starting with the check digit double the value of every other digit
// 2. If doubling of a number results in a two digits number, add up.
// the digits to get a single digit number. This will results in eight single digit numbers.
// 3. Get the sum of the digits.
int sumOfDigits = charArray.Where((e) => e >= '0' && e <= '9')
.Reverse()
.Select((e, i) => ((int)e - 48) * (i % 2 == 0 ? 1 : 2))
.Sum((e) => e / 10 + e % 10);
// If the final sum is divisible by 10, then the credit card number.
// is valid. If it is not divisible by 10, the number is invalid.
return sumOfDigits % 10 == 0;
}
}
}
DecodeTextView.cs
using System;
using System.Text;
using System.Timers;
//using Android.Runtime;
using Android.Content;
using Android.Util;
namespace ValidateCreditCardNumber_Android
{
public class DecodeTextView : Android.Widget.TextView
{
private readonly Timer _timerAnimate = new Timer();
private TextDecodeEffect _decodeEffect;
private bool _showing;
private int _initGenCount;
public int Interval
{
get { return (int)_timerAnimate.Interval; }
set { _timerAnimate.Interval = value; }
}
// protected DecodeTextView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
public DecodeTextView(Context c, IAttributeSet args) : base(c, args)
{
_timerAnimate.Interval = 100;
_timerAnimate.Elapsed += _timerAnimate_Tick;
}
public void AnimateText(bool show, string text, int initGenCount)
{
_initGenCount = initGenCount;
_decodeEffect = new TextDecodeEffect(text) { TextVisible = !show };
Text = _decodeEffect.Peek (DecodeMode.None);
_showing = show;
_timerAnimate.Start ();
}
private void _timerAnimate_Tick(object sender, EventArgs e)
{
if (_initGenCount != 0) {
Text = _decodeEffect.GenerateNumberRange (Text.Length);
_initGenCount--;
return;
}
var decodeMode = _showing ? DecodeMode.Show : DecodeMode.Hide;
var text = _decodeEffect.Peek (decodeMode);
if (text == null) {
_timerAnimate.Stop ();
} else {
Text = text;
}
}
}
public enum DecodeMode
{
None,
Show,
Numbers,
Hide
}
class TextDecodeEffect
{
private int _visibleCount;
private readonly Random _random = new Random ();
public bool TextVisible
{
get { return _visibleCount == OriginalText.Length; }
set { _visibleCount = value ? OriginalText.Length : 0; }
}
public string OriginalText { get; private set; }
public TextDecodeEffect(string text)
{
OriginalText = text;
}
public string Peek(DecodeMode mode)
{
switch (mode) {
case DecodeMode.Numbers:
return GenerateNumberRange (OriginalText.Length);
case DecodeMode.Hide:
if (_visibleCount == 0)
return null;
_visibleCount--;
break;
case DecodeMode.Show:
if (_visibleCount == OriginalText.Length)
return null;
_visibleCount++;
break;
}
var text = GenerateNumberRange (OriginalText.Length - _visibleCount);
text += OriginalText.Substring (OriginalText.Length - _visibleCount, _visibleCount);
return text;
}
public string GenerateNumberRange(int count)
{
var SB = new StringBuilder ();
for (int i = 0; i < count; i++)
SB.Append(_random.Next(0, 10));
return SB.ToString();
}
}
}
在这里你可以找到项目
请帮我解决这个问题:(谢谢。
这是一个线程问题,你只能在UI线程上更改UI元素,定时器回调_timerAnimate_Tick
将在后台线程上执行。
你可以通过记录DecodeTextView
的构造函数和它的_timerAnimate_Tick
方法的线程ID来看到这一点:
public DecodeTextView(Context c, IAttributeSet args) : base(c, args)
{
// ...
Console.WriteLine ("DecodeTextView executing on thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
}
private void _timerAnimate_Tick(object sender, EventArgs e)
{
Console.WriteLine ("_timerAnimate_Tick executing on thread: " + System.Threading.Thread.CurrentThread.ManagedThreadId);
// ...
}
将在日志输出中呈现以下内容:
DecodeTextView executing on thread: 1
_timerAnimate_Tick executing on thread: 6
这可以通过使用Post
方法在UI线程上改变DecodeTextView
的Text
属性来修复:
private void _timerAnimate_Tick(object sender, EventArgs e)
{
if (_initGenCount != 0) {
Post (() => {
Text = _decodeEffect.GenerateNumberRange (Text.Length);
});
_initGenCount--;
return;
}
var decodeMode = _showing ? DecodeMode.Show : DecodeMode.Hide;
var text = _decodeEffect.Peek (decodeMode);
if (text == null) {
_timerAnimate.Stop ();
} else {
Post (() => {
Text = text;
});
}
}