why the upper part of recyclerview item is erased? - android

the upper part of recyclerview item is erased in some phones and is normal in other phones as the images below.
the first image is normal which from samsung phone (android 12 )
the second image has the problem which from huawi phone (android 8)
this is the code
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="70dp"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
android:layout_margin="5dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp">
<com.makeramen.roundedimageview.RoundedImageView
android:id="#+id/itemImage"
android:layout_width="40dp"
android:layout_height="40dp"
android:scaleType="centerCrop"
android:src="#drawable/ic_launcher_background"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:riv_oval="true"
/>
<View
android:layout_width="1dp"
android:layout_height="1dp"
android:id="#+id/viewSupporter2"
app:layout_constraintBottom_toBottomOf="#id/itemImage"
app:layout_constraintEnd_toEndOf="#id/itemImage"
app:layout_constraintStart_toStartOf="#id/itemImage"
app:layout_constraintTop_toTopOf="#id/itemImage"
/>
<TextView
android:id="#+id/diseasename"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="disease name"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#color/black"
app:layout_constraintBottom_toTopOf="#id/viewSupporter2"
app:layout_constraintStart_toEndOf="#id/itemImage"
/>
<TextView
android:id="#+id/diseasenickname"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text= "disease nickname"
android:textColor="#color/teal_700"
app:layout_constraintTop_toBottomOf="#id/viewSupporter2"
app:layout_constraintStart_toEndOf="#id/itemImage"
tools:ignore="NotSibling" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

You're doing a basic mistake of having your cards at fixed height of 70dp. Change them to be wrap_content and tweak margins/paddings of your layout instead to achieve the size you need.
While it looks ok on device you designed it for you can see it cannot fit TextViews on the other one so they ends up being clipped (on top). Actually you can even break it on your Samsung if you go into device settings and increase font size.
You have to let your card view "grow" in those cases so unrestraining height it is the way to go. Although you might consider adding maxlines to your textviews so they don't get too out of hand with maximum font size.

