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

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

问题描述

我有一个奇怪的问题,或者它可能是一个功能,我只是不知道,只要在我的RecyclerView中加载了NativeAdExpress(如果仅能看到NativeAd的一部分),它就会强制RecyclerView滚动直到

我的布局主要是:



活动>带有选项卡和ViewPager的AppBar>分页器中的每个页面都包含PullToRefresh,并且其中有一个RecyclerView,
RecyclerView有2种类型的商品(Article和NativeAdExpress)。



更新:我之所以会这样猜测,主要是因为原生广告在网络视图中表示渲染,并且该网络视图获得了焦点,然后这导致RecyclerView滚动到该视图,但这仅仅是猜猜



更新2:显然这是Support Lib中的问题。 24.0.0,这就是太过昂贵的代价2date:(



这里是我的完整XML /布局

 <?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
工具:openDrawer = end>

<包括
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 / Ale rtDialog.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
工具:openDrawer = end
/>

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

其中 app_bar_main.xml如下:

 <?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
工具: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 = horizo​​ntal
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
工具: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
工具:context =。ui.activities.ArticlesListActivity
工具: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个View Types Item和NativeAdExpress:



NativeAdExpress ViewHolder如下:

 公共类NativeExpressAdViewHolder扩展BaseCardAdViewHolder {
私有最终NativeExpressExpressView视图;
private boolean loading = false;
私人AdListener adListener;
private WeakReference< 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();
loading = 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();
loading =假;
}
}
}

,然后使用自定义适配器,如下所示:

  private BaseCardViewHolder createNativeExpressAdViewHolder(ViewGroup parent){
View view = LayoutInflater.from(parent。 getContext())。inflate(R.layout.ad_express,parent,false);
最终NativeExpressAdViewHolder viewHolder = new NativeExpressAdViewHolder(
视图,
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();
//做某事
}
});
viewHolder.loadAd(cardWidthInDips);

return viewHolder;
}


解决方案

我不知道你在哪里实际上在您的代码中实现了 RecyclerView ,但是无论如何,这可能在您的情况下可行。



GridView 相似的问题总是在 Fragment 第一次加载期间获得焦点,它也自动向下滚动到 GridView



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

  android:descendantFocusability = blocksDescendants 

此行基本上意味着父级布局的所有后代将不再获得焦点。您可以在 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.

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

解决方案

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.

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.

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

android:descendantFocusability="blocksDescendants"

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滚动以使其在首次加载时完全可见的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