I created a BaseAdapter that implements ListAdapter. This BaseAdapter reads a JSON file and populate my ListView inflating a custom layout.
In this JSON file I have a boolean value (active = true or active = false). If active is true, I inflate the custom layout and everything is fine, but if active is false, I need to create a new View in this custom layout. Here's my code:
if (!active) {
JSONObject notifications = jsonData.getJSONObject("notifications");
String message = notifications.getString("message");
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params.height = 70;
TextView warning = new TextView(Controller.getContext());
warning.setText(message);
warning.setTextColor(Color.WHITE);
warning.setBackgroundColor(Color.RED);
warning.setGravity(Gravity.CENTER);
warning.setPadding(10, 0, 10, 0);
warning.setLayoutParams(params);
// contentFrame is a RelativeLayout where the view is created;
viewHolder.contentFrame.getLayoutParams().height = 320;
viewHolder.contentFrame.addView(warning);
}
My problem here is this:
params.height = 70;
viewHolder.contentFrame.getLayoutParams().height = 320;
I'm saying that my TextView is 70 pixels higher and my RelativeLayout is now 320 pixeis high.
It looks nice on my phone, but if I test on a phone with other resolution it will not look the same right?
Is there any way to create a View and define is Height or Width according to the screen resolution? Maybe create the View 10% the size of the screen resolution? Is that a good pratice? What's the best aproach for something like this?
Instead of using hardcoded pixel values, use DPs. DPs account for the device density so views look pretty much the same regardless of which device the app runs on.
See this for additional info.
So, define this in your dimens.xml:
<resources>
<dimen name="my_width">320dp</dimen>
</resources>
Then read it like this:
int width = getResources().getDimensionPixelSize(R.dimen.my_width);
You have to scale your size values according to the screen density:
float density = getResources().getDisplayMetrics().density;
That means you have to multiply all size values with density:
params.height = (int)(70 * density);
viewHolder.contentFrame.getLayoutParams().height = (int)(320 * density);
and the same with padding values:
warning.setPadding((int)(10 * density), 0, (int)(10 * density), 0);
You can define dimensions in XML like any other resource, and have those resources automatically selected by Android based on the current device configuration.
So you have two definitions, one for "normal" circumstances, and another for "bigger screen":
src/main/res/values/dimens.xml
src/main/res/values-sw600dp/dimens.xml
Each resource file can have the same dimension defined in dp. Android will pick the appropriate one. If you need to read the values programmatically as raw pixel sizes, you can do that with Resources.getDimensionPixelSize().
I would recommend against trying to define list items in terms of percentage of the size of the screen.
Related
How to can I set a view at a specific point on the screen programmatically? I want use a Point like x and y. I don't want it to translateX or translateY. I want for example to set a view to the Point x: 0 and y: 0 that means it needs to be at the top left of the screen. How can I achieve that?
I was trying this but the view translates X and Y what I don't want.
val layoutInflater = LayoutInflater.from(context)
val inflatedView: View = layoutInflater.inflate(R.layout.fragment_change_font_size_right, null, false)
inflatedView.popup_xml_view.x = 0f
inflatedView.popup_xml_view.y = 0f
Android had a layout that would support this requirements, but I think that it was pretty bad in regards to performance and it was deprecated (I hope that I am not wrong making this affirmation). However, the same behaviour can be implemented using a FrameLayout and add the views in that layout.
To add a view at a particular position, you create its layout params to set a width and a height, then set the margins which will position your view as absolute coordinates (the dimension is in pixels):
val imageView = ImageView(this)
imageView.setBackgroundResource(android.R.color.holo_red_dark)
imageView.layoutParams = FrameLayout.LayoutParams(width, height).apply {
setMargins(left, top, right, bottom)
}
root.addView(imageView)
For a height/width of 200 and margins of (100, 100, 0, 0), it will look something like the image below (run on an emulated Pixel 3).
NOTE: Here is a talk where they talk about this approach to emulate the AbsoulteLayout and why they "killed" it.
I found this to work:
ViewGroup.MarginLayoutParams margins = (ViewGroup.MarginLayoutParams) layout.getLayoutParams();
margins.topMargin = 100;
margins.leftMargin = 200;
Alternatively use animate:
view.animate().x(x).y(y).setDuration(0).start();
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
There are a number of edit texts on
,
which I create dynamically using RelativeLayout (whis is defined in XML). The first edit text is also defined in XML, and the other ones are created based on this first edit text. The problem is that, as you can see the last edit text is changing its height and it's unlike the other ones, but how can I check it? How can I get the height of this edit text and add it to the next line on the screen?
you can try this to get size dynamically:
getMeasuredHeight() :please google it for more information.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EditText ed = (EditText) findViewById(R.id.edit1);
ed.setTextSize(20);
ed.setText("here stackoverflow");
ed.measure(0, 0);
int height = edit.getMeasuredHeight();
I usually use it because of this reasons, read carefully,it'll help you in future:
The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().
The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().
You can try something like this..
EditText editText = (EditText) findViewById(R.id.your_view_id);
int height = editText.getHeight(); // This will give height
EditText editTextLast = (EditText) findViewById(R.id.your_view_id);
editTextLast.setHeight(height); // this will set the height
This is driving me crazy. I would like to be able to resize an xml vector drawable icon programmatically in order to use it in an ImageView.
This is what I've done so far which is not working
Drawable drawable = ResourcesCompat.getDrawable(getResources(),R.drawable.ic_marker,null);
drawable.setBounds(0,0,512,512);
imageVenue.setImageDrawable(drawable);
The vector icon ic_marker is not resized. It just keeps the hardcoded width and height values every time.
Any ideas?
You can change the width and height of your imageview programmatically. Since vector drawables will preserve the original quality of the image, this will make the desired output happen.
ImageView iv = (ImageView) findViewById(R.id.imgview);
int width = 60;
int height = 60;
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(width,height);
iv.setLayoutParams(params);
I'm currently facing the same problem.
I'm trying something like this, cause ViewParent has actually height set explicitly, so I use match_parent and set margins. It doesn't work all the time though, cause I simply use this view in a viewholder for RecyclerView... Also I've noticed that sometimes I see scaled up version with artifacts, sometimes full size, sometimes there are margins, and bigger margins... But it still might work for you, if you use it in a simpler scenario.
mImageViewFront.setImageDrawable(vectorDrawable);
final int paddingLR = mImageViewFront.getWidth() / 4;
final int paddingTB = mImageViewFront.getHeight() / 4;
LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
params.setMargins(paddingLR, paddingTB, paddingLR, paddingTB);
mImageViewFront.setLayoutParams(params);
I have a custom view that extends from FrameLayout. I'd like one of the children to have a size equal to the 20% of the total size as shown in the image.
How can I achieve the imageview to always have this size even if the custom view changes its size in runtime?
Lets say you have your view:
FrameLayout view = (FrameLayout)findViewById(R.id.customView);
Then you can get the layoutParams of the view calculate 20% of it, and then create a new view which will be 20% of the view.
For example:
ImageView img = new ImageView(this);
int imgSize = view.getLayoutParams().width * 0.2; //20 % of the width
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(imgSize, imgSize);
//params.gravity = Gravity.TOP;//How to set gravity programmatically
img.setLayoutParams(params);
//Set img attirubutes like src etc.
view.addView(img)
Also because you are using a FrameLayout it might be better to create an instance of a LayoutParam first and the set it in img.setLayoutParams(params), because iam sure you want to change the layout_gravity of the different views, which you can do in the params vairable