dimanche 26 juin 2016

NativeAdsExpress forces RecyclerView to Scroll to have the NativeAd fully visible when first loaded

I have a weird "problem" or may be it's a "feature" and I just don't know, whenever a NativeAdExpress is loaded in my RecyclerView if only part of the NativeAd is visible, it forces the RecyclerView to scroll until the Native ad becomes fully visible, this behavior causes the list to keep jumping as I scroll.

My Layout is mainly:

Activity > AppBar with Tabs and ViewPager > each Page in the Pager contains PullToRefresh and inside it there's a RecyclerView, The RecyclerView has 2 types of items (Article and NativeAdExpress).

UPDATE: My guess on why this is happening is mainly because native ads express render in a webview, and this webview receives focus then this causes the RecyclerView to scroll to it, but that's only a Guess

UPDATE 2: Apparently this is an issue in Support Lib. 24.0.0, that's the cost of being too up2date :(

Heres's my Full XML/Layouts

<?xml version="1.0" encoding="utf-8"?>
<my.package.custom.views.CustomDrawerLayout
    android:id="@+id/drawer_layout"
    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:fitsSystemWindows="true"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:openDrawer="end">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        style="@style/AlertDialog.AppCompat.Light"
        fontPath="fonts/fonts/DroidKufi-Regular.ttf"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="end"
        android:fitsSystemWindows="true"
        app:elevation="5px"
        app:headerLayout="@layout/nav_header"
        app:itemIconTint="@color/colorPrimary"
        app:itemTextColor="@color/contentColor"
        app:actionLayout="@layout/nav_item_layout"
        app:menu="@menu/drawer_menu"
        app:theme="@style/NavDrawerStyle"
        tools:openDrawer="end"
        />

</my.package.custom.views.CustomDrawerLayout>

where "app_bar_main.xml" is as follows:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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:fitsSystemWindows="true"
    tools:context=".ui.activities.ArticlesListActivity">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="end">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="52dp"
            android:background="?attr/colorPrimary"
            android:gravity="end"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_vertical"
                android:orientation="horizontal"
                android:paddingEnd="14dp"
                android:paddingStart="14dp">

                <android.support.v7.widget.AppCompatImageButton
                    android:id="@+id/ivCustomDrawable"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentEnd="true"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true"
                    android:background="@color/transparent"
                    android:tint="@color/white"
                    />

                <TextView
                    android:id="@+id/view_title"
                    android:visibility="gone"
                    style="@style/SectionTitle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    />

                <android.support.v7.widget.AppCompatSpinner
                    android:id="@+id/sources_spinner"
                    android:gravity="center"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentLeft="true"
                    android:transitionName="@string/transition_splash_logo"
                    app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                    tools:targetApi="lollipop"/>
            </RelativeLayout>

        </android.support.v7.widget.Toolbar>

        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            style="@style/TabsStyle"
            android:layout_width="match_parent"
            android:layout_height="42dp"
            android:layout_gravity="bottom"
            android:layout_marginTop="0dp"
            android:transitionGroup="true"
            app:tabContentStart="0dp"
            app:tabGravity="fill"
            app:tabIndicatorColor="@color/white"
            app:tabIndicatorHeight="3dp"
            app:tabMode="scrollable"
            app:tabPaddingBottom="0dp"
            app:tabPaddingTop="0dp"
            app:tabTextAppearance="@style/TextAppearance.RegularTextFont"
            />

    </android.support.design.widget.AppBarLayout>

    <RelativeLayout 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"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            tools:context=".ui.activities.ArticlesListActivity"
            tools:showIn="@layout/activity_newsitem_list">

       <android.support.v4.view.ViewPager
         android:id="@+id/viewpager"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
        />
    </RelativeLayout>
</android.support.design.widget.CoordinatorLayout>

and finally I have 2 View Types Item and NativeAdExpress:

The NativeAdExpress ViewHolder is as follows:

public class NativeExpressAdViewHolder extends BaseCardAdViewHolder {
    private final NativeExpressAdView view;
    private boolean loaded = false;
    private AdListener adListener;
    private WeakReference<Context> context;

    public NativeExpressAdViewHolder(View itemView, String adId, Context context) {
        super(itemView);
        view = new NativeExpressAdView(context);
        view.setAdUnitId(adId);
        ((LinearLayout) itemView.findViewById(R.id.express_ad_holder)).addView(view);
        this.context = new WeakReference<>(context);
    }

    public void loadAd(float cardWidthInDips) {
        if (!loaded && null != context.get() && !view.isLoading()) {
            int width = cardWidthInDips > 0 ? (int) cardWidthInDips : 330;
            if (view.getAdSize() == null) {
                view.setAdSize(new AdSize(width, 330));
                view.setAdListener(new AdListener() {
                    @Override
                    public void onAdLoaded() {
                        super.onAdLoaded();
                        loaded = true;
                        if (adListener != null) {
                            adListener.onAdLoaded();
                        }
                    }

                    @Override
                    public void onAdFailedToLoad(int i) {
                        super.onAdFailedToLoad(i);
                        if (adListener != null) {
                            adListener.onAdFailedToLoad(i);
                        }
                    }

                    @Override
                    public void onAdOpened() {
                        super.onAdOpened();
                        if (adListener != null) {
                            adListener.onAdOpened();
                        }
                    }
                });
            }
            new Handler(context.get().getMainLooper()).post(new Runnable() {
                @Override
                public void run() {
                    view.loadAd(new AdRequest.Builder().build());
                }
            });
        }
    }

    public NativeExpressAdView getView() {
        return view;
    }

    public void setAdListener(AdListener adListener) {
        this.adListener = adListener;
    }

    @Override
    public void destroyAd() {
        if (view != null) {
            view.destroy();
            loaded = false;
        }
    }
}

and ads are create using a custom adapter as follows:

private BaseCardViewHolder createNativeExpressAdViewHolder(ViewGroup parent) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.ad_express, parent, false);
        final NativeExpressAdViewHolder viewHolder = new NativeExpressAdViewHolder(
            view,
            adManager.getNativeExpressAdId(),
            context.get()
        );
        adViewHolders.add(viewHolder);
        viewHolder.setAdListener(new AdListener() {
            @Override
            public void onAdFailedToLoad(int errorCode) {
                Log.i("ADS", "onAdFailedToLoad " + errorCode);
            }

            @Override
            public void onAdLoaded() {
                super.onAdLoaded();
                // Do something
            }
        });
        viewHolder.loadAd(cardWidthInDips);

        return viewHolder;
    }

Aucun commentaire:

Enregistrer un commentaire