Кто-нибудь знает какой-либо эффективный метод выполнения анимации, который заключается в том, чтобы отображать текст, символ за символом? Подобно:
T
Th
Thi
это
Это я
Это
...
И так далее.
Спасибо!
Кто-нибудь знает какой-либо эффективный метод выполнения анимации, который заключается в том, чтобы отображать текст, символ за символом? Подобно:
T
Th
Thi
это
Это я
Это
...
И так далее.
Спасибо!
Это может быть не самое изящное решение, но самый простой - это, вероятно, быстрый подкласс TextView
с Handler
, который обновляет текст так часто, пока не появится полная последовательность:
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;
}
}
Затем вы можете использовать это в Activity следующим образом:
public class MyActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Typewriter writer = new Typewriter(this);
setContentView(writer);
//Add a character every 150ms
writer.setCharacterDelay(150);
writer.animateText("Sample String");
}
}
Если вы хотите, чтобы некоторые эффекты анимации добавлялись с каждой добавленной буквой, возможно, посмотрите на подклассу TextSwitcher
.
Надеюсь, что это поможет!
использовать класс Devunwired Typewriter
то в макете:
<com.example.fmm.Typewriter
android:id="@+id/typewriter"
android:layout_alignParentTop="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
в действии:
Typewriter writer = (Typewriter)findViewById(R.id.typewriter);
//Add a character every 150ms
writer.setCharacterDelay(150);
writer.animateText("Sample String");
Нет необходимости устанавливать дополнительный класс. Используйте это, здесь телевизор - это текстовое представление в вашем макете. просто позвоните
setCharacterDelay (150);
animateText ("Sample String");
private Handler mHandler = new Handler();
private Runnable characterAdder = new Runnable() {
@Override
public void run() {
tv.setText(mText.subSequence(0, mIndex++));
if(mIndex <= mText.length()) {
mHandler.postDelayed(characterAdder, mDelay);
}
}
};
public void animateText(CharSequence text) {
mText = text;
mIndex = 0;
tv.setText("");
mHandler.removeCallbacks(characterAdder);
mHandler.postDelayed(characterAdder, mDelay);
}
public void setCharacterDelay(long millis) {
mDelay = millis;
}
эта новая копия для Devunwired с макетом xml
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;
}
}
использование кода
textView = (Typewriter)findViewById(R.id.textView1);
//Add a character every 150ms
textView.setCharacterDelay(150);
textView.animateText("Sample String");
затем определите textView в classStart
Я знаю, что уже слишком поздно, но кто-то еще может приехать сюда из Google. На самом деле, мне тоже нужно что-то подобное для моего приложения, так что сделал это сам. Попробуйте Fade-In TextView, он заставляет каждого персонажа появляться с плавной альфа-анимацией. Использование также довольно просто.
В макете XML
<believe.cht.fadeintextview.TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:textColor="@android:color/black"
app:letterDuration="250"/>
В Деятельности/Фрагмент
believe.cht.fadeintextview.TextView textView = (believe.cht.fadeintextview.TextView) findViewById(R.id.textView);
textView.setLetterDuration(250); // sets letter duration programmatically
textView.isAnimating(); // returns current animation state (boolean)
textView.setText(); // sets the text with animation
Еще немного информации
Библиотека Fade-In TextView наследует свои свойства непосредственно от собственного класса TextView, что означает, что поддерживаются все собственные методы TextView. Практически нет ограничений, включая многострочную поддержку. Библиотека также имеет некоторые собственные методы и атрибуты, которые обеспечивают полный контроль над View.
Я использовал рекурсивный метод, также добавил немного задержки между словами, чтобы иметь больше человеческого восприятия. Отправьте textView как представление вместе с текстом и отправьте "1" в качестве длины для ввода с начала
private fun typingAnimation(view: TextView, text: String, length: Int) {
var delay = 100L
if(Character.isWhitespace(text.elementAt(length-1))){
delay = 600L
}
view.text = text.substring(0,length)
when (length) {
text.length -> return
else -> Handler().postDelayed({
typingAnimation(view, text, length+1 )
}, delay)
}
}
В теории это будет
string text = "hello"
string temp = "h"
iterate: temp += if (text.length > temp.length) text[temp.length]; wait
Конечно, вы будете выполнять итерацию в вашей runmethod.
Ответ Kaj в основном правильный, но я хотел немного расширить его. В принципе, по его словам, вы захотите сохранить копию полной строки, а также "строку отображения", которая содержит только ту часть строки, которая нарисована на экране. Каждый так часто вы объединяете дополнительный символ из полной строки в строку отображения и затем перерисовываете отображаемую строку.
Если вы создавали игру с использованием простой архитектуры основного цикла, вы сделали бы это в некоторой подфункции основного цикла. Вы можете убедиться, что это происходит только так часто, отслеживая дельта времени от последнего события. Я думаю, это то, о чем Кадж ссылается на "runmethod". Однако, поскольку вы ничего не упомянули об игре, я предполагаю, что это не то, что вы делаете, а приложения с Java-ориентированным Java будут использовать другой подход.
Подклассификация TimerTask и создание Timer, вы можете настроить метод конкатенации строк и перерисовки, который вызывается так часто, как вам хотелось бы. В принципе, вы переопределите метод run
TimerTask, чтобы обновить строку и перерисовать ее, как описано ранее.
Большинство представленных выше решений вызывают различные ошибки. Я думаю, что старые решения. Я наткнулся на этот плагин Android-студии, и он работает как шарм.
1. Установка AutoTypeTextView проста. Просто добавьте build.gradle
compile 'com.krsticdragan: autotypetextview: 1.1'
2. Добавьте новое пространство имен, которое вы будете использовать для добавления AutoTypeTextView и использования его тегов.
XMLNS: attv = "http://schemas.android.com/apk/res-auto"
Следовательно, ваш корневой макет должен выглядеть так:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:attv="http://schemas.android.com/apk/res-auto"
Добавьте это в свой XML файл.
<com.dragankrstic.autotypetextview.AutoTypeTextView
android:id="@+id/lblTextWithoutMistakes"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
attv:animateTextTypeWithoutMistakes="Hello World!" />
С этими тремя шагами вам хорошо идти. Вы можете проверить документацию для более подробной информации
Просто чтобы добавить к @Devunwired ответ при работе с кодом Kotlin,
Я изменил (в функции animateText): mHandler.postDelayed(mRunnable,mDelay)
до mRunnable.run()
так что мой последний класс Kotlin выглядит так:
class TextViewAnimationComponent(context: Context,attributeSet: AttributeSet?) : TextView(context,attributeSet) {
private var mHandler = Handler()
private var mText:CharSequence = ""
private var mIndex:Int = 0
private var mDelay:Long = 500
private val mRunnable = object: Runnable{
override fun run() {
text = mText.subSequence(0,mIndex++)
if(mIndex <= mText.length){
mHandler.postDelayed(this,mDelay)
}
}
}
fun animateText(mText:CharSequence){
this.mText = mText
mIndex = 0
text = ""
mHandler.removeCallbacks(mRunnable)
mRunnable.run()
// mHandler.postDelayed(mRunnable,mDelay)
}
fun setCharacterDelay(millis:Long){
mDelay = millis
}
}
Кроме того, быстрый и грязный код (все еще в Kotlin) без подклассов.
Внутренняя деятельность:
private fun animateText(mText: CharSequence, delayMillis: Long, postFunction:() -> Unit){
var mIndex = 0
val runnable = object : Runnable {
override fun run() {
// RunRunnable is a boolean flag; used in case you want to interrupt the execution
if(runRunnable) {
if (mIndex <= mText.length) {
// change textViewSwitchStateValue with your own TextView id
textViewSwitchStateValue.text = mText.subSequence(0, mIndex++)
Handler().postDelayed(this, delayMillis)
} else {
// After all the characters finished animating; Clear the TextView text and then run the postFunction
textViewSwitchStateValue.text = ""
postFunction()
}
}
}
}
runOnUiThread(runnable)
Простой пример для анимации загрузки точек: animateText("...", 400){switchStateON()}
Да, я знаю, что это было давно, но я надеюсь помочь другим с другим подходом, используя ValueAnimator
val text = "This is your sentence"
val textLength = text.length-1
val textView = findViewById<TextView>(R.id.sampleText)
ValueAnimator.ofInt(0, textLength).apply {
var _Index = -1
interpolator = LinearInterpolator()
duration = 2000
addUpdateListener { valueAnimator ->
val currentCharIndex = valueAnimator.animatedValue as Int
if (_Index != currentCharIndex) {
val currentChar = text[currentCharIndex]
textView.text = textView.text.toString().plus(currentChar.toString())
}
_Index = currentCharIndex
}
}.start()
Update
Я думаю, что более уместно, а решение выше, конечно, если вы используете RxJava
Observable.range(0, textLength)
.concatMap { Observable.just(it).delay(75, TimeUnit.MILLISECONDS) }
.map { text[it].toString() }
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { char ->
println("Item: $char")
textView.text = textView.text.toString().plus(char)
}
Вы можете использовать эту библиотеку для того же: Библиотека Android TypeWriterView
Взгляд в библиотеку:
//Create Object and refer to layout view
TypeWriterView typeWriterView=(TypeWriterView)findViewById(R.id.typeWriterView);
//Setting each character animation delay
typeWriterView.setDelay(int);
//Setting music effect On/Off
typeWriterView.setWithMusic(boolean);
//Animating Text
typeWriterView.animateText(string);
//Remove Animation. This is required to be called when you want to minimize the app while animation is going on. Call this in onPause() or onStop()
typeWriterView.removeAnimation();