问题描述 投票:8回答:1
我的问题我使用DynamicLayout显示文本行。记住:行必须旋转。我的问题是:很明显,我无法使用方法canvas.drawTextOnPath(dynamicLayoutObject)。所以我要做的是:dynamicLayoutObjec.draw(canvas);。但是那时没有任何动画。实际上,文本(因此包含它的DynamicLayout)必须旋转。

预期结果

DynamicLayout(实际上是其文本)必须设置动画(旋转)。可以在此SO问题(https://github.com/mdg-iitr/RotatingText)开头给出的Github原始存储库插图中找到旋转方式。

我的问题

我不知道如何使我的DynamicLayout(和/或其文本)沿我的路径旋转。

最小且可测试的示例

大约8个月前,我已经修改了原始的RotatingText库。为了简化它(更少的类,更少的方法,没有未使用的方法等)。确实,我只有两个班级:

RotatingTextSwitcher,它是XML小部件

    Rotatable,其中包含要旋转的字符串数组。
  1. 包含XML小部件RotatingTextSwitcher以便进行测试的.XML布局

  2. A Fragment扩大前面提到的布局,设置每个旋转行的单词,并显示它们。

  3. 为了测试它,创建一个显示下面给出的片段的活动,而该片段又使用上面给出的其他来源。

可旋转类

  • import android.graphics.Path; import android.view.animation.Interpolator; public class Rotatable { private final String[] text; private final int update_duration; private int animation_duration; private Path path_in, path_out; private int currentWordNumber; private Interpolator interpolator; public Rotatable(int update_duration, int animation_duration, Interpolator interpolator, String... text) { this.update_duration = update_duration; this.animation_duration = animation_duration; this.text = text; this.interpolator = interpolator; currentWordNumber = -1; } private int nextWordNumber() { currentWordNumber = (currentWordNumber + 1) % text.length; return currentWordNumber; } String nextWord() { return text[nextWordNumber()]; } Path getPathIn() { return path_in; } void setPathIn(Path path_in) { this.path_in = path_in; } Path getPathOut() { return path_out; } void setPathOut(Path path_out) { this.path_out = path_out; } int getUpdateDuration() { return update_duration; } int getAnimationDuration() { return animation_duration; } Interpolator getInterpolator() { return interpolator; } }

    RotatingTextSwitcher类

    package libs.rotating_text; import android.animation.ValueAnimator; import android.app.Activity; import android.content.Context; import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.text.DynamicLayout; import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.StaticLayout; import android.text.TextPaint; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; import androidx.appcompat.widget.AppCompatTextView; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; import androidx.annotation.Nullable; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.TimeUnit; public class RotatingTextSwitcher extends AppCompatTextView { Disposable disposable; private TextPaint textPaint = new TextPaint(); private String text = "", old_text = ""; SpannableStringBuilder base = new SpannableStringBuilder(text); SpannableStringBuilder base_old = new SpannableStringBuilder(old_text); private DynamicLayout layout = new DynamicLayout(base, textPaint,500, Layout.Alignment.ALIGN_CENTER,1.0F,0.0F,true); private DynamicLayout layout_old = new DynamicLayout(base_old, textPaint,500, Layout.Alignment.ALIGN_CENTER,1.0F,0.0F,true); private Rotatable rotatable; private Paint paint; private Path path_in, path_out; public RotatingTextSwitcher(Context context, @Nullable AttributeSet attrs) { super(context, attrs); paint = getPaint(); paint.setAntiAlias(true); } public void setRotatable(Rotatable rotatable) { this.rotatable = rotatable; initialize(); } private void initialize() { text = rotatable.nextWord(); base.clear(); base.append(text); old_text = text; base_old.clear(); base_old.append(old_text); setUpPath(); setDisposable(); scheduleUpdateTextTimer(); } private void setDisposable() { disposable = Observable.interval(1000 / 60, TimeUnit.MILLISECONDS, Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Consumer<Long>() { @Override public void accept(Long aLong) { invalidate(); } }); } private void setUpPath() { post(new Runnable() { @Override public void run() { path_in = new Path(); path_in.moveTo(0.0f, getHeight() - paint.getFontMetrics().bottom); path_in.lineTo(getWidth(), getHeight() - paint.getFontMetrics().bottom); rotatable.setPathIn(path_in); path_out = new Path(); path_out.moveTo(0.0f, (2 * getHeight()) - paint.getFontMetrics().bottom); path_out.lineTo(getWidth(), (2 * getHeight()) - paint.getFontMetrics().bottom); rotatable.setPathOut(path_out); } }); } private void scheduleUpdateTextTimer() { Timer update_text_timer = new Timer(); update_text_timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { ((Activity) getContext()).runOnUiThread(new Runnable() { @Override public void run() { animateInHorizontal(); animateOutHorizontal(); old_text = text; base_old.clear(); base_old.append(old_text); text = rotatable.nextWord(); base.clear(); base.append(text); } }); } }, rotatable.getUpdateDuration(), rotatable.getUpdateDuration()); } @Override protected void onDraw(Canvas canvas) { DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); float size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 32, metrics); textPaint.setTextSize(size); if (rotatable.getPathIn() != null) { layout.draw(canvas); //canvas.drawTextOnPath(text, rotatable.getPathIn(), 0.0f, 0.0f, paint); } if (rotatable.getPathOut() != null) { layout_old.draw(canvas); //canvas.drawTextOnPath(old_text, rotatable.getPathOut(), 0.0f, 0.0f, paint); } setHeight(layout.getHeight() + layout_old.getHeight()); } private void animateInHorizontal() { ValueAnimator animator = ValueAnimator.ofFloat(0.0f, getHeight()); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { path_in = new Path(); path_in.moveTo(0.0f, (Float) valueAnimator.getAnimatedValue() - paint.getFontMetrics().bottom); path_in.lineTo(getWidth(), (Float) valueAnimator.getAnimatedValue() - paint.getFontMetrics().bottom); rotatable.setPathIn(path_in); } }); animator.setInterpolator(rotatable.getInterpolator()); animator.setDuration(rotatable.getAnimationDuration()); animator.start(); } private void animateOutHorizontal() { ValueAnimator animator = ValueAnimator.ofFloat(getHeight(), getHeight() * 2.0f); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { path_out = new Path(); path_out.moveTo(0.0f, (Float) valueAnimator.getAnimatedValue() - paint.getFontMetrics().bottom); path_out.lineTo(getWidth(), (Float) valueAnimator.getAnimatedValue() - paint.getFontMetrics().bottom); rotatable.setPathOut(path_out); } }); animator.setInterpolator(rotatable.getInterpolator()); animator.setDuration(rotatable.getAnimationDuration()); animator.start(); } }

    布局
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <libs.rotating_text.RotatingTextSwitcher
            android:id="@+id/textView_presentation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="50dp"
            android:textSize="35sp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    

    片段
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.animation.AccelerateInterpolator;
    import android.widget.ImageView;
    
    import androidx.annotation.Nullable;
    import androidx.fragment.app.Fragment;
    
    import com.example.androidframework.R;
    
    import libs.rotating_text.Rotatable;
    import libs.rotating_text.RotatingTextSwitcher;
    
    public class FragmentHomeSlide extends Fragment {
    
        private View inflated;
        private int drawable_id;
        private String[] text_presentation;
    
        @Override
        public void onCreate(@Nullable final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            assert getArguments() != null;
            text_presentation = new String[];
            text_presentation[0] = "One row is set up with several words";
            text_presentation[1] = "This is another row";
        }
    
        @Override
        public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container, @Nullable final Bundle savedInstanceState) {
            inflated = inflater.inflate(R.layout.home_slide, container, false);
            setWidgets();
            return inflated;
        }
    
        private void setWidgets() {    
            final RotatingTextSwitcher rotating_presentation = inflated.findViewById(R.id.textView_presentation);
            rotating_presentation.setRotatable(new Rotatable(1000, 500, new AccelerateInterpolator(), text_presentation));
        }
    }
    

    我使用自己的https://github.com/mdg-iitr/RotatingText版本来显示旋转文本小部件。这个想法是建立单词的行。这些行逐行显示。整行...

  • android android-widget android-canvas
    1个回答
    0
    投票

    行切割器代码

    public ArrayList<String> myCutter(String s) { String trueLine = ""; ArrayList<String> result = new ArrayList<>(); if (s.length() > 20) { String[] split = s.split(" "); for (int i = 0; i < split.length; i++) { if (trueLine.length() + split[i].length() < 20) { trueLine = trueLine + " " + split[i]; } else { result.add(trueLine); trueLine = ""; } } } else { result.add(s); } return result; }

    © www.soinside.com 2019 - 2024. All rights reserved.