40 -اندرويد : تكبير ال View

 

ملاحظة : الموضوع عبارة عن حلقة من حلقات سلسلة برمجة وتطوير اندرويد Android Development

اندرويد : تكبير ال View

السلام عليكم ورحمة الله وبركاته

سوف نتعلم ضمن هذا الدرس الامور التالية :

  1. إنشاء views
  2. إعداد التحريك الخاص بالتكبير Set up the Zoom Animation
  3. تكبير ال View

بالامكان تحميل المثال من الرابط التالي :

Download the sample app

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

في  مايلي ادناه , صورة توضع كيفية توسع الصورة بعد النقر على النسخة المصغرة منها لتملأ الشاشة:

 

zomming a view

لتحميل المثال انقر هنا

في حال رغبتم بالانتقال بسرعة للمثال الكامل , بإمكانكم تحميله من الرابط التالي : , حيث نجد عدد من الملفات , ولكن فيما يخص درس اليوم , يهمنا منها الملفات التالية :

  • src/TouchHighlightImageButton.java (a simple helper class that shows a blue touch highlight when the image button is pressed)
  • src/ZoomActivity.java
  • layout/activity_zoom.xml

إنشاء ال Views

قم بإنشاء ملف تنسيق يحوي على نسخة صغيرة ونسخة كبيرة من المحتوى الذي ترغب بتكبيره.

يقوم المثال التالي بإنشاء غرض من نوع ImageButton  وذلك لنسخة مصغرة من صورة قابلة للنقر , و غرض من نوع ImageView  يقوم بعرض ال view ألمكبر من الصورة :

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp">

        <ImageButton
            android:id="@+id/thumb_button_1"
            android:layout_width="100dp"
            android:layout_height="75dp"
            android:layout_marginRight="1dp"
            android:src="@drawable/thumb1"
            android:scaleType="centerCrop"
            android:contentDescription="@string/description_image_1" />

    </LinearLayout>

    <!-- This initially-hidden ImageView will hold the expanded/zoomed version of
         the images above. Without transformations applied, it takes up the entire
         screen. To achieve the "zoom" animation, this view's bounds are animated
         from the bounds of the thumbnail button above, to its final laid-out
         bounds.
         -->

    <ImageView
        android:id="@+id/expanded_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="invisible"
        android:contentDescription="@string/description_zoom_touch_close" />

</FrameLayout>

 

إعداد التحريك الخاص بالتكبير Set up the Zoom Animation

ما إن تقوم بتطبيق تنسيقك, حتى يتوجب عليك عندها ان تهيأ معالجات الاحداث event handlers التي تقوم بقدح التحريك على شكل تكبير ال view.

يقوم المثال التالي بإضافة View.OnClickListenerإلى الغرض ImageButton  وذلك بهدف تنفيذ التحريك (التكبير) المطلوب عندما ينقر المستخدم على زر الصورة:

public class ZoomActivity extends FragmentActivity {
    // Hold a reference to the current animator,
    // so that it can be canceled mid-way.
    private Animator mCurrentAnimator;

    // The system "short" animation time duration, in milliseconds. This
    // duration is ideal for subtle animations or animations that occur
    // very frequently.
    private int mShortAnimationDuration;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_zoom);

        // Hook up clicks on the thumbnail views.

        final View thumb1View = findViewById(R.id.thumb_button_1);
        thumb1View.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                zoomImageFromThumb(thumb1View, R.drawable.image1);
            }
        });

        // Retrieve and cache the system's default "short" animation time.
        mShortAnimationDuration = getResources().getInteger(
                android.R.integer.config_shortAnimTime);
    }
    ...
}

تكبير ال View

والآن أنت بحاجة إلى التحريك والانتقال من ال view  ذو القياس والحجم العادي , إلى ال view بعد تكبيره, وذلك في الوقت المناسب.

