Scaling ImageView to device width
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 file looks like this:
<?开发者_C百科xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical">
<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>
I tried to set the ScaleType of the ImageView but there is no ScalingType which scales the ImageView proportional. How can I scale the image proportionally to fit the whole screen in landscape mode AND portrait mode?
Basically what I want is something like ScaleType.CENTER_CORP but which also sets the proportional height for the image so I can see all of it and not just a part of the image.
Edit cause I know I'm confusing you with my "weird" questing.
I want to show it to you with a image. This is what I get at the moment with my layout. I want to fill the whole grey area by scaling the image as big as needed. How can I accomplish that?
When I set the ScaleType
to CENTER_CROP
I get this
but this is not what I want cause you are not seeing the whole image just a part from the center.
And this is what I want it to be:
I hope this helps you to understand what I'm trying to accomplish. Anyone knows how to do that?
Edit 2:
It might look weird and little confusing that I'm trying to display a image which is bigger in the height than the screen size but since I'm using a ScrollView
in my example layout this should be ok and the user could scroll if he want to see the not displayed area.
Hope this helps to understand what I'm trying to do.
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.
the easiest way is to add android:adjustViewBounds="true" to the ImageView and set the scale type to "fitCenter"
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);
}
}
}
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>
Have you tried setting it programmatically via ImageView.setScaleType()
?
setAdjustViewBounds( false )
might help as well.
Edit: sorry, I mis-read the question. Regardless, setAdjustViewBounds()
still might help. Never used it though.
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"
I don't see the images anymore and the question is old but just in case someone else finds this and has the same problem. Wouldn't it be better to just get float screenWidth = getResources().getDisplayMetrics().widthPixels
and set the ImageView LayoutParamters programmatically to scale the image to screenWidth
. Just an idea !!
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;
}
One of the ways to do it is by setting android:adjustViewBounds="true" to the ImageView and set the scale type to "fitCenter" in the xml file. This should work as expected. You can also do this programatically by setting ImageView.adjustViewBounds(true) and ImageView.setScaleType(ScaleType.FIT_CENTER).
精彩评论