setsupportactionbar - toolbar android example




كيفية جعل تدوير الصورة على نحو سلس في الروبوت؟ (9)

أنا أستخدم RotateAnimation لتدوير صورة RotateAnimation دورانية مخصصة في Android. إليك ملف rotate_indefinitely.xml الذي وضعته في res/anim/ :

<?xml version="1.0" encoding="UTF-8"?>
<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:duration="1200" />    

عند تطبيق هذا على ImageView بي باستخدام AndroidUtils.loadAnimation() ، فإنه يعمل بشكل رائع!

spinner.startAnimation( 
    AnimationUtils.loadAnimation(activity, R.anim.rotate_indefinitely) );

المشكلة الوحيدة هي أن دوران الصورة يبدو أنه توقف في أعلى كل دورة.

بمعنى آخر ، تدور الصورة بمقدار 360 درجة ، وتتوقف لفترة وجيزة ، ثم تدور 360 درجة مرة أخرى ، إلخ.

وأظن أن المشكلة تكمن في أن الرسم المتحرك يستخدم interpolator افتراضيًا مثل android:iterpolator="@android:anim/accelerate_interpolator" ( AccelerateInterpolator ) ، ولكن لا أعرف كيف أخبره بعدم تقريب الرسوم المتحركة.

كيف يمكنني إيقاف الاستيفاء (إذا كانت هذه هي المشكلة بالفعل) لجعل دورة الرسوم المتحركة الخاصة بي على نحو سلس؟


أنت على حق حول AccelerateInterpolator. يجب عليك استخدام LinearInterpolator بدلاً من ذلك.

يمكنك استخدام android.R.anim.linear_interpolator المدمج في ملف XML للرسوم المتحركة مع android:interpolator="@android:anim/linear_interpolator" .

أو يمكنك إنشاء ملف الاستيفاء XML الخاص بك في مشروعك ، على سبيل المثال الاسم it res/anim/linear_interpolator.xml :

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

وأضف إلى ملف الصور المتحركة بتنسيق XML:

android:interpolator="@anim/linear_interpolator"

ملاحظة خاصة: إذا كان الرسم المتحرك الخاص بالتدوير داخل مجموعة ، فلا يبدو أن عمل interpolator يعمل. يؤدي تدوير العنصر العلوي إلى إصلاحه. (سيوفر ذلك وقتك).


إذا كنت تستخدم مجموعة متحركة مثلي ، فيجب إضافة الاستيفاء الداخلي داخل علامة المجموعة:

<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/linear_interpolator">

 <rotate
    android:duration="5000"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:startOffset="0"
    android:toDegrees="360" />

 <alpha
    android:duration="200"
    android:fromAlpha="0.7"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:toAlpha="1.0" />

</set>

هذا العمل بالنسبة لي.


تشذيب <set> -Element التي لفت <rotate> -Element يحل المشكلة!

شكرا لشالفي!

لذلك يجب أن يكون لديك Rotation_ccw.xml مستغربًا على هذا النحو:

<?xml version="1.0" encoding="utf-8"?>

<rotate
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="-360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="2000"
    android:fillAfter="false"
    android:startOffset="0"
    android:repeatCount="infinite"
    android:interpolator="@android:anim/linear_interpolator"
    />

جرب استخدام toDegrees="359" لأن 360 ° و 0 ° هما نفس الشيء.


ربما ، شيء من هذا القبيل سوف يساعد:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        imageView.animate().rotationBy(360).withEndAction(this).setDuration(3000).setInterpolator(new LinearInterpolator()).start();
    }
};

imageView.animate().rotationBy(360).withEndAction(runnable).setDuration(3000).setInterpolator(new LinearInterpolator()).start();

بالمناسبة ، يمكنك التدوير بأكثر من 360 مثل:

imageView.animate().rotationBy(10000)...

