NativeAdsExpress 强制 RecyclerView 滚动以使 NativeAd 在首次加载时完全可见

NativeAdsExpress forces RecyclerView to Scroll to have the NativeAd fully visible when first loaded(NativeAdsExpress 强制 RecyclerView 滚动以使 NativeAd 在首次加载时完全可见)

本文介绍了NativeAdsExpress 强制 RecyclerView 滚动以使 NativeAd 在首次加载时完全可见的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个奇怪的问题"或者可能是一个功能",我只是不知道,每当在我的 RecyclerView 中加载 NativeAdExpress 时,如果只有部分 NativeAd 可见,它会强制 RecyclerView 滚动直到原生广告变得完全可见,这种行为会导致列表在我滚动时不断跳跃.

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.

我的布局主要是:

Activity > 带有 Tabs 和 ViewPager 的 AppBar > Pager 中的每个页面都包含 PullToRefresh 并且在其中有一个 RecyclerView,RecyclerView 有 2 种类型的项目(Article 和 NativeAdExpress).

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).

更新:我猜为什么会发生这种情况主要是因为原生广告在 webview 中表达渲染,并且这个 webview 接收焦点然后这会导致 RecyclerView 滚动到它,但这只是一个猜测

更新 2:显然这是 Support Lib 中的一个问题.24.0.0,这就是太更新的代价:(

这是我的完整 XML/布局

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>

其中app_bar_main.xml"如下:

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>

最后我有 2 个视图类型 Item 和 NativeAdExpress:

and finally I have 2 View Types Item and NativeAdExpress:

NativeAdExpress ViewHolder 如下:

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;
    }

推荐答案

我不明白您在代码中实际实现 RecyclerView 的位置,但无论如何,这可能适用于您的情况.

I did not understand where you actually implement a RecyclerView in your code but here is anyway maybe something that could work in your case.

我遇到了类似的问题,GridViewFragment 首次加载期间总是获得焦点,它也自动向下滚动到 GridView.

I had a similar problem with a GridView always getting the focus during a Fragment first load, it was also automatically scrolling down straight to the GridView.

经过大量测试,我终于在GridView的父布局上用这一行停止了这种行为:

After a lot of tests, I finally stopped this behavior with this one line on the parent layout of the GridView:

android:descendantFocusability="blocksDescendants"

这一行基本上意味着父布局的所有后代将不再获得焦点.你可以在你的 RecyclerView 父布局上试一试.

This line basically means that all descendants from the parent layout will not get focus anymore. You can try it out on your RecyclerView parent layout.

这篇关于NativeAdsExpress 强制 RecyclerView 滚动以使 NativeAd 在首次加载时完全可见的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:NativeAdsExpress 强制 RecyclerView 滚动以使 NativeAd 在首次加载时完全可见