In order to calulate the resize ratio, we need the expected width and height of the parent LinearLayout. BUT we cannot direct get it in onCreate() call-back method. Because when onCreate() is called, the layout not yet drawn and both getWidth() and getHeight() return 0. In the code, I display the getWidth() and getHeight() in onCreate(), onStart() and onResume() for your reference. So...how can I know when the layout is drawn? it's android.view.ViewTreeObserver.
android.view.ViewTreeObserver is used to register listeners that can be notified of global changes in the view tree. Such global events include, but are not limited to, layout of the whole tree, beginning of the drawing pass, touch mode change.... A ViewTreeObserver should never be instantiated by applications as it is provided by the views hierarchy. Refer to getViewTreeObserver() for more information.
onGlobalLayout() of ViewTreeObserver.OnGlobalLayoutListener is Callback method to be invoked when the global layout state or the visibility of views within the view tree changes.
Such that we can register our OnGlobalLayoutListener to get parent LinearLayout width and height, to perform the auto-resize.
(I also tried to do it in onPreDraw() of ViewTreeObserver.onPreDrawListener. But it seem that to be called too many times!)
Please note that inSampleSize is int value, that means we cannot get a 100% fit value. That's why I place HorizontalScrollView and ScrollView outside the ImageView, you can still scroll it. If you want a visually full-fit ImageView, simple remove HorizontalScrollView and ScrollView.
package com.AndroidResizeBigPicture; import android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import android.view.ViewTreeObserver.OnPreDrawListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; public class AndroidResizeBigPictureActivity extends Activity { TextView resizeLevel; ImageView imageView; LinearLayout imageParent; Bitmap bitmap_Source; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); resizeLevel = (TextView)findViewById(R.id.resizelevel); imageView = (ImageView)findViewById(R.id.imageview); imageParent = (LinearLayout)findViewById(R.id.imageparent); ToastInfo("onCreate"); ViewTreeObserver viewTreeObserver = imageParent.getViewTreeObserver(); viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener); //viewTreeObserver.addOnPreDrawListener(onPreDrawListener); } OnGlobalLayoutListener onGlobalLayoutListener = new OnGlobalLayoutListener(){ @Override public void onGlobalLayout() { /* * Callback method to be invoked when the global layout state * or the visibility of views within the view tree changes */ ToastInfo("onGlobalLayout"); imageView.setImageBitmap( resize(imageParent.getWidth(), imageParent.getHeight())); } }; OnPreDrawListener onPreDrawListener = new OnPreDrawListener(){ @Override public boolean onPreDraw() { /* * Callback method to be invoked when the view tree is about * to be drawn. At this point, all views in the tree have been * measured and given a frame. Clients can use this to adjust * their scroll bounds or even to request a new layout before * drawing occurs. */ ToastInfo("onPreDraw"); imageView.setImageBitmap( resize(imageParent.getWidth(), imageParent.getHeight())); return true; }}; private void ToastInfo(String caller){ Toast.makeText(getBaseContext(), caller + " - " + imageParent.getWidth() + " : " + imageParent.getHeight(), Toast.LENGTH_LONG).show(); } @Override protected void onStart() { // TODO Auto-generated method stub super.onStart(); ToastInfo("onStart"); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); ToastInfo("onResume"); } private Bitmap resize(int width, int height){ BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options(); bmpFactoryOptions.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeResource( getResources(), R.drawable.testpicture, bmpFactoryOptions); int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)height); int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)width); if (heightRatio > 1 || widthRatio > 1) { if (heightRatio > widthRatio) { bmpFactoryOptions.inSampleSize = heightRatio; resizeLevel.setText("inSampleSize= " + heightRatio); } else { bmpFactoryOptions.inSampleSize = widthRatio; resizeLevel.setText("inSampleSize= " + widthRatio); } }else{ resizeLevel.setText("inSampleSize= N/A"); } bmpFactoryOptions.inJustDecodeBounds = false; bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.testpicture, bmpFactoryOptions); return bitmap; } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <TextView android:id="@+id/resizelevel" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <LinearLayout android:id="@+id/imageparent" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <HorizontalScrollView android:layout_width="wrap_content" android:layout_height="wrap_content"> <ScrollView android:layout_width="wrap_content" android:layout_height="wrap_content"> <ImageView android:id="@+id/imageview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:scaleType="center" /> </ScrollView> </HorizontalScrollView> </LinearLayout> </LinearLayout>
Notice: You have to place your testpicture.jpg in /res/drawable/ folder.
No comments:
Post a Comment