I am getting images using the Html.fromHtml() method. So I am using URLImageParser and URLDrawable classes as defined here: Android HTML ImageGetter as AsyncTask.
I have adapted two methods from URLImageParser in order to scale the image to the width of the screen whilst maintaining the aspect ratio. The changed methods are as follows:
#Override
protected void onPostExecute(Drawable result) {
DisplayMetrics dm = new DisplayMetrics();
((WindowManager) c.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = width * container.getHeight() / container.getWidth();
urlDrawable.setBounds(0, 0, 0+width, 0+height);
// change the reference of the current drawable to the result
// from the HTTP call
urlDrawable.drawable = result;
// redraw the image by invalidating the container
URLImageParser.this.container.invalidate();
// For ICS
URLImageParser.this.container.setHeight((URLImageParser.this.container.getHeight()
+ height));
// Pre ICS
URLImageParser.this.container.setEllipsize(null);
}
and
public Drawable fetchDrawable(String urlString) {
try {
InputStream is = fetch(urlString);
Drawable drawable = Drawable.createFromStream(is, "src");
DisplayMetrics dm = new DisplayMetrics();
((WindowManager) c.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = width * container.getHeight() / container.getWidth();
drawable.setBounds(0, 0, 0 + width, 0
+ height);
return drawable;
} catch (Exception e) {
return null;
}
}
My problem is that when the phone is held in portrait orientation the image looks fine. However when I rotate the phone the width of the image goes to the new width of the phone, however the height does not change so the image looks distorted.
Is there a way to reset the height when the phone is rotated?
Pretty sure this is a silly mistake somewhere
To detect a screen rotation, you can try something like this:
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Checks the orientation of the screen
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
}
}
See more.
Here is another great example.
Related
Hello I want to ask about the most efficient way to adjust layout in all devices mobile and tablets sometimes I can't use wrap_content and layout_weight
I set size in some percentage to the device size in java like this:
ImageView img;
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
img.getLayoutParams().width = width* 7 / 10;
and when rotating screen I use this method to change percentage
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE&& getResources().getBoolean(R.bool.isTablet)) {
width=(int) (width * 0.7);
}
I am asking If this procedure is more efficient than using multi XML files for each screen size / orientation
Actually it depends on the scenario. Sometimes maintaining xml is efficient and easy sometimes dynamic calculation is necessary. You can go through the link https://developer.android.com/guide/practices/screens_support.html . It will give you some ideas. In your above code for width/height calculation sometimes you may not get proper result for some devices. Below is the code that will support all version of android device Resolution(Width, Height) accurately at runtime.
private void calculateDeviceResolution(Activity context) {
Display display = context.getWindowManager().getDefaultDisplay();
if (Build.VERSION.SDK_INT >= 17) {
//new pleasant way to get real metrics
DisplayMetrics realMetrics = new DisplayMetrics();
display.getRealMetrics(realMetrics);
realWidth = realMetrics.widthPixels;
realHeight = realMetrics.heightPixels;
} else if (Build.VERSION.SDK_INT >= 14) {
//reflection for this weird in-between time
try {
Method mGetRawH = Display.class.getMethod("getRawHeight");
Method mGetRawW = Display.class.getMethod("getRawWidth");
realWidth = (Integer) mGetRawW.invoke(display);
realHeight = (Integer) mGetRawH.invoke(display);
} catch (Exception e) {
//this may not be 100% accurate, but it's all we've got
realWidth = display.getWidth();
realHeight = display.getHeight();
Constants.errorLog("Display Info", "Couldn't use reflection to get the real display metrics.");
}
} else {
//This should be close, as lower API devices should not have window navigation bars
realWidth = display.getWidth();
realHeight = display.getHeight();
}
}
How can I calculate the screen size exactly under the consideration of Edge part?
Now, I'm developing custom keyboard and when it becomes visible, its size is calculated programmatically based on screen size.
What function I used calculate the screen size is like following.
public static Point getDimentionalSize(Context context)
{
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int realWidth;
int realHeight;
if (Build.VERSION.SDK_INT >= 17){
//new pleasant way to get real metrics
DisplayMetrics realMetrics = new DisplayMetrics();
display.getRealMetrics(realMetrics);
realWidth = realMetrics.widthPixels;
realHeight = realMetrics.heightPixels;
} else if (Build.VERSION.SDK_INT >= 14) {
//reflection for this weird in-between time
try {
Method mGetRawH = Display.class.getMethod("getRawHeight");
Method mGetRawW = Display.class.getMethod("getRawWidth");
realWidth = (Integer) mGetRawW.invoke(display);
realHeight = (Integer) mGetRawH.invoke(display);
} catch (Exception e) {
//this may not be 100% accurate, but it's all we've got
realWidth = display.getWidth();
realHeight = display.getHeight();
Log.e("Display Info", "Couldn't use reflection to get the real display metrics.");
}
} else {
//This should be close, as lower API devices should not have window navigation bars
realWidth = display.getWidth();
realHeight = display.getHeight();
}
return new Point(realWidth, realHeight);
}
This function calculates screen size exactly in terms of pixels.
But when I try it on Samsung Galaxy Note Edge, the resulted screen width composes device's Edge part also.
I'd like to exclude it from screen size. (if portrait, from width, otherwise, from height)
What's the solution?
You can try this
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int height = displaymetrics.heightPixels;
int width = displaymetrics.widthPixels;
I am trying to set my image as wallpaper but it gets zoomed/cropped when set as wallpaper. I have tried almost everything but nothing works.
Here is my piece of code:
public void setAswallpaper(Bitmap wallpaper)
{
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
System.out.println("screen dimensions "+width+" "+height);
System.out.println("wallpaper dimensions "+wallpaper.getWidth()+" "+wallpaper.getHeight());
wallpaper = Bitmap.createScaledBitmap(wallpaper, width*2 , height, true);
try {
WallpaperManager wallpaperManager=WallpaperManager.getInstance(context);
wallpaperManager.suggestDesiredDimensions(width,height);
System.out.println("wallpaper manager dimensions "+wallpaperManager.getDesiredMinimumWidth()+" "+wallpaperManager.getDesiredMinimumHeight());
wallpaperManager.setBitmap(wallpaper); }
}
catch (IOException e)
{
e.printStackTrace();
Toast.makeText(context,
"Wallpaper Not Set",
Toast.LENGTH_SHORT).show();}
}
I need help so that I can set my complete image as wallpaper
My image size is : 640*960
bitmap size is : 1960*2880
screen dimensions : 1080*1960
I am having a dynamic layout where there is a imagebutton named ButtonQ.
I would like to set the dimension of the ButtonQ and then to see if it is correct, I have added a toast.
#Override
protected void onStart()
{
super.onStart();
measure_dimension();
}
private static Point getDisplaySize(final Display display)
{
final Point point = new Point();
try {
display.getSize(point);
} catch (java.lang.NoSuchMethodError ignore) { // Older device
point.x = display.getWidth();
point.y = display.getHeight();
}
return point;
}
public void measure_dimension()
{
Display display = getWindowManager().getDefaultDisplay();
Point size = getDisplaySize(display);
int screen_width = size.x;
int screen_height = size.y;
int target_height = Math.min(screen_height, 600);
int target_width = Math.min(screen_width, 600);
int target_dimension = Math.min(target_height, target_width);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(target_dimension, target_dimension); // width, height
buttonQ.setLayoutParams(layoutParams);
image_height = target_height;
image_width = target_width;
Toast.makeText(Game_middle.this, "buttonQ height:"+ buttonQ.getHeight() +"\nbuttonQ width=" + buttonQ.getWidth(), Toast.LENGTH_LONG).show();
}
Question:
The toast reports the height and the width of ButtonQ are both 0.
Why?
I'd use the analogue way you're setting your height and width: via getLayoutParams(). If you want to set the params dynamically, I wouldn't use pixels directly but the dp unit, using TypedValue.COMPLEX_UNIT_DIP.
Regarding to synchronization, in that example I'd definitely use asynchronous mechanisms, such as CountDownLatch or Semaphore mechanisms. It's quite more secure this way than using temporary timers. You may want to check the CountDownLatch(1) example in the reference page for that purpose.
Try this to get the button dimensions where popLayout is the button name in your case
popupLayout.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
width = popupLayout.getMeasuredWidth();
height = popupLayout.getMeasuredHeight();
Lots been said, written, vented out ;) on this already, I know. But my question is a bit different. I realize that there is issue with using large bitmap objects in Android. In my Android App, I need to use large bitmaps in various places. cannot help it. I tried various things listed in stackoverflow. One that I want to try but not able to is to avoid using ARBG_8888. The App crashes exactly at that line many times. I have an ImageView where I load an initial large bitmap. Then the user can make some markings in the bitmap and then I need to save the whole image (i.e. the original bitmap + the user's markings). Am trying this with this code I got from stackoverflow:
public static Bitmap loadBitmapFromView(Context context, View view) {
Log.d(logtag, "loadBitmapFromView");
Bitmap bitmap;
BitmapFactory.Options options = new BitmapFactory.Options();
// These help in saving/recycling the bitmap memory
options.inPurgeable = true;
options.inInputShareable = true;
Bitmap dummy = null;
try {
dummy = BitmapFactory.decodeStream(context.getAssets().open("icon_add.png"), new Rect(-1,-1,-1,-1), options);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
bitmap = Bitmap.createBitmap(view.getLayoutParams().width,
view.getLayoutParams().height, Bitmap.Config.ARGB_8888);
// bitmap = Bitmap.createScaledBitmap( dummy, view.getLayoutParams().width,
// view.getLayoutParams().height, false);
Canvas c = new Canvas(bitmap);
view.layout(0, 0, view.getLayoutParams().width, view.getLayoutParams().height);
view.draw(c);
Log.d(logtag, "loadBitmapFromView: width:" + view.getLayoutParams().width);
c = null;
return bitmap;
}
How do I avoid using ARGB_8888 in the above code? Can someone please help?
I removed it from many other places in the code, but, in the above snippet, am left in vain.
I tried using an initial dummy object (you can see the object 'dummy' in the above code) to create a scaled bitmap object ( with createScaledBitmap() which necessarily asks for a source bitmap ) and then tried to load the canvas, but the generated image is having only the dummy object (icon_add.png) and not the one from the imageview.
you can show image in device specific height width....then you don't get out of memory for imagesize.
this is code:
#SuppressLint("NewApi")
public static int getDeviceWidth(Activity activity) {
int deviceWidth = 0;
Point size = new Point();
WindowManager windowManager = activity.getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
windowManager.getDefaultDisplay().getSize(size);
deviceWidth = size.x;
} else {
Display display = windowManager.getDefaultDisplay();
deviceWidth = display.getWidth();
}
return deviceWidth;
}
#SuppressLint("NewApi")
public static int getDeviceHeight(Activity activity) {
int deviceHeight = 0;
Point size = new Point();
WindowManager windowManager = activity.getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
windowManager.getDefaultDisplay().getSize(size);
deviceHeight = size.y;
} else {
Display display = windowManager.getDefaultDisplay();
deviceHeight = display.getHeight();
}
return deviceHeight;
}
you can use device height and width..and set this image in imageview..
ImageView image = new ImageView(viewHomeScreen);
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.FILL_PARENT,
FrameLayout.LayoutParams.FILL_PARENT);
params.height = getDeviceHeight(activity);
params.width = getDevicewidth(activity);
FrameLayout framelayout = new FrameLayout(viewHomeScreen);
framelayout.addView(image, 0, params);
i hope if you use device specific height and width then your image memory issue will be solved.