Android Scrolling/Fading Text(滚动/褪色文本)

8fsztsew  于 11个月前  发布在  Android
关注(0)|答案(2)|浏览(124)

我正在开发一个老式的android游戏,我希望有一个“战斗结果文本窗口”,我可以在动作发生时添加文本,这样玩家就知道发生了什么。
我目前使用了textview和valueAnimator来淡出文本:

public void updateCommentary(String updatedText){

    runOnUiThread(new Runnable() {

      @Override
      public void run() {
          ValueAnimator valueAnimator = ValueAnimator.ofFloat(1f, 0f);
          valueAnimator.setDuration(5000);
          valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator animation) {
                  TextView tv = (TextView) findViewById(R.id.txtRunningCommentary);
                  tv.setText(updatedText);
                  float alpha = (float) animation.getAnimatedValue();
                  tv.setAlpha(alpha);
              }
          });
          valueAnimator.start();
      }
    });
}

字符串
这可以工作到任何更新都会进入和淡出的程度,但是如果连续快速调用,下面的文本会覆盖已经存在的内容。
我想做的是,说,5行文字,让我不断添加新的更新,这推动了以前的更新,当他们得到进一步上升,他们淡出。如果没有更新足够长的时间,有文字淡出它自己。最后,在一个完美的世界,小部件不会有一个固定的高度,但了解多少行可以容纳它,并且具有基于该用户的设备/屏幕布局的期望功能。
x1c 0d1x的数据
我曾想过用一些textview来做这件事,在函数开始时,将textview 2的内容移动到textview 1中,然后将textview 3移动到textview 2中,依此类推,最后将最新的更新添加到textview 5中-但这感觉在几点上是有限的:

  • 首先,它看起来非常笨重,操作效率低下。
  • 其次,我希望个别行可以自行淡出--所以一个冗长的更新可能会淡出第一行,同时保留剩余的文本。
  • 最后,它肯定不会在自动魔法中运行,它会缩小或扩展用户设备的行-而是总是固定在我设置的textview数量上。

我还考虑过添加一个可滚动的垂直线性布局,并向其添加新的文本视图.
有没有一个android类,我可以用某种方式来实现这一点,或者我的可怕的方式是一样好,因为它会得到?

roqulrg3

roqulrg31#

如果你只需要淡出文本,不需要额外的转换,或者缩放,我有一个小技巧给你:
创建一个从白色平滑渐变为透明的渐变背景:

bgr_shadow_白色_down.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <gradient
        android:angle="-90"
        android:endColor="@android:color/transparent"
        android:startColor="@color/white" />
</shape>

字符串
您可以创建另一个自下而上淡出的可绘制对象:

bgr_shadow_白色_up.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <gradient
        android:angle="90"
        android:endColor="@android:color/transparent"
        android:startColor="@color/white" />
</shape>


然后你可以有一个这样的布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="100dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginHorizontal="10dp"
        tools:text="@tools:sample/lorem/random" />

    <View
        android:layout_width="match_parent"
        android:layout_height="32dp"
        android:background="@drawable/bgr_shadow_white_down" />

    <View
        android:layout_width="match_parent"
        android:layout_height="32dp"
        android:layout_gravity="bottom"
        android:background="@drawable/bgr_shadow_white_up" />
</FrameLayout>


目视检查:


的数据
您将拥有一个在顶部和底部具有淡入淡出效果的TextView。现在在您的用例中,您可以:

  • 有一个单一的TextView像这样,当一个新的行被追加时,将TextView向上平移一个lineHeight,这样旧的行就向上移动,这将被我们的渐变覆盖,并将完全被白色颜色覆盖,或者当它继续向上移动时从父级剪切掉。清除所有内容,并在超时时重置动画,没有新的行被追加。
  • 有一个垂直的LinearLayout,并添加多个TextView到堆栈中,向上翻译,如上所述。超时时清除所有内容。
rsl1atfo

rsl1atfo2#

我最终在自己的代码中所做的更接近于我的确切要求,即添加文本,并在一段时间后自行淡出,以及将新文本附加到屏幕上的日志底部。
在我的布局中,我在里面添加了一个滚动视图和一个线性布局:

<ScrollView
        android:id="@+id/svCommentaryHousing"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:scrollbars="vertical"
        app:layout_constraintBottom_toTopOf="@+id/worldSurface"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">

        <LinearLayout
            android:id="@+id/llRunningCommentary"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:orientation="vertical"
            android:scrollbars="vertical"
            android:text="txtRunningCommentary"

            >

        </LinearLayout>

    </ScrollView>

字符串
然后我修改了我的原始函数,以如下方式显示文本:

@Override
public void updateCommentary(String updatedText){

    runOnUiThread(new Runnable() {

      @Override
      public void run() {

          LinearLayout llRunningCommentary = (LinearLayout) findViewById(R.id.llRunningCommentary);
          TextView newComment = new TextView(getApplicationContext());
          newComment.setText(updatedText);
          newComment.setTag(10);
          llRunningCommentary.addView(newComment);

          ScrollView svCommentaryHousing = (ScrollView) findViewById(R.id.svCommentaryHousing);
          svCommentaryHousing.fullScroll(svCommentaryHousing.FOCUS_DOWN);
      }
    });
}


这将使用视图内部的标记创建一个新的文本更新,其生命周期为10个周期。我还使其每次向下滚动到最后,因此如果更新密集而快速,则始终显示最新的。
在我代码中,我已经有了一些功能,所以我连接了进程来轮询以下函数,因为它已经做了其他事情,很好地排列了输出生命周期:

@Override
public void updateJournal(){

    runOnUiThread(new Runnable() {
          @Override
          public void run() {
              LinearLayout llRunningCommentary = (LinearLayout) findViewById(R.id.llRunningCommentary);
              int viewAge=0;
              for(int index = 0; index < llRunningCommentary.getChildCount(); index++) {
                  View nextChild = llRunningCommentary.getChildAt(index);
                  viewAge=(Integer) nextChild.getTag();
                  viewAge--;
                  switch(viewAge){
                      case 4:
                          nextChild.setAlpha(0.7f);
                          break;
                      case 3:
                          nextChild.setAlpha(0.4f);
                          break;
                      case 2:
                          nextChild.setAlpha(0.2f);
                          break;
                      case 1:
                          nextChild.setAlpha(0.2f);
                          break;
                      case 0:
                          nextChild.setAlpha(0.0f);
                          break;
                  }
                  if(viewAge<=0){
                      llRunningCommentary.removeViewAt(index);
                  }
                  else{
                      nextChild.setTag(viewAge);
                  }
              }
          }
    });
}


每次调用cycle时,代码将遍历每个子视图,将剩余的cycle更新一次,然后当它们开始接近生命结束时,它会更改单个textview的不透明度以使其淡出,然后当它完全不可见时,它会完全删除视图。
这种方法的好处意味着,如果我愿意的话,我可以将一条生命周期更长的评论加载到日志中,尽管我不确定这是我最终会使用的行为,但可以选择让“重要”消息持续更长时间。
输出如下所示,无论是在新添加时,还是在发送了一些正在淡出的垃圾评论后。


的数据


相关问题