I have an image and ImageView of width 45dp & height 45dp. If I use my phone this image looks good but on another phone image seems very small. If you use picture converter and put xhdpi xxhdpi... the picture is still small.
(I want to get the same experience in all screen size. Example, in pixel 2 width 45dp height 45dp looks very good, Nexus width 65dp height 65dp very good, Samsung tab3 100dp looks very good. How can I do this?
Sorry for my poor English.
In the Dimens package of your application under res folder, use separate dimen values like dimens-ldpi, dimens-hdpi, dimens-mdpi, dimens-xhdpi, dimens-xxhdpi, dimens-xxxhdpi.
Create a value in each file and use different values for them.
Or, you can visit this question. There's multiple solution mentioned with example.
You need to maintain the aspect ratio of image view by calculating the ratio of screen width and height .
Create a Java File , say ProportionalImageView :
public class ProportionalImageView extends ImageView {
public ProportionalImageView(Context context) {
super(context);
}
public ProportionalImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ProportionalImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Drawable d = getDrawable();
if (d != null) {
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = w * d.getIntrinsicHeight() / d.getIntrinsicWidth();
setMeasuredDimension(w, h);
}
else super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
then use this image View in your xml file :
<com.example.ProportionalImageView
android:layout_width="matchParent"
android:layout_height="wrapContent"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="#mipmap/img" />
Here , replace com.example. with your package name Hope it helps
Related
When I created an Activity to display an image, the images with the low resolutions are simply ocupting the space it needs and not just fits the screen. This is my Activity:
The XML Code of the activity is this:
<LinearLayout
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/nick"/>
</LinearLayout>
I want to the ImageView to fit the image to the screen with the ratio of the selected Image
The image in the Galary App is having a small resolution than the image that I used in my Activity ! So how is this done?
Use a different scaleType and you can make it scale up. But that can cause pixelation and other issues. Its better to use a bigger image and scale down (or two images, full sized and thumbnail) than to scale most images up.
Edit: Ok, on rereading your question, scale type isn't enough. Try using this as a custom view:
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
public class HeightScaleImageView extends ImageView {
public HeightScaleImageView(Context context) {
super(context);
}
public HeightScaleImageView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public HeightScaleImageView(Context context, AttributeSet attributeSet, int defStyle) {
super(context, attributeSet, defStyle);
}
#Override
public void setImageResource(int resId) {
super.setImageResource(resId);
requestLayout();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = 0;
int height = 0;
//Scale to parent width
width = MeasureSpec.getSize(widthMeasureSpec);
Drawable drawable = getDrawable();
if (drawable != null) {
height = width * getDrawable().getIntrinsicHeight() / getDrawable().getIntrinsicWidth();
}
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
}
}
So I needed a view to be always square and I wrote the following custom class
public class SquareView extends LinearLayoutCompat
{
public SquareView(Context context)
{
super(context);
}
public SquareView(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public SquareView(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
int height = getMeasuredHeight();
if (width > height)
{
setMeasuredDimension(width, width);
}
else
{
setMeasuredDimension(height, height);
}
}
}
However, the children of the view that are using match_parent and wrap_content are no longer behaving correctly
How do I fix this?
This is an answer to your larger problem, not a way to fix your custom view.
ConstraintLayout supports sizing children to have a certain aspect ratio. If you want a square LinearLayout, you can just put it inside a ConstraintLayout and enforce a 1:1 aspect ratio.
https://developer.android.com/training/constraint-layout/index.html#adjust-the-view-size
Set size as a ratio
You can set the view size to a ratio such as 16:9 if at least one of the view dimensions is set to "match constraints" (0dp). To enable the ratio, click Toggle Aspect Ratio Constraint (callout 1 in figure 10), and then enter the width:height ratio in the input that appears.
If both the width and height are set to match constraints, you can click Toggle Aspect Ratio Constraint to select which dimension is based on a ratio of the other. The view inspector indicates which is set as a ratio by connecting the corresponding edges with a solid line.
For example, if you set both sides to "match constraints", click Toggle Aspect Ratio Constraint twice to set the width be a ratio of the height. Now the entire size is dictated by the height of the view (which can be defined in any way) as shown in figure 11.
I've some buttons in my activity that inflate from a custom class that make the button exact square and fit them in parent depend on screen size and it work's fine :
public class MyButton extends Button {
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = width > height ? height : width;
setMeasuredDimension(size, size); // make it square
}
}
and here my inflater:
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Button newGuessButton = (Button) inflater.inflate(R.layout.my_button, currentTableRow, false);
currentView.addView(newGuessButton);
and layout.xml:
<my.package.name.MyButton
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/newButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="100"/>
and my question is how can set text size in my button to change the default size if I want. I think I've to set it before add it as a view but I don't know HOW?
if you just want to set text size you can use attribute
android:textSize
or use method
Button.setTextSize()
If you want to fit text inside button you can check this answer
Thank you everyone, but I found an unofficial way:As I told, my customize class (at end) make me some button that fill the parent screen, and depend on how many of it that I want to create in a row and the width size or height size of screen(we need smaller one) we can find the size nearest number to that one to will create like this:(I want to create 5 square buttons in a row )
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
Resources resources = getApplicationContext().getResources();
scale = resources.getDisplayMetrics().density;
display.getSize(size);
int width = size.x;
int tempSize = width / 5;// (5: number of buttons)
float ff = (float) ((tempSize * 0.4) / (scale));// (0.4: for example)
....
newGuessButton.setTextSize(ff);
currentView.addView(newGuessButton);
I have simply extended the ImageView so an image goes full width. Like so:..
public class BannerImageView extends ImageView {
public BannerImageView(Context context) {
super(context);
}
public BannerImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BannerImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = width * getDrawable().getIntrinsicHeight() / getDrawable().getIntrinsicWidth();
setMeasuredDimension(width, height);
}
}
In XML I have declared it as follows:
<com.whatever.next.BannerImageView
android:id="#+id/banner"
android:src="#+drawable/logo"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
I receive the following errors:
main.xml: Unable to resolve drawable "com.android.layoutlib.bridge.ResourceValue#48537a0f" in attribute "src"
then I get the expected null pointer exceptions.
I am confused as I thought since I am not altering the default behaviour of the ImageView it would show in the graphical layout. I have read through the other similar questions and that confused me some more.
For the record the above code works fine on an actual device.
Any help is appreciated!
instead of
android:src="#+drawable/logo"
use
android:src="#drawable/logo"
No + for the src attribute
So after tons of frustrations with trying to stretch my image properly to width I realise my real problem is that setImageResource acts different from setImageDrawable (which I'm trying to use). XML below gives me perfect width, aspect ratio stretched image with setImageResource but with setImageDrawable the image is not stretched to the width, any suggestions to how I should handle the problem? I use setImageDrawable because I get the image from the internet alternatives are welcome :)
<ImageView
android:id="#+id/item_image"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"/>
Oh and I've tryed scaletype, the one giving best results was centercrop but it crops which isn't desired.
This issue is really stale but in case anyone comes across it, the problem has to do with not quite a bug, but a bad implementation decision in versions of Android prior to 18. If you target 18+ you probably won't see this issue. However I'm currently targeting enterprise owned tablets at 16.
The solution is to create a superclass of ImageView that overrides onMeasure to enforce the aspect ratio:
class MyImageView extends ImageView {
public MyImageView(Context context) {
super(context);
}
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
float iwidth = (float) View.MeasureSpec.getSize(widthMeasureSpec);
float swidth = (float) getDrawable().getIntrinsicWidth();
float sheight = (float) getDrawable().getIntrinsicHeight();
float iheight = sheight / swidth * iwidth;
setMeasuredDimension((int)iwidth, (int)iheight);
}
}
In your layout:
<com.mypackage.MyImageView layout_width="match_parent" etc... />
If you target Android 18+ adjustViewBounds should work as expected.
you just make change in xml ImageView
android:layout_width="fill_parent"
android:layout_hight="fill_parent"
One fix I've found is to use a bitmap as setImageBitmap apparently works similar to setImageResource. I'm still open to other suggestions.
Your image view's width is fill_parent so if your image's width is not enough then it will be stretched.If you dont want to use fill_parent just replace the width "wrap_content".
<ImageView
android:id="#+id/item_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"/>