Scaling ImageView to device width

前端 未结 9 860
清酒与你
清酒与你 2020-12-05 00:54

In my Android App I have a Activity which show images which have following size 244 x 330. I want to show those images in full device width.

My layout f

相关标签:
9条回答
  • 2020-12-05 01:34

    I tried really every ScaleType in my ImageView with fill_parent and wrap_content but no of them worked. I also tried everything what I found on Google but nothing worked for me either so came up with something on my own.

    It was clear that the ImageView is not scaling my image like I wanted to be scaled so I had to scale it on my own. After scaling the bitmap I would set the new Bitmap as the image source to the ImageView. This works pretty good and looks very good on the G1 and on the Motorola Milestone 2.

    And here is all pieces of my code

    Layout:

    <ScrollView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <LinearLayout 
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:id="@+id/news_wrapper">
    
                <ImageView android:id="@+id/news_image" 
                    android:layout_height="fill_parent"
                    android:layout_width="fill_parent"
                    android:layout_marginLeft="18dip"
                    android:layout_marginRight="18dip"
                    android:background="#aaaaaa" />
    
        </LinearLayout>
    
    </ScrollView>
    

    Activity

    public class ScalingImages extends Activity {
    
        private ImageView imageView;
    
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.test_margin);
    
            this.imageView = (ImageView)findViewById(R.id.news_image);
    
            // The image is coming from resource folder but it could also 
            // load from the internet or whatever
            Drawable drawable = getResources().getDrawable(R.drawable.img);
            Bitmap bitmap = ((BitmapDrawable)drawable).getBitmap();
    
            // Get scaling factor to fit the max possible width of the ImageView
            float scalingFactor = this.getBitmapScalingFactor(bitmap);
    
            // Create a new bitmap with the scaling factor
            Bitmap newBitmap = Util.ScaleBitmap(bitmap, scalingFactor);
    
            // Set the bitmap as the ImageView source
            this.imageView.setImageBitmap(newBitmap);
        }
    
        private float getBitmapScalingFactor(Bitmap bm) {
            // Get display width from device
            int displayWidth = getWindowManager().getDefaultDisplay().getWidth();
    
            // Get margin to use it for calculating to max width of the ImageView
            LinearLayout.LayoutParams layoutParams = 
                (LinearLayout.LayoutParams)this.imageView.getLayoutParams();
            int leftMargin = layoutParams.leftMargin;
            int rightMargin = layoutParams.rightMargin;
    
            // Calculate the max width of the imageView
            int imageViewWidth = displayWidth - (leftMargin + rightMargin);
    
            // Calculate scaling factor and return it
            return ( (float) imageViewWidth / (float) bm.getWidth() );
        }
    }
    

    Util class

    public class Util {
    
        public static Bitmap ScaleBitmap(Bitmap bm, float scalingFactor) {
            int scaleHeight = (int) (bm.getHeight() * scalingFactor);
            int scaleWidth = (int) (bm.getWidth() * scalingFactor);
    
            return Bitmap.createScaledBitmap(bm, scaleWidth, scaleHeight, true);
        }
    
    }
    

    If there is an better or more accurate way to accomplish the same scaling please let me know because I can't believe that such a trivial thing is so hard to accomplish.

    I'm really hoping to see a better way to do this.

    Thank you for reading.

    0 讨论(0)
  • 2020-12-05 01:39

    manage to achieve what I wanted, which hopefully is the same as your aim:

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pgviewer);
    
        ImageView PgContainer = (ImageView)findViewById(R.id.imageView1);
    
        String Page = String.valueOf(getIntent().getExtras().getInt("Page"));
        try {
            PgContainer.setImageBitmap(getBitmapFromAsset(Page));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    
        PgContainer.setScaleType(ScaleType.FIT_CENTER);
        PgContainer.scrollTo(0, 0);
        PgContainer.setScrollBarStyle(0);
    }
    

    then to scale the bitmap:

    private Bitmap getBitmapFromAsset(String strName) throws IOException
    {
        AssetManager assetManager = getAssets();
        InputStream istr = assetManager.open(strName+".png");
        Bitmap bitmap = BitmapFactory.decodeStream(istr);
    
        float screenWidth = getResources().getDisplayMetrics().widthPixels;
        int ih=bitmap.getHeight();
        int iw=bitmap.getWidth();
        float scalefactor = screenWidth/iw;
        //w = 480, h=~
        //int newh = bitmap.getHeight()/bitmap.getWidth();
        return android.graphics.Bitmap.createScaledBitmap(bitmap, (int)(iw*scalefactor), (int)(ih*scalefactor), true);
        //return bitmap;
    }
    
    0 讨论(0)
  • 2020-12-05 01:45

    I googled everywhere and could not find a solution. Here is what I did, that worked for me and with a scroll view.

    XML file:

    <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true" >
    
        <ImageView
            android:id="@+id/manga_page_image"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:adjustViewBounds="true"
            android:scaleType="fitCenter" />
    </ScrollView>
    
    0 讨论(0)
  • 2020-12-05 01:46

    Slightly confused on what you're looking for, exactly. If you're scaling to fit the screen, you have three options, two of which are viable if you're keeping proportions. You can use ScaleType fitCenter, which will make the image fit within the bounds proportionally, or you can use centerCrop (which you said you tried), which will stretch the shortest side of the image to fit the container (meaning some will get cropped off on the longer dimension). You can't have it stretch to fit the width AND height without either cropping, or stretching disproportionately.

    EDIT: Okay, I think I get your point now. First, I'd set your LinearLayout to wrap_content for the height. Second, in code, here's one way you can do it that I can think of. There's probably also another way you could do it by first getting the screen dimensions, and then doing createScaledBitmap with the new dimensions, and then setting the background resource.

    final ImageView newsImage = (ImageView)findViewById(R.id.news_image);
    
    //get details on resolution from the display
    DisplayMetrics metrics = new DisplayMetrics();
    getWindowManager().getDefaultDisplay().getMetrics(metrics);
    
    //going to set what happens as the layout happens
    newsImage.getViewTreeObserver().addOnGlobalLayoutListener(
        new ViewTreeObserver.OnGlobalLayoutListener() {
    
            public void onGlobalLayout() {
                int oldHeight, oldWidth, newHeight, newWidth;
    
                //we want the new width to be as wide as the screen
                newWidth = metrics.widthPixels;
    
                oldHeight = newsImage.getDrawable().getIntrinsicHeight();
                oldWidth = newsImage.getDrawable().getIntrinsicWidth();
    
                //keeping the aspect ratio, the new height should be w1/h1 = w2/h2
                newHeight = Math.floor((oldHeight * newWidth) / oldWidth);
                LinearLayout.LayoutParams params = 
                    (LinearLayout.LayoutParams)newsImage.getLayoutParams();
                params.height = newHeight;
                params.width = newWidth;
                newsImage.setLayoutParams(params);
                newsImage.setScaleType(ScaleType.CENTER);
                newsImage.invalidate();
                newsImage.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-05 01:49

    the easiest way is to add android:adjustViewBounds="true" to the ImageView and set the scale type to "fitCenter"

    0 讨论(0)
  • 2020-12-05 01:51

    I want to show those images in full device width.

    This is simple. You just have the wrong margin settings. Remove these lines and your image will show in full device width:

    android:layout_marginLeft="18dip"
    android:layout_marginRight="18dip" 
    
    0 讨论(0)
提交回复
热议问题