Set a view's width to be relative to device screen programmatically - java

I have a horizontal RecyclerView with child elements which I want to change the width of to be a bit less than the current match_parent set via the layout. I want to do this so that the next element in list is a bit visible on screen.
In the adapter onCreateViewHolder I am doing this:
ViewGroup.LayoutParams params = view.getLayoutParams();
params.width = MainActivity.deviceWidth - (int) MainActivity.dpToPx(40.0f);
view.setLayoutParams(params);
where MainActivity.deviceWidth is:
DisplayMetrics displaymetrics = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
deviceWidth = displaymetrics.widthPixels;
screenDensity = Resources.getSystem().getDisplayMetrics().density;
and dpToPx is this function:
public static float dpToPx(float dp) {
return (dp * screenDensity + 0.5f);
}
This works. however, I noticed that on different devices, the "margin" I am setting is not always the same. I.e. the next card in the RecyclerView is not always showing the same amount.
Is the dpToPx conversion correct? I might be missing something else in my calculation but I am not sure what.
Update
Changing:
params.width = MainActivity.deviceWidth - (int) MainActivity.dpToPx(40.0f);
To:
params.width = (int) (MainActivity.deviceWidth *0.9);
works!. I am fine with this solution. I just want to know why the previous one does not work...

Related

Android add imageview programmatically fix size all screen

I'm creating several ImageViews programmatically, but I'm running into an issue where there are different ImageView sizes on different displays.
I want the ImageView size to be fixed on all screens. Here is how I am generating those ImageViews:
for (int i = 0; i < myImageList.size(); i++) {
ImageView iv = new ImageView(this);
iv.setImageResource(myImageList.get(i));
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(420, 210);
lp.gravity = Gravity.CENTER;
iv.setLayoutParams(lp);
float angleDeg = i * 360.0f / myImageList.size() - 70.0f;
float angleRad = (float) (angleDeg * Math.PI / 180.0f);
iv.setTranslationX(320 * (float) Math.cos(angleRad));
iv.setTranslationY(320 * (float) Math.sin(angleRad));
iv.setRotation(angleDeg + 80.0f);
main.addView(iv);
final int finalI = i;
}
You could introduce new class derived from ImageView and make all those adjustments in that class. Then just replaces ImageView to your class implementation in layouts etc
There are multiple interpretations of your questions.
The ImageView should have same size on all the devices - use dp. You are using pixels right now in the LayoutParams.
The ImageView should look that it has same size on all screens - find the width and height of the screen, set an aspect ration, eg. 0.33 and use that factored width and height in LayoutParams.
Use MATCH_PARENT in LayoutParams for width as well as height and the ImageView will take the full size (of the parent).
This question has a lot of great explanation about dp, px, sp that could be useful - What is the difference between "px", "dip", "dp" and "sp"?
To find screen sizes
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
// these are sizes in pixels
metrics.widthPixels, metric.heightPixels
Then, you can use this
iv.setScaleType(ImageView.ScaleType.FIT_XY);
See this link for all ScaleType values
Android ImageView ScaleType: A Visual Guide

View.getWidth() shows the correct width but cannot produce the right margin when added to View's x position

So I overlayed a view of another view. And try to position my arrow so that it points to the image underneath it:
The arrow is an ImageView and I set its top and left margins to position it in the right place. I did it by adding the width of the TextView underneath it that says "No photo taken today" to the TextView's left border position. But funnily, the arrow is pointing to the middle and not the end of that TextView.
int topMargin=(int)pxToDp(getRelativeTop(dailyPhotos)+(int)dailyPhotos.getHeight(),this);
int leftMargin=(int)pxToDp(getRelativeLeft(dailyPhotos)+dailyPhotos.getWidth(),this);
getRelativeLeft() I copied from this answer.
I show the width of that TextView and the screen's width in a Toast. They are both correct since that TextView's width is set to match_parent. I don't what is wrong.
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
Toast.makeText(this,"width="+dailyPhotos.getWidth()+", screen's width="+width,Toast.LENGTH_SHORT).show();
showNote.putExtra("photoCountTopMargin", topMargin);
showNote.putExtra("photoCountLeftMargin", leftMargin);
Reading/Changing the margin of a view needs to be done in the layoutparams of the view
LayoutParams layoutParams = (LayoutParams) view.getLayoutParams();
layoutParams.topMargin = ddd (in pixels)