The problem here is your second device is set to a larger system font size than the first one. The dp system is designed so that things look consistent on different devices, and you can see that the ImageView takes up pretty much the same amount of space on both - the space around it is the same, the layout looks the same.
But you have to account for the user changing their overall text size, which is what's happening on your second image. See how the text is just bigger? Not just in your list items - the diseases text is taller than the hamburger icon on this one, the tab headers are much closer together because the words are wider...
You have three options in this case
use dp instead of sp for the text sizes (so they're consistent and don't scale to the user's preference)
make sure your fixed layout has enough space for those larger text sizes
make sure it can expand as necessary to fit them
The first option is ok sometimes, when you have text that's already large enough for everyone, and you want to maintain some kind of visual consistency (like a fixed design where things are a certain size etc). Don't do this as a way to get around the limitations of having to provide accessible content, that scales so the user can read it.
The flexible layout approach is what Pawel's suggesting - basically design your layout so it can grow if necessary. You can use the minWidth and minHeight layout attributes for this (and layout_constraintHeight_min in ConstraintLayout) to design how you want it to look, but use things like wrap_content and constraints to allow it to grow beyond that if necessary. That way you get it looking how you like, but if the user needs bigger text, it compromises.
And don't worry if you don't like how it looks with large text - that's not important! What's important is that the user can read it, and everything's visible and accessible. Nothing cut off, nothing overlapping anything, everything clickable etc. The user is the one making the compromise between style and practicality, and they probably don't have a choice, so just making it usable in that situation is the main thing.
The middle option is the fixed layout that has enough space for the larger text settings. This is actually what's recommended in the Material Design spec - I can't link directly to the Two line version, but go here and scroll down - there are some similar to what you're doing:
Those measurements are all in dp - notice that the top line's position is defined by where its baseline is, the line the text "rests" on, relative to the top of the layout. You can do that with:
android:layout_height="wrap_content"
app:firstBaselineToTopHeight="32dp"
app:layout_constraintTop_toTopOf="parent"
And then the text below has its baseline relative to the bottom of the first
app:layout_constraintBaseline_toBaselineOf="#id/firstTextView"
app:layout_marginBaseline="20dp"
or you could constrain it to the top of the layout like the first one, with a value of 32 + 20dp.
Notice that this design leaves space for the text to grow vertically (up from the baseline, which is in a fixed position). If you use the Material Design type scale (which is a bunch of standard text styles and font sizes with names like Subtitle and Body1) then those list item specs should have enough room to hold the text even at the larger font settings. Both lines in that image can pretty much double in height and still fit
The nice thing about these specs is someone's done the work coming up with a design for you! And they're working with fixed sizes, so you get a nice consistent look to your lists

Related

Putting drawables in front of one another causes dramatic used memory increase

Usual memory footprint of my app is around 20MB. However, when I put drawables one in front of the other (for the sake of animating the each individual element)...
There are actually two drawables in this picture: the green base and the pin (with its shadow)
...my memory usage goes up by ~40MB!The layout is using xhdpi drawables, which have around 2.1MB in total. The layout of these drawables is:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.2">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/serbia"
android:src="#drawable/serbia"
android:adjustViewBounds="true" />
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/pin"
android:src="#drawable/pin"
android:adjustViewBounds="true"/>
</RelativeLayout>
What is causing such sudden memory increase? Is there a way to bypass such practice, but still be able to animate each part of the image separately?
Note that I still have to properly align these elements (the pin isn't in the center of the layout), because the right edge of the shadow is cropped to the shape of the base)
The pin and the shadow may be small but the view size is the same as the parent as you layout them so the bigger one (the parent) sets the size of all them three buffers for painting. So the biggest size multiplied by 3 (or four, I donno how actually the container paints itself) is the memory used. And by biggest I mean biggest in screen format, not in the file compressed.
Best thing to do could be to paint them yourself or stack them up using a FrameLayout and then setting x and y possition... Donno right now if u can set thrm in the xml directly but, if not, set them in code elsewhere.

Am I misusing dimens.xml?

This will be a pretty simple question, because I might have been doing the wrong thing for a long time.
I will introduce my problem with an example: Let's say that the designer defines the following design for a screen of our app (phone only):
Which I then would implement with the following layout code:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:gravity="center"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Example text"
android:gravity="center"
android:textColor="#android:color/black"
android:textSize="56sp" />
</LinearLayout>
Which looks fine on the Nexus 5, but when I switch to a Nexus One, I get this picture, which is definitely not what I wanted:
So my solution for this was: defining a dimens.xml both in /values, and in /values-sw360dp. Then adding a dimension for the text size. Where the size would be 56sp in values-sw360dp/dimens.xml, and 52sp in values/dimens.xml
Of course, when the project got bigger and bigger, the amount of dimens just kept rising (we have about a hundred now). It's not only text sizes of course, but widths, heights, margins and paddings too.
Lately I got a remark, which said that keeping track of all the dimens is just hell, because sometimes you forget to edit one (like when making something smaller), and then it looks good on all screen sizes except one. I completely agree with this, but can't think of a better solution. Is this what dimens.xml is for, or is there a way better solution I just didn't find yet?
I get this picture, which is definitely not what I wanted
I am going to guess that you mean that you do not want this text to be word-wrapped.
is there a way better solution I just didn't find yet?
With respect to text size, you are welcome to use any number of libraries that can automatically adjust the font scale, such as AutoSizeTextView.
With respect to "margins and paddings", those are usually handled by dimension resources, akin to handling them in CSS rules in Web development.
Beyond that, design fluid layouts (so you can hard-code fewer "heights, widths") that can handle word-wrap (particularly for text not knowable in advance, such as user-entered values or data retrieved from the Internet).
It's really not just text, this was just a good example of showing the difference.
Most widgets don't have "word wrap" as an option; for those, you really need to use fluid layout designs, where the size of the widget is derived at runtime from other rules (wrap_content, match_parent, weights on LinearLayout, spanning rules on GridLayout, anchoring rules on RelativeLayout, column-sizing rules on TableLayout, etc.).

Extending margins on larger Screens

Is there a way in android to make the margins extend to fill screens? The problem is that layouts I build for Nexus devices look great, but then when previewing on a regular device without the bottom controls there is an ugly space between the rest of the layout and the bottom. I would like the margins between items to increase when there is available space.
Pictures are added below. Sorry for the ugly cutting of some of the fields, I'm unable to show them at this time to due a contract. Notice how "advacned search" is far from the bottom, I would like the vertical margins between all items to increase and make sure this doesnt happen.
How can I acheive this in a relative layout?
Try using LinearLayout and empty Views between each of the items.
just empty View:
<View
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#android:color/transparent" />

Android sp vs dp texts - what would adjust the 'scale' and what is the philosophy of support

So we know from many other posts that we should use sp rather than dp for text in Android, and we know the reason for this is to respect a 'user's preferences'.
But precisely what are these preferences?
How might a user change this setting?
I cannot find any reference through the settings on my phone (I would have expected something in 'Accessibility' or 'Display'). So what is a user setting? Is it only done through the likes of an app such as 'Big Font'?
Assuming that it is (set by something like big font) - I have played with Google Docs and some other Google apps with the font set to 130%. While most layout stays fine, some gets a bit cut off and can't be read (and that is on a big screened SGS2). So, what is the approach to developing apps with text sizes using 'sp'? Do we make sure it works on 100% scaling and then ignore other settings - call it a special case that the user can worry about, or do we go out of our way to make sure things expand or are scrollable, in case the text overflows?
One argument is that we should use 'dp' to guarantee a user has a chance of seeing the text (even if they have to use a magnifying glass)
Thoughts/comments?
It is exposed in the settings menu on some Android devices (manufacturer dependent). It may also be altered by some accessibility options (device-dependent).
In general, you should always used scale-independent pixels, especially for a large body of text.
However if your text has to fit into a bounding-box of known size then you should use density independent pixels in order to ensure that the text always fits properly and that all characters are visible regardless of the users' setting.
In a nutshell: would increasing the text-size by around 5sp result in the text being unreadable or mangle your UI? If so use density-independent pixels. If not, use scale-independent pixels. However you should generally aim to use scale-independent pixels wherever possible, which means designing a UI that can accommodate different text sizes.
Using the sp unit is recommended for text because in ICS and above (could be Honeycomb too, correct me if I'm wrong), there is a preference for a user's font size. So, if you're using Gingerbread or lower, you won't be able to find this setting.
The preference is under Settings, Display, Font Size. There's also an option under Settings, Accessibility, Large text, too.
To address your question about how to go about using sp, note that by default, without changing any of the font size preferences, 1sp is equivalent to 1dp (also, they are equivalent before the preference was introduced). Like you've noted, designing for the case where a user has huge text would probably require you to assume things are going to need to scroll where you might otherwise not expect them to.
The answer lies in looking at this particular issue holistically.
The motivation for using "sp" for font sizes lies in giving the developer power to control their layout in the face of user changing the font size on their device.
Example:
Lets look at 2 extreme cases:
1) User selects font size "small"
This is what my layout looks like:
http://postimg.org/image/kiyqeo2bh/
Here is the layout xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
tools:context=".MainActivity"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_row="0"
android:layout_column="0"
android:text="Material-Design ist die Scheiße"
android:textSize="18sp"
android:background="#ffff0000" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_row="0"
android:layout_column="0"
android:text="Material-Design ist die Scheiße"
android:textSize="25sp"
android:background="#ffff0000" />
2) If the user selects font size "huge":
This i what my layout looks like:
http://postimg.org/image/d7rax9wob/
My layout xml is same as above in case 1).
So, as you can see what happened here is the top TextView has sort of perfect font-size in sp because it does not wrap for the entirety of the range of font sizes (small to huge). But the bottom TextView completely messes up your layout/design in case 2).
So you as a developer can iterate and decide what size in sp works for your design and android will draw it for you.