بشكل عام, أنت بحاجة إلى ان يبدأ التحريك من الحدود الاساسية لل view ذو القياس العادي , إلى الحدود الخاصة بال view  ذو القياس المكبر.

يبين لنا التابع التالي كيفية تحقيق التحريك بحيث ينطلق من حدود الصورة المصغرة , ويكبر ليصل إلى حدود الصورة الكبيرة وذلك عبر اتباع وتنفيذ الامور التالية :

  1. قم بإسناد الصورة ذات الدقة العالية , إلى عن عنصر ImageViewالمخفي.يقوم المثال التالي بتحميل موارد الصورة الكبيرة ضمن مسرى UI thread وذلك بهدف التسهيل.
    تحتاج لان تقوم بعملية التحميل هذه ضمن مسرى مستقل وذلك لكي لا تحجب المسرى الاساسي الخاص بواجهة المستخدم , ومن ثم نقوم باعداد الصورة ضمن مسرى UI . يفضل إلا يكون حجم هذه الصورة bitmap اكبر من قياس الشاشة.
  2. حساب حدود الانطلاق والنهاية ل ImageView.
  3. تحريك كل موضع من المواضع الاربعة (وخصائص التقييس sizing properties)
    X, Y, (SCALE_X, and SCALE_Y) بنفس الوقت , انطلاقا من حدود البداية وصولا لحدود النهاية التي تم حسابها في الخطوات السابقة. يتم اضافة هذه المتحركات الاربعة إلى AnimatorSet  , وبالتالي يصبح بالامكان بدء تحريكهم في نفس الوقت.
  4. التصغير للعودة لنقطة البداية , وذلك عبر اعادة نفس التحريك السابق ولكن بشكل معاكس عندما ينقر المستخدم على الشاشة بعد تكبير الصورة.
    بالامكان القيام بذلك عبر اضافة View.OnClickListener إلى غرض ImageView. عند النقر , يقوم ImageView  بالتصاغر رجوعا إلى حجم الصورة المصغرة , ويسند قيمة الرؤية visibility للقيمة GONE, وبالتالي يختفي.
