Problem tracking: Image Display is incomplete after the scaling animation ScaleAnimation is executed in ImageView .,

Source: Internet
Author: User

Problem tracking: Image Display is incomplete after the scaling animation ScaleAnimation is executed in ImageView .,

Problem: I have a ScrollView nested with a vertical LinearLayout. Then, this LinearLayout contains multiple ImageView controls to display their own images respectively.

Then I created a scaled-up ScaleAnimation animation and set it to LinearLayout or ScrollView. Now I am listening to ScrollView to scroll the LinearLayout so that the enlarged ImageView can be fully visible.

However, when I slide through fling, I reset the Bitmap of the ImageView. Although the Bitmap is scaled up, it is reduced and not displayed completely.

Solution: At the beginning, I went to the onDraw method and draw method of ScrollView and LinearLayout to check whether any exceptions were found. (by the way, I found that LinearLayout can really set Divider like ListView. I have never found it before !), Then I went to the onDraw method of ImageView and found an mDrawable, which is the background Drawable and an mDrawMatrix. If mDrawMatrix = null, mDrawable is directly drawn, then I checked how mDrawMatrix assigned a value.

    @Override    protected boolean setFrame(int l, int t, int r, int b) {        boolean changed = super.setFrame(l, t, r, b);        mHaveFrame = true;        configureBounds();        return changed;    }    private void configureBounds() {        if (mDrawable == null || !mHaveFrame) {            return;        }        int dwidth = mDrawableWidth;        int dheight = mDrawableHeight;        int vwidth = getWidth() - mPaddingLeft - mPaddingRight;        int vheight = getHeight() - mPaddingTop - mPaddingBottom;        boolean fits = (dwidth < 0 || vwidth == dwidth) &&                       (dheight < 0 || vheight == dheight);        if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {            /* If the drawable has no intrinsic size, or we're told to                scaletofit, then we just fill our entire view.            */            mDrawable.setBounds(0, 0, vwidth, vheight);            mDrawMatrix = null;        } else {            // We need to do the scaling ourself, so have the drawable            // use its native size.            mDrawable.setBounds(0, 0, dwidth, dheight);            if (ScaleType.MATRIX == mScaleType) {                // Use the specified matrix as-is.                if (mMatrix.isIdentity()) {                    mDrawMatrix = null;                } else {                    mDrawMatrix = mMatrix;                }            } else if (fits) {                // The bitmap fits exactly, no transform needed.                mDrawMatrix = null;            } else if (ScaleType.CENTER == mScaleType) {                // Center bitmap in view, no scaling.                mDrawMatrix = mMatrix;                mDrawMatrix.setTranslate((int) ((vwidth - dwidth) * 0.5f + 0.5f),                                         (int) ((vheight - dheight) * 0.5f + 0.5f));            } else if (ScaleType.CENTER_CROP == mScaleType) {                mDrawMatrix = mMatrix;                float scale;                float dx = 0, dy = 0;                if (dwidth * vheight > vwidth * dheight) {                    scale = (float) vheight / (float) dheight;                     dx = (vwidth - dwidth * scale) * 0.5f;                } else {                    scale = (float) vwidth / (float) dwidth;                    dy = (vheight - dheight * scale) * 0.5f;                }                mDrawMatrix.setScale(scale, scale);                mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));            } else if (ScaleType.CENTER_INSIDE == mScaleType) {                mDrawMatrix = mMatrix;                float scale;                float dx;                float dy;                                if (dwidth <= vwidth && dheight <= vheight) {                    scale = 1.0f;                } else {                    scale = Math.min((float) vwidth / (float) dwidth,                            (float) vheight / (float) dheight);                }                                dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f);                dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f);                mDrawMatrix.setScale(scale, scale);                mDrawMatrix.postTranslate(dx, dy);            } else {                // Generate the required transform.                mTempSrc.set(0, 0, dwidth, dheight);                mTempDst.set(0, 0, vwidth, vheight);                                mDrawMatrix = mMatrix;                mDrawMatrix.setRectToRect(mTempSrc, mTempDst, scaleTypeToScaleToFit(mScaleType));            }        }    }

Obviously, this mDrawMatrix will operate based on the value of mScaleType, because the mScaleType in my program is ScaleType. FIT_XY, so this section is executed:

if (dwidth <= 0 || dheight <= 0 || ScaleType.FIT_XY == mScaleType) {
  mDrawable.setBounds(0, 0, vwidth, vheight);  mDrawMatrix = null;
}

This mDrawable is set to the width and height of the control.

Then I tried to find out whether the bounds was set after the control was animated. I found a method:

    /**     * Return the visible drawing bounds of your view. Fills in the output     * rectangle with the values from getScrollX(), getScrollY(),     * getWidth(), and getHeight(). These bounds do not account for any     * transformation properties currently set on the view, such as     * {@link #setScaleX(float)} or {@link #setRotation(float)}.     *     * @param outRect The (scrolled) drawing bounds of the view.     */    public void getDrawingRect(Rect outRect) {        outRect.left = mScrollX;        outRect.top = mScrollY;        outRect.right = mScrollX + (mRight - mLeft);        outRect.bottom = mScrollY + (mBottom - mTop);    }

This method returns the margin information of the drawn area of your view. One sentence (These bounds do not account for any * transformation properties currently set on the view, such as * {@ link # setScaleX (float)} or {@ link # setRotation (float )}.), it means that the bounds will not be affected by the animation. Okay... No clue...

Then I went to Google: android ImageView after ScaleAnimation draw not complete

In the last few search results,

I found: ImageView scale animation cropping (link: https://code.google.com/p/android/issues/detail? Id = 20333), the content is as follows:

Reported by halfs...@gmail.com, Sep 26, 2011I have a project that requires a fairly simple animation.There is a ImageView created this way:        <ImageView android:src="@drawable/letter3" android:clipChildren="false" android:clipToPadding="false" android:cropToPadding="false" android:id="@+id/startmessage" android:adjustViewBounds="true" android:layout_width="wrap_content" android:scaleType="fitCenter" android:layout_centerVertical="true" android:layout_centerHorizontal="true"></ImageView>As I understand it wrap_content should keep the size of the view big enough to contain the image within.Then in code I set an image and start an animation that fades out and scales up the image:final ImageView v = (ImageView)findViewById(R.id.startmessage);                fadeout.setAnimationListener(null);                v.setImageBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.letter3));                v.startAnimation(fadeout);Here is the animation code:<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"     android:interpolator="@android:anim/accelerate_interpolator"     android:shareInterpolator="true">    <alpha  android:fromAlpha = "1.0"            android:toAlpha = "0.0"            android:duration="1000"     /></set>The problem is that when the scaling animation begins the drawing rect does not seem to change so the image is cropped when it becomes larger. The problem occurs only on android 2.3.3 I believe, on device and on emulator as well. I played around with all the scaleType settings for the imageview but it didn't fix the problem.Sep 26, 2011#1 halfs...@gmail.comCorrection - this is how the animation is defined:<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"     android:interpolator="@android:anim/accelerate_interpolator"     android:shareInterpolator="true">    <alpha  android:fromAlpha = "1.0"            android:toAlpha = "0.0"            android:duration="1000"     />    <scale android:fromXScale="1.0"           android:toXScale="6.0"           android:fromYScale="1.0"           android:toYScale="6.0"           android:pivotX="50%"           android:pivotY="50%"           android:duration="1000"    /></set>Sep 26, 2011Project Member #2 romain...@android.comThe ImageView will be cropped by its parent. You need to disable children clipping on the parent and make the parent big enough.Status: DeclinedSep 27, 2011#3 halfs...@gmail.comThe parent is fullscreen and it also is set to not crop the children, also this behavior is observer only on 2.3.3, on  2.2 and lower everything is working fine.    <RelativeLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:clipChildren="false" android:clipToPadding="false" android:id="@+id/startlayout" android:visibility="invisible">        <ImageView android:layout_height="wrap_content" android:src="@drawable/letter3" android:layout_width="wrap_content" android:layout_centerVertical="true" android:layout_centerHorizontal="true" android:scaleType="fitCenter" android:id="@+id/startmessage"></ImageView>    </RelativeLayout>

 

This means that the clipChildren attribute of your parent container is set to true by default, leading to this cropping phenomenon. Now you only need to set the clipChildren attribute of ScrollView and LinearLayout to true.

For the time being, there is no problem with my Samsung i9250. In addition, it is okay for me to use the Genymotion simulator to simulate Nexus4 of 4.3. Other versions are unknown.

 

 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.