当一个计时器在Xamarin.Android上执行RunOnUiThread时,TextView文本滚动转到开始位置

时间:2017-10-19 10:34:05

标签: android xamarin timer xamarin.android

**我在使用带有android的TextView时遇到了一些问题:scrollHorizo​​ntally =" true"和计时器。

每次定时器执行Elapsed事件时,TextView的文本都会返回到开始位置,如果经过的时间太短,则文本接缝会发出声音。

但是当计时器未运行时,文本正确滚动。

这是AXML代码:**

<?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_alignParentTop="true"
            android:id="@+id/relFullMinimize">
            <ImageButton
                android:id="@+id/minimize_image_button_id"
                android:src="@drawable/ic_arrow_back_gray"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginTop="15dp"
                android:layout_marginLeft="15dp"
                android:scaleType="fitXY"
                android:clickable="true"
                android:layout_alignParentTop="true" />
            <ImageButton
                android:id="@+id/view_list_image_button_id"
                android:src="@drawable/ic_view_list_dark"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_marginTop="15dp"
                android:layout_marginEnd="15dp"
                android:scaleType="fitXY"
                android:clickable="true"
                android:layout_alignParentEnd="true"
                android:layout_alignParentTop="true" />
            <RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:gravity="center|top"
                android:layout_alignParentTop="true"
                android:id="@+id/relativeLayout1"
                android:layout_toLeftOf="@id/view_list_image_button_id"
                android:layout_toRightOf="@id/minimize_image_button_id">
                <TextView
                    android:id="@+id/viewplayerfullsongname"
                    android:text="Single-line text view that scrolls automatically if the text is too long to fit in the widget"
                    android:singleLine="true"
                    android:ellipsize="marquee"
                    android:marqueeRepeatLimit="marquee_forever"
                    android:focusable="true"
                    android:focusableInTouchMode="true"
                    android:scrollHorizontally="true"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />
                <TextView
                    android:id="@+id/viewplayerfullartistname"
                    android:text="B"
                    android:layout_below="@id/viewplayerfullsongname"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:gravity="center"
                    android:maxLines="2"
                    android:textSize="14sp"
                    android:layout_marginTop="5dp"
                    android:textColor="#fff1f4f9"
                    android:layout_marginLeft="15dp"
                    android:layout_marginRight="15dp" />
            </RelativeLayout>
        </RelativeLayout>
        <TextView
            android:id="@+id/time"
            android:textColor="@android:color/background_dark"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@id/relFullMinimize"
            android:text="Time xxx"
            android:layout_centerHorizontal="true"
            android:focusable="false" />
        <ProgressBar
            android:id="@+id/viewplayerProgressBar"
            android:layout_width="30dp"
            android:layout_height="30dp"
            android:layout_centerInParent="true"
            android:layout_below="@id/time"
            android:layout_centerHorizontal="true"
            android:focusable="false" />
    </RelativeLayout>

这是MainActivity中的代码:

public class MainActivity : Activity
    {
        int count = 1;
        private System.Timers.Timer playerTimer;
        TextView time;
        ProgressBar viewplayerProgressBar;

        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            //Button button = FindViewById<Button>(Resource.Id.myButton);

            //button.Click += delegate { button.Text = $"{count++} clicks!"; };

            FindViewById<TextView>(Resource.Id.viewplayerfullsongname).Selected = true;

            this.playerTimer = new System.Timers.Timer(1000);
            this.playerTimer.Elapsed += PlayerTimerHandleElapsed;
            this.playerTimer.Start();

            this.time = FindViewById<TextView>(Resource.Id.time);
            this.viewplayerProgressBar = FindViewById<ProgressBar>(Resource.Id.viewplayerProgressBar);
            this.viewplayerProgressBar.Max = 10;

        }

        private void PlayerTimerHandleElapsed(object sender, System.Timers.ElapsedEventArgs e)
        {

                this.viewplayerProgressBar.IncrementProgressBy(1);
                count++;
                if (count > 100)
                {
                    count = 0;
                }

            RunOnUiThread(() =>
            {
                this.time.Text = "time: " + count;

            }
            );
        }

我认为问题是关于进度条和TextView的更新名为&#34; time&#34;使用RunOnUiThred。但如果我不这样做,那些组件的数据就不会刷新。 有人有一些解决方案吗? 感谢。

1 个答案:

答案 0 :(得分:0)

  

每次计时器执行Elapsed事件时,TextView的文本都会返回到开始位置

以下是您的time布局:

<TextView
    android:id="@+id/time"
    android:textColor="@android:color/background_dark" 
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    ...
    />

解决方案:

将布局参数android:layout_width"wrap_content"更改为固定宽度,例如"fill_parent""100dp"

Effect

分析:

问题在于,每次更新时间TextView文字时,TextView都会使整个布局无效。

以下是Source code

/**
 * Check whether entirely new text requires a new view layout
 * or merely a new text layout.
 */

private void checkForRelayout() {
    // If we have a fixed width, we can just swap in a new text layout
    // if the text height stays the same or if the view height is fixed.

    if ((mLayoutParams.width != LayoutParams.WRAP_CONTENT ||
            (mMaxWidthMode == mMinWidthMode && mMaxWidth == mMinWidth)) &&
            (mHint == null || mHintLayout != null) &&
            (mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight() > 0)) {
        // Static width, so try making a new text layout.

        int oldht = mLayout.getHeight();
        int want = mLayout.getWidth();
        int hintWant = mHintLayout == null ? 0 : mHintLayout.getWidth();

        /*
         * No need to bring the text into view, since the size is not
         * changing (unless we do the requestLayout(), in which case it
         * will happen at measure).
         */
        makeNewLayout(want, hintWant, UNKNOWN_BORING, UNKNOWN_BORING,
                      mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(),
                      false);

        if (mEllipsize != TextUtils.TruncateAt.MARQUEE) {
            // In a fixed-height view, so use our new text layout.
            if (mLayoutParams.height != LayoutParams.WRAP_CONTENT &&
                mLayoutParams.height != LayoutParams.MATCH_PARENT) {
                invalidate();
                return;
            }

            // Dynamic height, but height has stayed the same,
            // so use our new text layout.
            if (mLayout.getHeight() == oldht &&
                (mHintLayout == null || mHintLayout.getHeight() == oldht)) {
                invalidate();
                return;
            }
        }

        // We lose: the height has changed and we have a dynamic height.
        // Request a new view layout using our new text layout.
        requestLayout();
        invalidate();
    } else {
        // Dynamic width, so we have no choice but to request a new
        // view layout with a new text layout.

        nullLayouts();
        requestLayout();
        invalidate();
    }
}