ঘোরানো পাঠ্য উইজেট প্রদর্শন করতে আমি https://github.com/mdg-iitr/RotatingText এর নিজস্ব সংস্করণটি ব্যবহার করছি । আপনাকে অ্যানিমেশনটি দেখার অনুমতি দেয় এই গিটহাবে একটি ভিডিও উপলব্ধ। শব্দের সারি সেট আপ করার ধারণা। সারিগুলির পরে সারি সারি দেখানো হয়। পুরো সারিটি ঘোরে (তাই এর শব্দগুলি করুন)। পরের সারির ঘূর্ণন অ্যানিমেশন শেষ হয়ে গেলে পূর্ববর্তী সারির পরে একটি সারি দেখানো হয়।
আমার সমস্যা
আমি DynamicLayout
পাঠ্যের সারিগুলি দেখানোর জন্য একটি ব্যবহার করি । মনে রাখবেন: সারিগুলি অবশ্যই ঘোরানো হবে।
আমার সমস্যাটি হ'ল: স্পষ্টতই, আমি পদ্ধতিটি ব্যবহার করতে পারি না canvas.drawTextOnPath(dynamicLayoutObject)
। তাই আমি কি হল: dynamicLayoutObjec.draw(canvas);
। কিন্তু তখন কোনও অ্যানিমেশন নেই। প্রকৃতপক্ষে, পাঠ্যটি (সুতরাং এটি DynamicLayout
এতে রয়েছে) অবশ্যই ঘোরানো উচিত।
প্রত্যাশিত ফলাফল
DynamicLayout
(আসলে, তার পাঠ্য) অ্যানিমেটেড করা আবশ্যক (ক ঘূর্ণন)। এই এসও প্রশ্নের ( https://github.com/mdg-iitr/RotatingText ) শুরুতে প্রদত্ত গিথুব মূল রেপোর চিত্রটিতে ঘূর্ণনটি পাওয়া যাবে ।
আমার প্রশ্ন
আমার DynamicLayout
(এবং / অথবা এর পাঠ্য) কীভাবে আমার পথে ঘোরানো যায় তা আমি জানি না ।
ন্যূনতম এবং পরীক্ষামূলক উদাহরণ
আমি প্রায় 8 মাস আগে আসল রোটিংটেক্সট লাইব্রেরিটি পরিবর্তন করেছি। এটি সহজ করার জন্য (কম ক্লাস, কম পদ্ধতি, অব্যবহৃত পদ্ধতি ইত্যাদি)। আসলে, আমার কেবল দুটি ক্লাস রয়েছে:
RotatingTextSwitcher
যা এক্সএমএল উইজেটএবং
Rotatable
, যা ঘোরানোর জন্য স্ট্রিংগুলির অ্যারে ধারণ করে।RotatingTextSwitcher
এটি পরীক্ষার জন্য এক্সএমএল উইজেটযুক্ত একটি .XML লেআউটএকজন
Fragment
, পূর্বে mentionned বিন্যাস বৃদ্ধি প্রতিটি আবর্তিত সারি শব্দের স্থাপনের, এবং তাদের দেখাচ্ছে।
এটি পরীক্ষা করতে, নীচে প্রদত্ত খণ্ডগুলি দেখিয়ে এমন একটি ক্রিয়াকলাপ তৈরি করুন, যা উপরে উপস্থাপিত অন্য উত্সগুলি ব্যবহার করে।
ঘূর্ণনযোগ্য ক্লাস
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; }
}
টেক্সটসুইচার ক্লাস ঘোরানো
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));
}
}
DynamicLayout
। সুতরাং, এখন আমি এটি ব্যবহার করি ... তবে আমি এটিকে পথের সাথে ঘোরাইতে পারি না। আমি প্রশ্নটি সম্পাদনা করেছি। অনুগ্রহ এখনও উপলব্ধ :-)।