Resize View in dp

I'm stuck trying to resize the width of a View in a ListView programmatically, because I want it to be in DP, not pixels.
My ListView generate instances of a RelativeLayout with a View that fills all the screen (match_parent), and a TextView and a button inside.
The View is set to width = match_parent to fill the whole screen, as intended
What I want, is to have different View width in my adapter. Like 25%, 50%, or 75% of the total width of the base View.
mRelativeLayout.setLayoutParams(new RelativeLayout.LayoutParams(**[VALUE I NEED HERE]**, mRelativeLayout.getLayoutParams().height));
The ImageView is set to width = match_parent
So this are the relevant parts of code in my ViewList adapter :
RelativeLayout mRelativeLayout = (RelativeLayout) convertView.findViewById(R.id.test_layout);
mRelativeLayout.setBackgroundResource(arrayListName.myColor);
if (arrayListName.myColor == R.color.custom ) {
dayviewLayout.setLayoutParams(new RelativeLayout.LayoutParams( 25% , dayviewLayout.getLayoutParams().height));
}
if (days.mMoodColor == R.color.custom2) {
dayviewLayout.setLayoutParams(new RelativeLayout.LayoutParams( 50% , dayviewLayout.getLayoutParams().height));
}
if (days.mMoodColor == R.color.custom3) {
dayviewLayout.setLayoutParams(new RelativeLayout.LayoutParams( 75% , dayviewLayout.getLayoutParams().height));
}
The 25-50-75% are obviously wrong, as it takes only int values. I want it to fit any screen.
Thanks for your support.
dp units are just px units multiplied by the current screen density, which is available via the DisplayMetrics class:
float density = [some context].getResources().getDisplayMetrics().density;
int dp = (int) ([your px value] * density);

Android getDisplayMetrics() not returning accurate display size

I'm trying to get the pixel width/height of the device for placing elements and mapping touch events on the screen but not getting the desired effect (notice lower right square should be completely flush with the bottom right):
// screen size
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float ScrDensity = metrics.density;
int metricHeight = metrics.heightPixels;//
int metricWidth = metrics.widthPixels;//
Log.i("AllMetrics", metrics.toString());
// temp
int rightButton_diameter = 100;
int rightButton_xpos = metricWidth - rightButton_diameter;
int rightButton_ypos = metricHeight - rightButton_diameter;
Where AllMetrics returns:
DisplayMetrics{density=2.0, width=720, height=1184, scaledDensity=2.0, xdpi=320.0, ydpi=320.0}
I notice that the returned height is also different from the 720x1280 listed in the Virtual Device Manager (API 19, Android 4.4) and the x/y positions of the touch events seems accurate to the drawn elements (ie the clickable area of the button is the same as where it is being drawn)
Is this a configuration error or am I using the incorrect method of fetching screen position?
Check this code it works for me
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
Outside of activity you can try this
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(dm)
To access the DisplayMetrics members, initialize an object like this:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

Android – Am I Doing this Right?

I am building an android app that requires a layout to be added programmatically. This is the line that seems to be giving me a hard time:
RelativeLayout.LayoutParams rightScreenParams = new RelativeLayout.LayoutParams(
(int) (screenWidth * 0.25), (int) (screenHeight * 0.94));
The variables screenWidth and screenHeight are the width and height of the screen in pixels. The layout is supposed to be 25% of the width of the parent layout, and 94% of the height. When I add the parameters to the layout and then add the layout, it takes up the entire screen instead of the dimensions I mentioned.
So am I using this constructor correctly? Any help is appreciated. Thank you for your time.
Edit:
I get screenWidth and screenHeight in onCreate():
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager wm = (WindowManager) getApplicationContext()
.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getMetrics(displayMetrics);
screenWidth = displayMetrics.widthPixels;
screenHeight = displayMetrics.heightPixels
The variable screenHeight is returning as 1184 even though the actual height in pixels is 1280. The variable screenWidth seems to be fine. So how can I get an actual screen height in pixels?
RelativeLayout.LayoutParams rightScreenParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.Wrap_Parent,samehere);
View.setLayoutParams(rightScreenParams);//your view
//after you add it to the layout then you call
rightScreenParams.width = (int) (screenWidth * 0.25);
rightScreenParams.height = (int) (screenHeight * 0.94);
its the same thing but it forces android.

Categories