9

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:

enter image description here

But after scrolling down and back up, some items appears to be rendered incorrectly:

enter image description here

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 ListViews 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>
Mike Keskinov
  • 11,614
  • 6
  • 59
  • 87
  • 1
    Can you please share the lang_item layout. – Subrata Mondal Apr 12 '18 at 17:37
  • Shared, but I need to note, that I have multiple different layouts which all works fine in LTR languages, but not in RTL (Arabic). – Mike Keskinov Apr 12 '18 at 17:57
  • i dont see any issues with the code. which android version are you running it on? – user1506104 Apr 15 '18 at 10:35
  • @MikeKeskinov In the screenshot you shared, I can see that the device language is in English but your app is in Arabic, so possibly the issue could be where you are changing app language. Please share the snippet you are using to update your app language. – Rehan Apr 16 '18 at 08:24
  • have you tried `android:textDirection="rtl"` in listview? – Sagar Apr 17 '18 at 01:58
  • 1
    Turns out that in Android 8.1 the problem is gone by itself. I still see it in Android 7 – Mike Keskinov Apr 17 '18 at 15:50
  • Why don't you try `RecyclerView` instead of `ListView` which could handle the view recycling properly? – Onkar Nene Apr 19 '18 at 09:16
  • 1
    sorry, did you find a solution to this? – Zee Mar 29 '19 at 08:48
  • +1 for this question. I saw the same on an Android 7.0 device. It seems like it's a bug in android https://issuetracker.google.com/issues?q=componentid:190923%2B%20listview%20rtl%20 and there are a few issues reported in the issue tracker for this as well. – Shivam Pokhriyal Oct 12 '20 at 11:14

6 Answers6

2

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.

Karan sharma
  • 1,511
  • 1
  • 13
  • 37
1

Try manually setting the direction based on configuration (that is quite reliably updated based on device language) by adding rowView.setLayoutDirection(getContext().getResources().getConfiguration().getLayoutDirection()); in the getView of your ListAdapter.

From: ListView's first entry always incorrect for RTL

This solved my problem that was similar to your.

afruzan
  • 1,454
  • 19
  • 20
-2

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

Shmuel
  • 3,916
  • 2
  • 27
  • 45
-2

If you want to generalise rtl and ltr using the same layout, in my opinion the best way to deal with two ImageViews 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.

Subrata Mondal
  • 822
  • 7
  • 17
-2

Try changing TextView gravity to this: android:gravity="center_vertical|right"

Leo
  • 44
  • 1
  • 2
  • 8