private void zoomImageFromThumb(final View thumbView, int imageResId) {
    // If there's an animation in progress, cancel it
    // immediately and proceed with this one.
    if (mCurrentAnimator != null) {
        mCurrentAnimator.cancel();
    }

    // Load the high-resolution "zoomed-in" image.
    final ImageView expandedImageView = (ImageView) findViewById(
            R.id.expanded_image);
    expandedImageView.setImageResource(imageResId);

    // Calculate the starting and ending bounds for the zoomed-in image.
    // This step involves lots of math. Yay, math.
    final Rect startBounds = new Rect();
    final Rect finalBounds = new Rect();
    final Point globalOffset = new Point();

    // The start bounds are the global visible rectangle of the thumbnail,
    // and the final bounds are the global visible rectangle of the container
    // view. Also set the container view's offset as the origin for the
    // bounds, since that's the origin for the positioning animation
    // properties (X, Y).
    thumbView.getGlobalVisibleRect(startBounds);
    findViewById(R.id.container)
            .getGlobalVisibleRect(finalBounds, globalOffset);
    startBounds.offset(-globalOffset.x, -globalOffset.y);
    finalBounds.offset(-globalOffset.x, -globalOffset.y);

    // Adjust the start bounds to be the same aspect ratio as the final
    // bounds using the "center crop" technique. This prevents undesirable
    // stretching during the animation. Also calculate the start scaling
    // factor (the end scaling factor is always 1.0).
    float startScale;
    if ((float) finalBounds.width() / finalBounds.height()
            > (float) startBounds.width() / startBounds.height()) {
        // Extend start bounds horizontally
        startScale = (float) startBounds.height() / finalBounds.height();
        float startWidth = startScale * finalBounds.width();
        float deltaWidth = (startWidth - startBounds.width()) / 2;
        startBounds.left -= deltaWidth;
        startBounds.right += deltaWidth;
    } else {
        // Extend start bounds vertically
        startScale = (float) startBounds.width() / finalBounds.width();
        float startHeight = startScale * finalBounds.height();
        float deltaHeight = (startHeight - startBounds.height()) / 2;
        startBounds.top -= deltaHeight;
        startBounds.bottom += deltaHeight;
    }

    // Hide the thumbnail and show the zoomed-in view. When the animation
    // begins, it will position the zoomed-in view in the place of the
    // thumbnail.
    thumbView.setAlpha(0f);
    expandedImageView.setVisibility(View.VISIBLE);

    // Set the pivot point for SCALE_X and SCALE_Y transformations
    // to the top-left corner of the zoomed-in view (the default
    // is the center of the view).
    expandedImageView.setPivotX(0f);
    expandedImageView.setPivotY(0f);

    // Construct and run the parallel animation of the four translation and
    // scale properties (X, Y, SCALE_X, and SCALE_Y).
    AnimatorSet set = new AnimatorSet();
    set
            .play(ObjectAnimator.ofFloat(expandedImageView, View.X,
                    startBounds.left, finalBounds.left))
            .with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
                    startBounds.top, finalBounds.top))
            .with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
            startScale, 1f)).with(ObjectAnimator.ofFloat(expandedImageView,
                    View.SCALE_Y, startScale, 1f));
    set.setDuration(mShortAnimationDuration);
    set.setInterpolator(new DecelerateInterpolator());
    set.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            mCurrentAnimator = null;
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            mCurrentAnimator = null;
        }
    });
    set.start();
    mCurrentAnimator = set;

    // Upon clicking the zoomed-in image, it should zoom back down
    // to the original bounds and show the thumbnail instead of
    // the expanded image.
    final float startScaleFinal = startScale;
    expandedImageView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (mCurrentAnimator != null) {
                mCurrentAnimator.cancel();
            }

            // Animate the four positioning/sizing properties in parallel,
            // back to their original values.
            AnimatorSet set = new AnimatorSet();
            set.play(ObjectAnimator
                        .ofFloat(expandedImageView, View.X, startBounds.left))
                        .with(ObjectAnimator
                                .ofFloat(expandedImageView, 
                                        View.Y,startBounds.top))
                        .with(ObjectAnimator
                                .ofFloat(expandedImageView, 
                                        View.SCALE_X, startScaleFinal))
                        .with(ObjectAnimator
                                .ofFloat(expandedImageView, 
                                        View.SCALE_Y, startScaleFinal));
            set.setDuration(mShortAnimationDuration);
            set.setInterpolator(new DecelerateInterpolator());
            set.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    thumbView.setAlpha(1f);
                    expandedImageView.setVisibility(View.GONE);
                    mCurrentAnimator = null;
                }

                @Override
                public void onAnimationCancel(Animator animation) {
                    thumbView.setAlpha(1f);
                    expandedImageView.setVisibility(View.GONE);
                    mCurrentAnimator = null;
                }
            });
            set.start();
            mCurrentAnimator = set;
        }
    });
}

اتمنى لكم الفائدة ,وإلى لقاء في حلقة قريبة , وإلى ذلك الحين استودعكم الله والسلام عليكم ورحمة الله وبركاته

Advertisements

, , , , , , , , , , , , , , , , , , ,

  1. أضف تعليق

اترك رد

Please log in using one of these methods to post your comment:

WordPress.com Logo

أنت تعلق بإستخدام حساب WordPress.com. تسجيل خروج   / تغيير )

صورة تويتر

أنت تعلق بإستخدام حساب Twitter. تسجيل خروج   / تغيير )

Facebook photo

أنت تعلق بإستخدام حساب Facebook. تسجيل خروج   / تغيير )

Google+ photo

أنت تعلق بإستخدام حساب Google+. تسجيل خروج   / تغيير )

Connecting to %s

%d مدونون معجبون بهذه: