I have a custom layout with width="match_parent". Layout consists of big circle in the center and smaller one just next to it.
On my screen I have found the dimensions that I like and now I want to make it look similar across all devices.
My device is Galaxy S8 with display metrics reported as:
DisplayMetrics {
density=3.5,
width=1440,
height=2960,
scaledDensity=2.8,
xdpi=562.707,
ydpi=565.293
}
So as I understand I have 411dp in width available.
For dimensions I have
Big Circle in the center 110dp radius.
Smaller circle next to it 21dp radius.
The distance between them 20dp.
Now I wonder how should I go with this. I have 2 options in my mind. First will be to create separate values for other screen densities, or just convert this dimensions into percentage and do the layout programmatically.
My problem with first option is that some devices (like mine) have screen zoom which changes scaledDensity making it look totally different.
You can support different screen sizes use ConstraintLayout:
ConstraintLayout allows you to create large and complex layouts with a flat view hierarchy (no nested view groups). It's similar to RelativeLayout in that all views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than RelativeLayout and easier to use with Android Studio's Layout Editor.
You can use those attributes to specify your views size in precents:
app:layout_constraintWidth_percent=".5"
app:layout_constraintHeight_percent=".5"
For example, single button that is equal to 50% of the screen both in height and width:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_percent=".5"
app:layout_constraintHeight_percent=".5"/>
</androidx.constraintlayout.widget.ConstraintLayout>
And it will look something like this:
One more thing, because different phones got different screen size you better not use fixed size dimensions (50dp for example )on your views.
I can recommend using ConstraintLayout with guidelines and Chains to support different screen sizes (In addition to what I mentioned above - app:layout_constraintWidth_percent and app:layout_constraintHeight_percent).
Related
Suppose I have arbitrary text to display and I can't put it in a ScrollView or anything similar because of the application needs and the rest of the layout details -- the text can be any length, has to be on one line, and the only way to get it all on screen if it's too large is to scale it down according to display dimensions. It needs to use wrap_content for width and height as it may wind up smaller than the display bounds and we don't want to stretch it in that case.
To address this problem, I first tried placing the TextView in a ConstraintLayout and constraining its width and height; I expected this to automatically scale the TextView down if it was too large, in order to fit the constraints of its parent whose width/height are given as match_parent. Unfortunately, it had no obvious effect and the text ran happily off screen. Next I tried to manually scale the TextView to fit from my app code, but when I call getMeasuredWidth/Height on the TextView I always get the display dimensions back (presumably because the measurement is clamping to display bounds).
Layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black">
<TextView
android:id="#+id/text"
android:text="teeeeeeeeeeeeeeesteeeeeeeeeeeeeeeeeeeeeeesteeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeesteeeeeeeeeeeeeeeeeeeest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:textSize="300sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constrainedWidth="true"
app:layout_constrainedHeight="true"
android:maxLines="1"
/>
</android.support.constraint.ConstraintLayout>
Measure reporting code:
View textView = findViewById(R.id.text);
ViewTreeObserver textViewTreeObserver = textView.getViewTreeObserver();
textViewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Log.i("MyActivity","oncreate; text view dimens are "+textView.getMeasuredWidth()+","+textView.getMeasuredHeight());
}
});
The logs are telling me "text view dimens are 2094,1017" which are the display dimens minus system views, and the text is just cut off after there's too much to fit on screen (all I see on screen is "teee").
Note
The TextView example is just a symptom of the larger problem; I may need to deal with runtime images etc. that are too large for the display, so I'm looking for a way to detect and scale down (or ideally set up ConstraintLayout to do so for me) arbitrarily large runtime content set in a View. The only option that comes to mind (considering the fact that View's measurements apparently clamp to display bounds) is to figure out the problem before View gets involved, e.g. by looking at a raw image's dimens or the text data we've received for a TextView vs. the TextView's current font scaling factor and modifying as needed before setting it as the View's content. The trouble with that is it's very content type dependent, and I was hoping to avoid writing a lot of code to manage runtime content when View subclasses theoretically already have the information at some point during layout.
Questions:
Why didn't the constraint solution scale the TextView down automatically to fit within the ConstraintLayout's match_parent width and height per this answer?
How can I get the total size in pixels it would take to display a view's contents even if that value is greater than the actual device display boundaries?
android:textSize="300sp" //Its a fixed value
Setting too large font size make the result, you could refer the autosizing-textview to learn how to handle this case.
I created the corresponding drawable folders in android studio for the application, but the images in it did not work properly, with two different devices in terms of their resolution for two different results. The application only displays the image in only 1 folder and makes the layout skewed in 2 types of devices.
I have created small-normal-large layout files, they work fine, but when the same layout type (for example the same type of normal screen on both devices), the photos were in the wrong position when designing.
Screen 1
enter image description here
Screen 2
enter image description here
Layout XML of both screens.
Here are the layout XML of two screens above
I think you manually assign margin left and margin top. please remove margin if given and make parent layout relative and image view make it centerInParent="true" also fixed the height and width on image view
To continue use ConstraintLayout you can try below
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="50dp"
android:id="#+id/guideline"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5"/>
</androidx.constraintlayout.widget.ConstraintLayout>
I have an ImageView (human body) and buttons over this image.
Is it possible somehow easily create this in RelativeLayout for the most different screen sizes? Or should I create different layouts for different screen sizes?
How would you proceed? What do you recommend?
Have a look at the percent library.
It would be perfect for something like this, and would work for every device. You'd have to work out the percentage width, height, and margin for each PercentRelativeLayout relative to your person image.
Here's an example:
<android.support.percent.PercentRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
app:layout_widthPercent="25%"
android:layout_height="100dp"
app:layout_marginLeftPercent="5%"
android:background="#ff0000" />
</android.support.percent.PercentRelativeLayout>
and remember to
compile 'com.android.support:percent:23.0.0'
This is an example for an imageview with clickeable areas.
https://blahti.wordpress.com/2012/06/26/images-with-clickable-areas/
I hope it will helps to you.
Yes it is possible with Relative layout but its difficult.
for this you have to focus on
different images with perfect cutting.
put images in all drawable.
Create Relative layout and starting with image-view at one side to end side as reference wise.
Margin add in different dimen.xml
I am a bit of an android noob, and have been struggling with this problem for far too long.
What I'm aiming for:
Two ImageViews. The first will be the width of the screen, and drawn to match the proportions of its src image (so far so easy). The second ImageView needs to be scaled, so that its width is a fixed multiple (between 0 and 1) of the first image.
I will ultimately then need to be able to touch-drag the second smaller image around on top of the first, fixed image, although this part is not the point of this question.
This will all generally be done programmatically, as the src images and the scale multiple are not known until runtime.
What I've tried: I can overlay two ImageViews in a RelativeLayout, using alignParentTop and so on. This works fine, but I can't see how to scale the images in this case.
I can alternatively scale the two ImageViews using a LinearLayout, by setting their layout_weights to 1 and the scale multiple respectively. In this case I can't get the images overlapping however (not strictly true - I have managed this with negative margins, but it is a very hacky solution and will make it almost impossible to implement the movement of the top image later).
So my question is: is there a way to fix either of the two solutions I have tried to implement? Or is there perhaps a better way to approach the problem?
(I'm not necessarily looking for an answer in code, just the approach I should take)
Well with what I understand,
You can use a Constraint Layout
Place 1st ImageView on your desired place
with constraints to your parent
Place Second ImageView on your desired place
with constraints to the parent (NOT WITH ANY OTHER CHILD VIEW)
The Approach is if you put a SubView In ConstraintLayout with Constraints to Parent, you can manipulate (Scale / translate) without any effect on other views.
to change the position of the View in runtime you can use
view.setTranslationX() and view.setTranslationY();
you can also create a view programmatically with Constraints to the parent
(my personal preference)
you can use this to overlay different Views in ConstraintLayout
<ImageView
android:id="imageID1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="yourImageStable"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
// put your own constraints-
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</ImageView>
<ImageView
android:id="imageID2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="yourImageUnStable"
android:adjustViewBounds="true"
android:scaleType="fitCenter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
Note: This two constraint value will draw an ImageView from the Top-Left
corner of the Parent View (on Position x=0, y=0)
Remember: the View which you want to overlay should be written next to the other,
like here ImageID2 can overlay ImageID1.
</ImageView>
I have a RelativeLayout which currently has a fixed size. Widths, heights, margins, font heights of child views are specified so everything looks just right.
I now want to scale the layout (to fit screen size). The layout should scale as if it was a flat image, so everything gets smaller in proportion (fonts, margins etc.)
I made a simplified example, below. Scaled to 0.5, this would display the text "ONE QUARTER" with margin left 200dip and margin top 120dip.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="#+id/RelativeLayout01"
android:layout_width="1600dip"
android:layout_height="960dip"
xmlns:android="http://schemas.android.com/apk/res/android"
>
<TextView
android:text="ONE QUARTER"
android:id="#+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="400dip"
android:layout_marginTop="240dip"
></TextView>
</RelativeLayout>
Of course, I'm not asking anyone to help me hand code an algorithm to scale all these values: just wondering if there's some simple way to achieve this...
Thanks!
If you just want your app to look ok on another device then specifying things in dip and sp should do the trick.
If you actually want to shrink or expand the scale of your app on the same device then you would have to do it manually, perhaps using themes or styles.