我有一个奇怪的“问题”,或者可能是一个“功能”,我只是不知道,只要NativeAdExpress加载到我的RecyclerView中,如果只有部分NativeAd可见,它会强制RecyclerView滚动直到原生广告变得完全可见,这种行为导致列表在我滚动时继续跳跃。
我的布局主要是:
活动>带Tabs和ViewPager的AppBar>寻呼机中的每个页面都包含PullToRefresh,里面有一个RecyclerView, RecyclerView有两种类型的项目(Article和NativeAdExpress)。
更新:我猜测为什么会发生这种情况主要是因为原生广告在网页浏览中表达了渲染,而这个网页视图获得了焦点,然后这会导致RecyclerView滚动到它,但这只是一个猜测
更新2:显然这是支持库中的一个问题。 24.0.0,这是过于高涨的成本:(
Heres是我的完整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"
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”如下:
<?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个View Types Item和NativeAdExpress:
NativeAdExpress ViewHolder如下:
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;
}
}
}
并使用自定义适配器创建广告,如下所示:
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;
}
答案 0 :(得分:13)
我不明白你在代码中实际实现RecyclerView
的位置,但无论如何这可能是适用于你的情况。
我遇到类似的问题,GridView
始终在Fragment
首次加载时获得焦点,它也会自动向下滚动到GridView
。
经过大量测试后,我终于在GridView
的父布局上用这一行停止了这种行为:
android:descendantFocusability="blocksDescendants"
这一行基本上意味着来自父布局的所有后代都不会再获得焦点。您可以在RecyclerView
父级布局上试用它。
答案 1 :(得分:1)
我不知道它是否是问题,但看起来RecyclerView的行为从支持库23.4.0改为24.2.0。
现在不是默认为descendantFocusability = beforeDescendants,而是默认为afterDescendants,这会导致它将焦点提供给他们的孩子而不是自己的孩子。
当孩子获得焦点时,它最终会滚动以使其可见。
我通过添加android:descendantFocusability =&#34; beforeDescendants&#34;来修复它。到RecyclerView,恢复以前的行为,它保持焦点本身。
答案 2 :(得分:0)
我在使用RecyclerView滚动时遇到了类似的问题,而不是专门针对NativeAdExpress ...但 Android支持库 24.0.0 与此相关。 android:descendantFocusability =“blocksDescendants”对我不起作用。但降级到 Android支持库 23.4.0 使其重新开始工作。