في Android ، إذا كنت ترغب في تحريك كائن وجعله يحرك كائنًا من location1 إلى location2 ، فإن واجهة برمجة تطبيقات الرسوم المتحركة تعرض المواقع المتوسطة (tweening) ثم تصطف على مؤشر الترابط الرئيسي عمليات النقل المناسبة في الأوقات المناسبة باستخدام جهاز ضبط وقت . هذا يعمل بشكل جيد باستثناء أن الخيط الرئيسي يستخدم عادة للعديد من الأشياء الأخرى - الطلاء ، فتح الملفات ، الاستجابة لمدخلات المستخدم إلخ. يمكن تأجيل جهاز ضبط الوقت في قائمة الانتظار في كثير من الأحيان. ستحاول البرامج المكتوبة بشكل جيد القيام بأكبر عدد ممكن من العمليات في الخلفية (غير الرئيسية) ، ولكن لا يمكنك دائمًا تجنب استخدام الموضوع الرئيسي. يجب دائمًا إجراء العمليات التي تتطلب منك العمل على كائن واجهة المستخدم على مؤشر الترابط الرئيسي. أيضا ، سوف العديد من واجهات برمجة التطبيقات عمليات القمع مرة أخرى إلى الموضوع الرئيسي كنوع من سلامة الصفحات.

يتم رسم جميع المشاهدات على نفس مؤشر ترابط واجهة المستخدم الرسومية والتي تستخدم أيضًا لجميع تفاعلات المستخدم.

لذلك إذا كنت بحاجة إلى تحديث واجهة المستخدم الرسومية بشكل سريع أو إذا كان العرض يستغرق الكثير من الوقت ويؤثر على تجربة المستخدم ، فيمكنك استخدام SurfaceView.

مثال على صورة التدوير:

public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    private DrawThread drawThread;

    public MySurfaceView(Context context) {
        super(context);
        getHolder().addCallback(this);
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {   
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        drawThread = new DrawThread(getHolder(), getResources());
        drawThread.setRunning(true);
        drawThread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        drawThread.setRunning(false);
        while (retry) {
            try {
                drawThread.join();
                retry = false;
            } catch (InterruptedException e) {
            }
        }
    }
}


class DrawThread extends Thread{
    private boolean runFlag = false;
    private SurfaceHolder surfaceHolder;
    private Bitmap picture;
    private Matrix matrix;
    private long prevTime;

    public DrawThread(SurfaceHolder surfaceHolder, Resources resources){
        this.surfaceHolder = surfaceHolder;

        picture = BitmapFactory.decodeResource(resources, R.drawable.icon);

        matrix = new Matrix();
        matrix.postScale(3.0f, 3.0f);
        matrix.postTranslate(100.0f, 100.0f);

        prevTime = System.currentTimeMillis();
    }

    public void setRunning(boolean run) {
        runFlag = run;
    }

    @Override
    public void run() {
        Canvas canvas;
        while (runFlag) {
            long now = System.currentTimeMillis();
            long elapsedTime = now - prevTime;
            if (elapsedTime > 30){

                prevTime = now;
                matrix.preRotate(2.0f, picture.getWidth() / 2, picture.getHeight() / 2);
            }
            canvas = null;
            try {
                canvas = surfaceHolder.lockCanvas(null);
                synchronized (surfaceHolder) {
                    canvas.drawColor(Color.BLACK);
                    canvas.drawBitmap(picture, matrix, null);
                }
            } 
            finally {
                if (canvas != null) {
                    surfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }
}

نشاط:

public class SurfaceViewActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MySurfaceView(this));
    }
}

كما ذكر hanry أعلاه وضع بطانة iterpolator على ما يرام. ولكن إذا كان التدوير داخل مجموعة يجب أن تضع android: shareInterpolator = "false" لجعله سلسًا.

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
**android:shareInterpolator="false"**
>
<rotate
    android:interpolator="@android:anim/linear_interpolator"
    android:duration="300"
    android:fillAfter="true"
    android:repeatCount="10"
    android:repeatMode="restart"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%" />
<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:duration="3000"
    android:fillAfter="true"
    android:pivotX="50%"
    android:pivotY="50%"
    android:fromXScale="1.0"
    android:fromYScale="1.0"
    android:toXScale="0"
    android:toYScale="0" />
</set>

إذا كانت Sharedinterpolator غير خاطئة ، فإن الشفرة الواردة أعلاه تعطي مواطن الخلل.


هذا يعمل بشكل جيد

<?xml version="1.0" encoding="UTF-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1600"
    android:fromDegrees="0"
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:toDegrees="358" />

لعكس التدوير:

<?xml version="1.0" encoding="UTF-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1600"
    android:fromDegrees="358"
    android:interpolator="@android:anim/linear_interpolator"
    android:pivotX="50%"
    android:pivotY="50%"
    android:repeatCount="infinite"
    android:toDegrees="0" />

ObjectAnimatior.ofFloat(view,"rotation",0,360).start();

جرب هذا.





view