I tried setting height/width manually in button but it didn't work. Then implemented Layoutparams. But size shows small and not getting required dp value.
XML
<Button
android:id="#+id/itemButton"
android:layout_width="88dp"
android:layout_height="88dp"
android:layout_marginRight="5dp"
android:layout_marginBottom="5dp"
android:background="#5e5789"
android:gravity="bottom"
android:padding="10dp"
android:text=""
android:textColor="#FFF"
android:textSize="10sp" />
Constructor:
public Item (int id, String name, String backgroundColor, String textColor, int width, int height){
this.id = id;
this.name = name;
this.backgroundColor = backgroundColor;
this.textColor = textColor;
this.width = width;
this.height = height;
}
Adapter:
#Override public void onBindViewHolder(final ViewHolder holder, int position) {
final Item item = items.get(position);
holder.itemView.setTag(item);
holder.itemButton.setText(item.getName());
holder.itemButton.setTextColor(Color.parseColor(item.getTextColor()));
holder.itemButton.setBackgroundColor(Color.parseColor(item.getBackgroundColor()));
ViewGroup.LayoutParams params = holder.itemButton.getLayoutParams();
params.width = item.getWidth();
params.height = item.getHeight();
holder.itemButton.setLayoutParams(params);
}
When you specify values programmatically in the LayoutParams, those values are expected to be pixels.
To convert between pixels and dp you have to multiply by the current density factor. That value is in the DisplayMetrics, that you can access from a Context:
float pixels = dp * context.getResources().getDisplayMetrics().density;
So in your case you could do:
.
.
float factor = holder.itemView.getContext().getResources().getDisplayMetrics().density;
params.width = (int)(item.getWidth() * factor);
params.height = (int)(item.getHeight() * factor);
.
.
I believe you should be using a dp value defined in dimens along with getDimensionPixelSize. In a custom view, the Kotlin implementation would look like:
val layoutParams = layoutParams
val width = context.resources.getDimensionPixelSize(R.dimen.width_in_dp)
layoutParams.width = width
Option 1: Use dimens.xml
view.updateLayoutParams {
width = resources.getDimensionPixelSize(R.dimen.my_width)
height = resources.getDimensionPixelSize(R.dimen.my_height)
}
Option 2: Dispense with dimens.xml
/** Converts dp to pixel. */
val Int.px get() = (this * Resources.getSystem().displayMetrics.density).toInt()
view.updateLayoutParams {
width = 100.px
height = 100.px
}
ViewGroup.LayoutParams params = ListView.getLayoutParams();
params.height = (int) (50 * customsDebts.size() * (getResources().getDisplayMetrics().density));
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
ListView.setLayoutParams(params);
Related
I have an image loading from a url using Glide, with the image I'm getting the image height. WHen I set the height, and width to match parent, the height is too high and there is empty space on bottom and top of image. The height is in pixels
This is how I'm setting height:
if (height != 0) {
height = convertPixelsToDp(height, mContext);
ViewGroup.LayoutParams params = viewHolder.listphoto.getLayoutParams();
params.height = height;
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
viewHolder.listphoto.setLayoutParams(params);
}
XML:
<ImageView
android:id="#+id/listphoto"
android:adjustViewBounds="true"
android:layout_width="match_parent"
android:background="#dddddd"
android:layout_height="wrap_content"
android:scaleType="fitCenter"
/>
I tried experimenting with adjustViewBounds and scaleType but nothing is working. It's not wrapping the top and bottom. How can I make this work?
I've been working on this all night
UPDATE:
public static float convertPixelsToDp(float px, Context context){
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
return dp;
}
Okay. So, the answer is very simple. We just need to change the height of the ImageView with respect to the width of the image and the width of the screen. Doing this will set the image properly in the ImageView:
private float getHeight(float height, float width) {
Display display = ((Activity) context).getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return (height * size.x / width);
}
If your ImageView has some margin or padding set to it, use this instead:
private float getHeight(float height, float width, int containerHeight) {
return (height * containerHeight / width);
}
Then finally,
if (height != 0) {
height = (int) getHeight(height, width);
//or if has some margin or padding
ViewGroup.LayoutParams params = viewHolder.listphoto.getLayoutParams();
params.height = height;
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
viewHolder.listphoto.setLayoutParams(params);
}
Or if has padding or margin:
if (height != 0) {
height = (int) getHeight(height, width, viewHolder.listphoto.getMeasuredWidth());
ViewGroup.LayoutParams params = viewHolder.listphoto.getLayoutParams();
params.height = height;
params.width = ViewGroup.LayoutParams.MATCH_PARENT;
viewHolder.listphoto.setLayoutParams(params);
}
Note: It will be a better if you go with the second one. It will ensure that even when you apply some margin/padding to your ImageView, the image sets properly in the ImageView ignoring the padding/margin.
add these attributes
android:adjustViewBounds="true"
android:cropToPadding="false"
android:scaleType="fitXY"
android:scaleType="fitXY"
android:adjustViewBounds="true"
I think these two property will resolve the problem and please remove
android:scaleType="fitCenter"
Change width to
android:layout_width="wrap_content"
android:adjustViewBounds="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
This will work for you without giving scaleType.
I am developing Android v2.2 app.
I have a Fragment. In the onCreateView(...) callback of my fragment class, I inflate an layout to the fragment like below:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.login, null);
return view;
}
The above inflated layout file is (login.xml):
<?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="Username" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Username" />
</LinearLayout>
I would like to set a paddingTop to the above <LinearLayout> element , and I want to do it in the Java code instead of do it in xml.
How to set paddingTop to <LinearLayout> in my fragment Java class code ??
view.setPadding(0,padding,0,0);
This will set the top padding to padding-pixels.
If you want to set it in dp instead, you can do a conversion:
float scale = getResources().getDisplayMetrics().density;
int dpAsPixels = (int) (sizeInDp*scale + 0.5f);
To answer your second question:
view.setPadding(0,padding,0,0);
like SpK and Jave suggested, will set the padding in pixels. You can set it in dp by calculating the dp value as follows:
int paddingDp = 25;
float density = context.getResources().getDisplayMetrics().density
int paddingPixel = (int)(paddingDp * density);
view.setPadding(0,paddingPixel,0,0);
If you store the padding in resource files, you can simply call
int padding = getResources().getDimensionPixelOffset(R.dimen.padding);
It does the conversion for you.
Using Kotlin and the android-ktx library, you can simply do
view.updatePadding(top = 42)
See docs here
You can set padding to your view by pro grammatically throughout below code -
view.setPadding(0,1,20,3);
And, also there are different type of padding available -
Padding
PaddingBottom
PaddingLeft
PaddingRight
PaddingTop
These, links will refer Android Developers site. Hope this helps you lot.
Using TypedValue is a much cleaner way of converting to pixels compared to manually calculating:
float paddingDp = 10f;
// Convert to pixels
int paddingPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, paddingDp, context.getResources().getDisplayMetrics());
view.setPadding(paddingPx, paddingPx, paddingPx, paddingPx);
Essentially, TypedValue.applyDimension converts the desired padding into pixels appropriately depending on the current device's display properties.
For more info see: TypedValue.applyDimension Docs.
Kotlin; extension function
fun Float.px(m: DisplayMetrics!): Int
get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, m).toInt()
...
val pad = 10.0f.px
use below method for setting padding dynamically
setPadding(int left, int top, int right, int bottom)
Example :
view.setPadding(2,2,2,2);
Here you can see in which section the padding is applied
bidding.subHeader.tvSubHeader.setPadding(0, 5, 0, 0);
Someone edited this answer, but I added an image that had been removed before, here it is again
Step 1: First, take the padding value as an integer.
int padding = getResources().getDimensionPixelOffset(R.dimen.padding);
or int padding = 16; [Use any method]
Step 2: Then assign the padding value to the layout.
layout.setPadding(padding, padding, padding, padding);
layout.setPadding(padding_left, padding_top, padding_right, padding_bottom);
All side different padding can be assigned. layout.setPadding(16, 10, 8, 12);
For removing padding (No Padding) set padding values as 0,
layout.setPadding(0, 0, 0, 0);
Write Following Code to set padding, it may help you.
TextView ApplyPaddingTextView = (TextView)findViewById(R.id.textView1);
final LayoutParams layoutparams = (RelativeLayout.LayoutParams) ApplyPaddingTextView.getLayoutParams();
layoutparams.setPadding(50,50,50,50);
ApplyPaddingTextView.setLayoutParams(layoutparams);
Use LinearLayout.LayoutParams or RelativeLayout.LayoutParams according to parent layout of the child view
Context contect=MainActivity.this;
TextView tview=new TextView(context);
tview.setPaddingRelative(10,0,0,0);
The best way is not to write your own funcion.
Let me explain the motivaion - please lookup the official Android source code.
In TypedValue.java we have:
public static int complexToDimensionPixelSize(int data,
DisplayMetrics metrics)
{
final float value = complexToFloat(data);
final float f = applyDimension(
(data>>COMPLEX_UNIT_SHIFT)&COMPLEX_UNIT_MASK,
value,
metrics);
final int res = (int) ((f >= 0) ? (f + 0.5f) : (f - 0.5f));
if (res != 0) return res;
if (value == 0) return 0;
if (value > 0) return 1;
return -1;
}
and:
public static float applyDimension(int unit, float value,
DisplayMetrics metrics)
{
switch (unit) {
case COMPLEX_UNIT_PX:
return value;
case COMPLEX_UNIT_DIP:
return value * metrics.density;
case COMPLEX_UNIT_SP:
return value * metrics.scaledDensity;
case COMPLEX_UNIT_PT:
return value * metrics.xdpi * (1.0f/72);
case COMPLEX_UNIT_IN:
return value * metrics.xdpi;
case COMPLEX_UNIT_MM:
return value * metrics.xdpi * (1.0f/25.4f);
}
return 0;
}
As you can see, DisplayMetrics metrics can differ, which means it would yield different values across Android-OS powered devices.
I strongly recommend putting your dp padding in dimen xml file and use the official Android conversions to have consistent behaviour with regard to how Android framework works.
Using Jave's solution.
public static int getResourceDimension(Context context, String name, String defType, String defPackage) {
int sizeInDp = 0;
int resourceId = context.getResources().getIdentifier(name, defType, defPackage);
if (resourceId > 0) {
sizeInDp = context.getResources().getDimensionPixelSize(resourceId);
}
float scale = context.getResources().getDisplayMetrics().density;
int dpAsPixels = (int) (sizeInDp*scale + 0.5f);
return dpAsPixels;
}
then call when needed.
int statusBarHeight = getResourceDimension(getContext(), "status_bar_height",
"dimen", "android");
statusBarHeight = (int) (statusBarHeight + getResources().getDimension(R.dimen.fragment_vertical_padding));
view.setPadding(0, statusBarHeight, 0, 0);
While padding programmatically, convert to density related values by converting pixel to Dp.
binding.appBarMain.toolbar.setOnApplyWindowInsetsListener { _, insets ->
val statusBarSize: Int =
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
insets.getInsets(WindowInsets.Type.systemBars()).top
} else {
insets.systemWindowInsetTop
}
binding.appBarMain.appBarLayout.setPadding(0, statusBarSize, 0, 0)
return#setOnApplyWindowInsetsListener insets
}
I would like to set height and width in dp for ImageView in android pragmatically.
How can I achieve this?
Set width & height with dp :
imageview.getLayoutParams().height = (int) getResources().getDimension(R.dimen.imageview_height);
imageview.getLayoutParams().width = (int) getResources().getDimension(R.dimen.imageview_width);
In your dimens.xml provide values for the keys :
<dimen name="imageview_width">50dp</dimen>
<dimen name="imageview_height">50dp</dimen>
Use display metrics to get the sale factor and then just some simple maths - example, if I want 200x150dp:
final float scale = getResources().getDisplayMetrics().density;
int dpWidthInPx = (int) (200 * scale);
int dpHeightInPx = (int) (150 * scale);
Then set the image view size:
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(dpWidthInPx, dpHeightInPx);
imageView.setLayoutParams(layoutParams);
This may be simpler and should do the trick:
ImageView im = (ImageView)findViewById(R.id.image1);
LayoutParams params = im.getLayoutParams();
params.height = getActivity().getResources().getDimensionPixelSize(R.dimen.item_height);
params.width = getActivity().getResources().getDimensionPixelSize(R.dimen.item_width);
And in your dimens.xml
<dimen name="item_height">80dp</dimen>
<dimen name="item_width">80dp</dimen>
This may help you...
ImageView im = (ImageView)findViewById(R.id.image1);
LayoutParams params = im.getLayoutParams();
params.height = 100;
params.width = 100;
at first choose a desirable dip and assign it to a var.
int dipAmount=350;
Then read the height of your ImageView.
float scale = imageview.Resource.DisplayMetrics.Density;
Convert from px to dip.
int converter =(int) (350 * scale + 0.5f);
Set the height to imageview.
imageView.LayoutParameters.Height=converter;
final float scale = getContext().getResources().getDisplayMetrics().density;
int height_ = (int) (250 * scale + 0.5f);
int width_ = (int) (250 * scale + 0.5f);
250 is in dp
ViewGroup.LayoutParams params = ImageView.getLayoutParams();
params.height = height_;
params.width = width_;
ImageView.setLayoutParams(params);
Try this:
image_view.getLayoutParams().height = 20;
image_view.getLayoutParams().width= 20;
Give me your feedback if it's acceptable. It's work for me.
I'm trying to calculate the dimension for this image, which will be downloaded from the web using this lineimgLoader.DisplayImage(url, R.drawable.thumbnail_background, image);.
The problem is that orgHeight becomes zero and you can't divide by zero. But why is this orgHeight 0?
// Add the imageview and calculate its dimensions
//assuming your layout is in a LinearLayout as its root
LinearLayout layout = (LinearLayout)findViewById(R.id.layout);
ImageView image = (ImageView)findViewById(R.id.photo);
ImageLoader imgLoader = new ImageLoader(getApplicationContext());
imgLoader.DisplayImage(url, R.drawable.thumbnail_background, image);
int newHeight = getWindowManager().getDefaultDisplay().getHeight() / 2;
int orgWidth = image.getWidth();
int orgHeight = image.getHeight();
//double check my math, this should be right, though
int newWidth = (int) Math.floor((orgWidth * newHeight) / orgHeight);
//Use RelativeLayout.LayoutParams if your parent is a RelativeLayout
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
newWidth, newHeight);
image.setLayoutParams(params);
image.setScaleType(ImageView.ScaleType.CENTER_CROP);
layout.updateViewLayout(image, params);
My imageView xml is like this:
<ImageView
android:id="#+id/photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
/>
The views aren't yet laid in the onCreate() method so their dimensions are 0. Post a Runnable from onCreate() to get the proper values:
image.post(new Runnable() {
#Override
public void run() {
int newHeight = getWindowManager().getDefaultDisplay().getHeight() / 2;
int orgWidth = image.getWidth();
int orgHeight = image.getHeight();
//double check my math, this should be right, though
int newWidth = (int) Math.floor((orgWidth * newHeight) / orgHeight);
//Use RelativeLayout.LayoutParams if your parent is a RelativeLayout
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
newWidth, newHeight);
image.setLayoutParams(params);
image.setScaleType(ImageView.ScaleType.CENTER_CROP);
layout.updateViewLayout(image, params);
}
});
You can also use the ViewTreeObserver to get the values as soon as the layout is done.
Ref - How can you tell when a layout has been drawn?
I am coding a custom view, extended from RelativeLayout, and I want to resize it programmatically, How can I do?
the custom view Class is something like:
public ActiveSlideView(Context context, AttributeSet attr){
super(context, attr);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(inflater != null){
inflater.inflate(R.layout.active_slide, this);
}
Android throws an exception if you fail to pass the height or width of a view.
Instead of creating a new LayoutParams object, use the original one, so that all other set parameters are kept. Note that the type of LayoutParams returned by getLayoutParams is that of the parent layout, not the view you are resizing.
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) someLayout.getLayoutParams();
params.height = 130;
someLayout.setLayoutParams(params);
this.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, theSizeIWant));
Problem solved!
NOTE: Be sure to use the parent Layout's LayoutParams. Mine is LinearLayout.LayoutParams!
This works for me:
ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();
In Kotlin, you can use the ktx extensions:
yourView.updateLayoutParams {
height = <YOUR_HEIGHT>
}
For what it's worth, let's say you wanted to resize the view in device independent pixels (dp): -
You need to use a method called applyDimension, that's a member of the class TypedValue to convert from dp to pixels. So if I want to set the height to 150dp (say) - then I could do this:
float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 150, getResources().getDisplayMetrics());
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) someLayout.getLayoutParams();
params.height = (int) pixels;
someLayout.setLayoutParams(params);
where the expression: getResources().getDisplayMetrics() gets the screen density/resolution
Here's a more generic version of the solution above from #herbertD :
private void resizeView(View view, int newWidth, int newHeight) {
try {
Constructor<? extends LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class);
view.setLayoutParams(ctor.newInstance(newWidth, newHeight));
} catch (Exception e) {
e.printStackTrace();
}
}
try a this one:
...
View view = inflater.inflate(R.layout.active_slide, this);
view.setMinimumWidth(200);
I used this way to increase width of custom view
customDrawingView.post(new Runnable() {
#Override
public void run() {
View view_instance = customDrawingView;
android.view.ViewGroup.LayoutParams params = view_instance
.getLayoutParams();
int newLayoutWidth = customDrawingView
.getWidth()
+ customDrawingView.getWidth();
params.width = newLayoutWidth;
view_instance.setLayoutParams(params);
screenWidthBackup = params.width;
}
});
With Kotlin and using dp unit:
myView.updateLayoutParams {
val pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 200f, context.resources.displayMetrics)
height = pixels.toInt()
}
I solved it this way.. I have basically a simple view inside xml file.
View viewname = findViewById(R.id.prod_extra);
prodExtra.getLayoutParams().height=64;
If you have only two or three condition(sizes) then you can use #Overide onMeasure like
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
And change your size for these conditions in CustomView class easily.
This is how it can be done in Kotlin:
updateLayoutParams:
val view = layoutInflater.inflate(R.layout.cell, binding.ssss, false).apply {
id = View.generateViewId()
updateLayoutParams {
height = 200
width = 400
}
}
binding.ssss.addView(view)
OR
layoutParams:
val view = layoutInflater.inflate(R.layout.cell, binding.ssss, false).apply {
id = View.generateViewId()
layoutParams.width = 200
layoutParams.height = 200
}
binding.ssss.addView(view)
if you are overriding onMeasure, don't forget to update the new sizes
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(newWidth, newHeight);
}
This is how I achieved this. In Sileria answer he/she did the following:
ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = customHeight;
layout.requestLayout();
This is correct, but it expects us to give the height in pixels, but I wanted to give the dp I want the height to be so I added:
public int convertDpToPixelInt(float dp, Context context) {
return (int) (dp * (((float) context.getResources().getDisplayMetrics().densityDpi) / 160.0f));
}
So it will look like this:
ViewGroup.LayoutParams params = layout.getLayoutParams();
params.height = convertDpToPixelInt(50, getContext());
layout.requestLayout();
This is what I did:
View myView;
myView.getLayoutParams().height = 32;
myView.getLayoutParams().width = 32;
If there is a view group that this view belongs to, you may also need to call yourViewGroup.requestLayout() for it to take effect.
fun View.setSize(width: Int, height: Int) {
updateLayoutParams {
this.width = width
this.height = height
}
}