问题
I have simple ListView with ArrayAdapter which is working just fine. The problems start with RTL language (Arabic in this case).
When you open it for the first time, everything looks ok:
But after scrolling down and back up, some items appears to be rendered incorrectly:
The code is straightforward. Note that if I do not REUSE view and instead inflate it unconditionally every time (see the commented line below), the issue is GONE. But this is obviously not right, I want to REUSE items for better performance and smooth scrolling.
Please also note that I have multiple ListView
s in the app, and all of them shows this kind of incorrect rendering in Arabic. For this question I picked up the simplest case when I just set text and icon for every list item.
Please advice. The portion of code of my implementation of ArrayAdapter
:
public class PagesListAdapter extends ArrayAdapter<IPageRef> {
...
public View getView(int position, View convertView, @NonNull ViewGroup parent) {
final IPageRef b = getItem(position);
View row = convertView == null ? mInflater.inflate(R.layout.lang_item, parent, false) : convertView;
//View row = mInflater.inflate(R.layout.wordlist_item, parent, false);
TextView title = row.findViewById(R.id.title);
ImageView img = row.findViewById(R.id.img);
... // (setting the title & img properties)
return row;
}
}
lang_item.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:gravity="center_vertical"
android:orientation="horizontal" >
<ImageView
android:id="@+id/img"
android:layout_marginBottom="5dp"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_width="50dp"
android:layout_height="38dp"
android:padding="1dp"
/>
<TextView
android:id="@+id/title"
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center_vertical"
android:textSize="25sp" >
</TextView>
</LinearLayout>
回答1:
change your layout to:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingBottom="5dp"
android:paddingTop="5dp">
<ImageView
android:id="@+id/img"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_width="50dp"
android:layout_height="38dp"
android:padding="1dp"
/>
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/img"
android:textSize="25sp" />
</RelativeLayout>
回答2:
To support RTL alignment you first need to add android:supportsRtl="true"
to the <application>
element in your manifest file.
Major thing:-
- If your app only supports API ≥ 17, replace all the layout_marginLeft/layout_marginRight/paddingLeft/paddingRight or any other Left and Right layout property with Start and End equivalent. For example android:paddingLeft will be replaced with android:paddingStart.
- If your app supports API<17 then instead of replacing the Left and Right layout properties, add their Start and End layout property equivalent alongside.
Or you can just do for all layouts using Android Studio > Refactor > Add RTL
support where possible…
For more references on RTL follow this article for drawables as well here It will surely solve your problem using each step.
回答3:
Try using a Relative Layout for your row items, with the gravity as 'start' and 'end' (instead of 'left' and 'right') to see if that helps.
(If you always want the image to be on a specific side then use left/right instead of start/end)
Also, make sure you have rtl support on in your Manifest file
android:supportsRtl=true
https://developer.android.com/guide/topics/manifest/application-element.html
回答4:
Try changing TextView gravity to this: android:gravity="center_vertical|right"
回答5:
If you want to generalise rtl and ltr using the same layout, in my opinion the best way to deal with two ImageView
s and make one Visible / Gone according to your need. Something like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ImageView
android:id="@+id/img_rtl"
android:layout_alignParentRight="true"
android:layout_marginBottom="5dp"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="1dp" />
<ImageView
android:id="@+id/img_ltr"
android:layout_marginBottom="5dp"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_width="wrap_content"
android:visibility="gone"
android:layout_height="wrap_content"
android:padding="1dp" />
<TextView
android:id="@+id/title"
android:layout_toLeftOf="@id/img_rtl"
android:layout_toRightOf="@id/img_ltr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textSize="25sp" >
</TextView>
</RelativeLayout>
Make img_rtl 'visible' and img_ltr 'gone' in case of arabic texts and opposite in case of english, from your getView
method.
来源:https://stackoverflow.com/questions/49696154/listview-layout-inconsistent-rendering-with-rtl-languages-arabic