如何延迟(逐字)在TextView中显示文本

3
我希望TextView中的文本能够逐词或逐字地显示,就像大多数RPG和冒险游戏中的文本框一样。一个很好的例子是游戏《逆转裁判》中的文本流(http://youtu.be/2OOX2Gv0768?t=1m7s)。
到目前为止,我尝试过以下方法:
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    String text = "test test test test";
    String[] split = text.split(" ");
    Deque<String> words = new LinkedList<String>();
    for (int i = 0; i<split.length; i++)
    {
        words.addLast(split[i]);
    }
    showNextWord(words);

}

public void showNextWord(final Deque<String> words)
{
    Handler handler = new Handler(); 
    handler.postDelayed(new Runnable() 
    { 
        public void run() 
        { 
            TextView t = (TextView) findViewById(R.id.textBox);
            t.append(words.pollFirst()+" ");
            if (words.size()>0)
                showNextWord(words);
        } 
    }, 500);
}

我在模拟器上测试了一下,发现性能很低,特别是在每个字母显示后加入延迟的情况下。延迟不稳定。
此外,希望有更优雅的解决方案。也许可以更灵活地处理延迟?例如,在句子后增加更长的延迟等。
非常感谢!

1
你的方法很好,尽量降低延迟以符合你的口味。模拟器无法给你真实的性能表现,请在真实设备上尝试。 - Nazgul
不要相信模拟器,你的代码看起来很好。 - user3455363
顺便说一下:我发现使用Genymotion和VirtualBox比默认模拟器要好得多。如果手头没有真实设备进行测试,可以试试。即使只是启动时间加速也值得一试。 - indivisible
4个回答

4
public class Typewriter extends TextView {

private CharSequence mText;
private int mIndex;
private long mDelay = 500; //Default 500ms delay


public Typewriter(Context context) {
    super(context);
}

public Typewriter(Context context, AttributeSet attrs) {
    super(context, attrs);
}

private Handler mHandler = new Handler();
private Runnable characterAdder = new Runnable() {
    @Override
    public void run() {
        setText(mText.subSequence(0, mIndex++));
        if(mIndex <= mText.length()) {
            mHandler.postDelayed(characterAdder, mDelay);
        }
    }
};

public void animateText(CharSequence text) {
    mText = text;
    mIndex = 0;

    setText("");
    mHandler.removeCallbacks(characterAdder);
    mHandler.postDelayed(characterAdder, mDelay);
}

public void setCharacterDelay(long millis) {
    mDelay = millis;
}
}

在您的活动中使用上述类,像这样:

    Typewriter writer = new Typewriter(this);
    //Add a character every 200ms
    writer.setCharacterDelay(200);
    writer.animateText("Sample String");

1

试试这个:

Handler handler = new Handler(); 
handler.postDelayed(new Runnable() 
{ 
    public void run() 
    { 
            if (words.size()>0)
            showNextWord(words);
    } 
}, 500);

public void showNextWord(words)
{
        TextView t = (TextView) findViewById(R.id.textBox);
        t.append(words.pollFirst()+" ");        
}

0

好的,这是我想出来的!

public static void main(String[] args) {
    printWord("Sup dude!", 150);
}

public static void printWord(String word, int time){
    for(int i = 0; i < word.length(); i++){
        double start = System.currentTimeMillis();
        double end = System.currentTimeMillis();
        while(end - start <= time){
            end = System.currentTimeMillis();
        }
        System.out.print(word.charAt(i));
    }
}

我打赌你可以通过将syso更改为以下内容轻松地将打印输出到你的TextView:

tv.setText(tv.getText() + word.charAt(i));

希望这回答了你的问题并有所帮助!祝你好运 :)

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接