Is it a bad practice to use negative margins in Android?

Demo of negative margin:
                         
The scenario
Overlapping views by setting a negative margin to one of them so that it invades the bounding box of another view.
Thoughts
It seems to work the way you'd expect with overlapping of the layouts if they should. But I don't want to run into a bigger problem for unknowingly not doing things right. Emulators, physical devices, you name it, when you use negative margins everything seems to work correctly, one view invades another's views bounding box and depending on how it's declared in the layout it will be above or below the other view.
I'm also aware that since API 21 we can set the translationZ and elevation attributes to make view appear above or below other views but my concern basically comes from the fact that in the documentation for the layout_margin attributes it's clearly specified that margin values should be positive, let me quote:
Excerpt:
Specifies extra space on the left, top, right and bottom sides of this view. This space is outside this view's bounds. Margin values should be positive.
Must be a dimension value, which is a floating point number appended with a unit such as "14.5sp". Available units are: px (pixels), dp (density-independent pixels), sp (scaled pixels based on preferred font size), in (inches), mm (millimeters)...
In the years since originally asking this question I haven't had any issues with negative margins, did try to avoid using them as much as possible, but did not encounter any issues, so even though the documentation states that, I'm not too worried about it.
In 2010, #RomainGuy (core Android engineer) stated that negative margins had unspecified behavior.
In 2011, #RomainGuy stated that you can use negative margins on LinearLayout and RelativeLayout.
In 2016, #RomainGuy stated that they have never been officially supported and won't be supported by ConstraintLayout.
In December 2020(v2.1.0, official release June 2021), negative margin support for constraints has been added to ConstraintLayout.
It is easy to work around this limitation though.
Add a helper view (height 0dp, width constrained to parent) at the bottom of your base view, at the bottom add the margin you want.
Then position your view below this one, effectively allowing it to have a "negative" margin but without having to use any unsupported negative value.
Hope this will help someone. Here is working sample code using ConstraintLayout based on #CommonsWare's answer:
Add an helper view (height 0dp, width constrained to parent) at the
bottom of your base view, at the bottom add the margin you want. Then
position your view below this one, effectively allowing it to have a
"negative" margin but without having to use any unsupported negative
value.
Sample code:
<TextView
android:id="#+id/below"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#F1B36D"
android:padding="30dp"
android:text="I'm below"
android:textColor="#ffffff"
android:textSize="48sp"
android:textAlignment="center"
tools:layout_editor_absoluteX="129dp"
tools:layout_editor_absoluteY="0dp" />
<android.support.v4.widget.Space
android:id="#+id/space"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="32dp"
app:layout_constraintBottom_toBottomOf="#+id/below"
app:layout_constraintLeft_toLeftOf="#id/below"
app:layout_constraintRight_toRightOf="#id/below" />
<TextView
android:id="#+id/top"
android:layout_width="100dp"
android:layout_height="60dp"
android:textAlignment="center"
android:textColor="#ffffff"
android:text="I'M ON TOP!"
android:background="#676563"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/space" />
Output:
Instead of negative margins you can use:
translationX and translationY.
Example:
android:layout_marginBottom = -2dp
android:translationY = -2dp
UPDATE:
Have in mind that the whole view is translated.
In case you want use negative margin,set enough padding for container and its clipToPadding to false and set negative margin for it's children so it won't clip the child view!
It might have been bad practice in the past but with Material Design and its floating action buttons, it seems to be inevitable and required in many cases now. Basically, when you have two separate layouts that you can't put into a single RelativeLayout because they need distinctly separate handling (think header and contents, for instance), the only way to overlap the FAB is to make it stick out of one those layouts using negative margins. And this creates additional problems with clickable areas.
For me, and regarding setting a negative margin on a TextView (I realize the OP is referring to a ViewGroup, but I was looking for issues with setting negative margins and I landed here)... I found a problem with 4.0.3 (API 15) ONLY and the setting of android:layout_marginTop or android:layout_marginBottom to a negative value such as -2dp.
For some reason the TextView does not display at all. It appears to be "gone" from the view (not just invisible).
When I tried this with the other 3 versions of layout_margin, I didn't see the issue.
Note that I haven't tried this on a real device, this is using a 4.0.3 emulator. This is the 2nd odd thing I've found that only affected 4.0.3, so my new rule is to always test with a 4.0.3 emulator :)
I have success with reducing the bottom margin of a TextView by using android:lineSpacingExtra="-2dp" which works even though I happen to have android:singleLine="true" (and so I wouldn't have thought that line spacing would be a factor).
No, you should not use negative margin. instead you should use translate. Even if negative margin work sometime, when you change layout programmably, translate would help. And view can't overflow the screen wen you use margin.
I've only known that it was possible for a rather short period of time. But I see no problem with it. Just be aware of screen sizes and such so you are sure not to accidentally make to items that shouldn't appear overlapped on the screen. (i.e. text on top of text is likely a bad idea.)

Categories

Resources