8

这是在其他地方问过的,但该解决方案对我不起作用。所以再次摆出更多的背景。问题是一个活动包含一个滚动的音乐标题文本视图,该视图被更新的经过时间计数器文本视图中断。

我的活动布局中有这两个 TextView 小部件(尽管它们被其他布局容器包含)。

<TextView android:id="@+id/v_current_time"
   android:minWidth="26dp"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:layout_gravity="center_vertical"
   android:gravity="right|center_vertical"
   android:singleLine="true"
   android:textSize="12sp"
   android:enabled="false"
  />

<TextView android:id="@+id/v_track_title"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:textSize="18sp"
   android:textStyle="normal"
   android:singleLine="true"
   android:ellipsize="marquee"
   android:marqueeRepeatLimit="marquee_forever"
   android:scrollHorizontally="true"
   android:focusable="true"
   android:focusableInTouchMode="true"
   android:enabled="true"
/>

音乐标题被动态设置为(在测试用例中)一长行文本。如果我从不使用以下行更新当前时间的文本,那么无论我如何与暂停和播放按钮交互,音乐标​​题都会愉快地永远滚动。

tvCurrentTime.setText(DataFormat.formatTime(progress));

但是,如果我确实将文本设置为当前时间,则音乐标题将停止。按下我的暂停按钮会以某种方式重新滚动,但按下播放会导致当前时间更新并再次停止。

根据此线程中的建议,我尝试将时间文本的设置与重新启用滚动标题结合起来,如下所示:

tvCurrentTime.setText(DataFormat.formatTime(progress));
tvTitle.setEnabled(true);

除了每次重新启动时重置滚动条之外,这对失败没有影响。

是否有一些我遗漏的细节,或者关于可能出现什么问题的任何其他想法?非常感谢!

4

5 回答 5

8

还有另一种方法可以在不删除所有RelativeLayout 的情况下解决这个问题。

您可以简单地将选取框 TextView 与相对布局内的 LinearLayout 包装为容器。

于 2014-02-05T06:55:22.220 回答
7

选框是有问题的。当 TextView(或包含 TextView 的窗口)失去焦点时,选取框将停止并重置(请参阅 TextView 的来源)。我想你在这里有 3 种可能的解决方案:

  1. 您可以android:focusable="false"在布局中的所有其他视图中进行设置。这样你的 TextView 不应该失去焦点。但这可能不是您想要的解决方案。
  2. 您可以继承 TextView 并更改onFocusChanged()onWindowFocusChanged()防止选取框被停止和重置。
  3. 创建您自己的选取框实现。
于 2011-09-04T11:19:50.277 回答
2

(将上面的评论提升为答案)事实证明,上面的 TextView XML 配置工作正常,无需任何运行时更改(重置启用 = true 或其他)如果我摆脱了布局文件中的 RelativeLayout 并用 LinearLayout 替换它们。如果我不这样做,上面的建议 1 或 2(不确定 3)都不起作用。这似乎是RelativeLayout 的一个微妙而虚假的无证失败。

于 2015-03-10T00:05:44.010 回答
0

在 java 代码中,做tvTitle.setSelected(true);(这里,tvTitle 是你的滑动 TextView 变量)对我有用。这样做,似乎使它再次集中。所以工作就像一个魅力。

于 2018-05-25T07:14:48.773 回答
0

我们有一个具有多种视图类型的适配器,第一项是带有选取框 TextView 的适配器。滚动回到屏幕顶部后,没有显示文本(我们调用了 textView.isSelected == true)。

此外,问题不是 RelativeLayout,没有必要用 LinearLayout 包装 TextView,因为布局中的当前结构是:

RelativeLayout
     Button
     TextView

下面是从 TextView 开始选取框的方法:

private void startMarquee() {
    // Do not ellipsize EditText
    if (getKeyListener() != null) return;

    if (compressText(getWidth() - getCompoundPaddingLeft() - getCompoundPaddingRight())) {
        return;
    }

    if ((mMarquee == null || mMarquee.isStopped()) && (isFocused() || isSelected())
            && getLineCount() == 1 && canMarquee()) {

        if (mMarqueeFadeMode == MARQUEE_FADE_SWITCH_SHOW_ELLIPSIS) {
            mMarqueeFadeMode = MARQUEE_FADE_SWITCH_SHOW_FADE;
            final Layout tmp = mLayout;
            mLayout = mSavedMarqueeModeLayout;
            mSavedMarqueeModeLayout = tmp;
            setHorizontalFadingEdgeEnabled(true);
            requestLayout();
            invalidate();
        }

        if (mMarquee == null) mMarquee = new Marquee(this);
        mMarquee.start(mMarqueeRepeatLimit);
    }
}

它要求视图具有焦点或被选中以启动选取框。

在 TextView.onFocusChanged(...) 中调用 startStopMarquee(focused) 方法,它将触发滚动动画。我们使用这种方法遇到的问题是我们需要使用 postDelayed 来请求焦点,这可能会导致一些问题。

在检查了 TextView.setSelected(boolean) 方法在做什么之后,很清楚为什么 textView.isSelected = true 没有触发动画。它在里面检查之前的 isSelected 状态,如果新的 isSelected 状态与之前的状态不同,它将处理 startMarquee() 或 stopMarquee()。

解决方案是将选定状态更改为 false ,然后将其设置为 true,效果很好。

下面是两个方法,setSelected 和 onFocusChanged。

@Override
public void setSelected(boolean selected) {
    boolean wasSelected = isSelected();

    super.setSelected(selected);

    if (selected != wasSelected && mEllipsize == TextUtils.TruncateAt.MARQUEE) {
        if (selected) {
            startMarquee();
        } else {
            stopMarquee();
        }
    }
}

@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
    if (isTemporarilyDetached()) {
        // If we are temporarily in the detach state, then do nothing.
        super.onFocusChanged(focused, direction, previouslyFocusedRect);
        return;
    }

    if (mEditor != null) mEditor.onFocusChanged(focused, direction);

    if (focused) {
        if (mSpannable != null) {
            MetaKeyKeyListener.resetMetaState(mSpannable);
        }
    }

    startStopMarquee(focused);

    if (mTransformation != null) {
        mTransformation.onFocusChanged(this, mText, focused, direction, previouslyFocusedRect);
    }

    super.onFocusChanged(focused, direction, previouslyFocusedRect);
}
于 2021-01-12T09:51:15.743 回答