奇葩布局:RecyclerView+Webview的布局,如何使之连贯滑动

场景:列表+webview的布局 会出现滑动分割,各自滑动自己的,没法连贯性滑动。有没有一个支持整体滑动的库呢?

产品需要实现的场景:

  • 列表可见时,整体可滑动
  • 列表不可见,滑动到webview,webview自己滑动
  • webview要支持下拉,把列表下拉显示

第三方库:ConsecutiveScroller

ConsecutiveScrollerLayout是Android下支持多个滑动布局(RecyclerView、WebView、ScrollView等)
和普通控件(TextView、ImageView、LinearLayou、自定义View等)持续连贯滑动的容器,
它使所有的子View像一个整体一样连续顺畅滑动。并且支持布局吸顶功能。

1.布局

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/ll_default_recyclerview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical"
    android:descendantFocusability="blocksDescendants"
    >
<!-- 使用ConsecutiveScrollerLayout -->
<com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout
    android:id="@+id/scroller_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical"
    >
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
    <cn.szy.yd.education.publishresource.view.MyDSBridgeWebView
        android:id="@+id/wv_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout>
</LinearLayout>

2.要处理的问题

  • webview内容为空的时候,整体滑动
  • webview要可滑动,需要设置一个固定的高度
  • webview有内容时,列表如果可见,就整体滑动;如果列表不可见就webview自己滑动
  • webview刷新后,会自动滑动到top=0(顶部),这时webview没办法下拉,所以需要设置1px的偏移量(scrollTo)
  • 需要h5回传webview内容高度,根据高度来控制是否整体滑动

3.代码

webview使用的是腾讯的X5WebView,需要实现重写scrollTo方法。底部有附上代码,可参考。

package cn.szy.yd.education.find.ui;

import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.ad.AdsConstant;
import com.alibaba.fastjson.JSONObject;
import com.donkingliang.consecutivescroller.ConsecutiveScrollerLayout;
import com.shenzy.trunk.libflog.FLog;
import com.szy.common.bean.PathBean;
import com.szy.common.constant.Net;
import com.szy.common.handler.CommonHandler;
import com.szy.common.handler.IHandlerMessage;
import com.szy.common.message.MessageUtil;
import com.szy.common.statistcs.UmengStatistics;
import com.szy.common.utils.ArrayUtils;
import com.szy.common.utils.DataParserUtil;
import com.szy.common.utils.LogUtil;
import com.szy.common.utils.PathManage;
import com.szy.subscription.parentschool.constant.FindConstant;
import com.szy.subscription.search.ui.activity.ParentSearchActivity;
import com.szy.szyad.bean.AdvBean;
import com.szy.szyad.bean.CoordinateBean;
import com.szy.ui.uibase.adapter.BaseRecyclerAdapter;
import com.szy.ui.uibase.adapter.BaseViewHolder;
import com.szy.ui.uibase.bean.BaseBean;
import com.szy.ui.uibase.widget.ToolBarView;
import com.szy.zth_camera.util.ScreenUtils;
import com.tencent.smtt.sdk.WebChromeClient;
import com.tencent.smtt.sdk.WebView;
import com.yuanding.seebaby.R;
import com.yuanding.seebaby.startup.utils.UserDataManager;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import cn.szy.yd.education.find.adapter.RecommendMultiViewTypeAdapter;
import cn.szy.yd.education.find.bean.BaseRecommendItemBean;
import cn.szy.yd.education.find.bean.DailyRecommendBean;
import cn.szy.yd.education.find.bean.PlateContentContentBean;
import cn.szy.yd.education.find.bean.PlateHeaderBean;
import cn.szy.yd.education.find.bean.PlateSubjectContentBean;
import cn.szy.yd.education.find.bean.RecommendAuthBean;
import cn.szy.yd.education.find.bean.RecommendBannerBean;
import cn.szy.yd.education.find.bean.RecommendBannerItemBean;
import cn.szy.yd.education.find.bean.RecommendShortcutBean;
import cn.szy.yd.education.find.bean.type.FindRecommendViewType;
import cn.szy.yd.education.find.contract.RecommendContract;
import cn.szy.yd.education.find.count.FindRecommendCount;
import cn.szy.yd.education.find.inter.OnDailyRecommendOperateListener;
import cn.szy.yd.education.find.presenter.RecommendPresenter;
import cn.szy.yd.education.find.utils.FindJumpUtil;
import cn.szy.yd.education.publishresource.constant.RefreshEducationVideoListEvent;
import cn.szy.yd.education.publishresource.constant.WebviewLoadedEvent;
import cn.szy.yd.education.publishresource.count.PublishResourceCount;
import cn.szy.yd.education.publishresource.ui.PublishResourceActivity;
import cn.szy.yd.education.publishresource.utils.AppToJsUtils;
import cn.szy.yd.education.publishresource.view.MyDSBridgeWebView;
import cn.szy.yd.education.publishresource.view.MyX5WebView;
import cn.szy.yd.garden.coursealbum.bean.BannerModel;
import cn.szy.yd.garden.coursealbum.bean.CombBean;
import cn.szy.yd.garden.coursealbum.bean.ShortcutBean;
import cn.szy.yd.garden.coursealbum.listener.SchoolBannerPagerListener;
import cn.szy.yd.garden.coursealbum.listener.ShortcutItemClickListener;
import cn.szy.yd.garden.media.constant.CountConstants;
import cn.szy.yd.homenew.count.BannerCount;
import cn.szy.yd.homenew.tab.work.constant.ContentTypeConstant;
import cn.szy.yd.homenew.tab.work.constant.DataConstant;
import cn.szy.yd.homenew.utils.BannerJump;
import cn.szy.yd.homenew.utils.ad.ADReport;
import cn.szy.yd.homenew.utils.ad.AdJump;
import cn.szy.yd.uibase.ui.activity.BaseGardenActivity;
import cn.szy.yd.uibase.ui.fragment.BaseGardenListFragment;
import cn.szy.yd.util.SPUtil;
import cn.szy.yd.utils.ClickUtil;
import cn.szy.yd.utils.Utils;

/**
 * 优教页面
 * Created by yanxw on 2018/9/5.
 */

public class RecommendFragment extends BaseGardenListFragment<RecommendMultiViewTypeAdapter, RecommendPresenter> implements RecommendContract.IView, IHandlerMessage, OnDailyRecommendOperateListener<BaseRecommendItemBean> {

    public static final String TAG = "RecommendFragment";

    private String FIRST_USE_UPLOAD_RESOURCE = "first_use_upload_resource";

    boolean isFirstShow = true;


    private LinearLayoutManager layoutManager;

    private CommonHandler commonHandler;

    private String page_location = ""; //记录当前页面的触发位置

    private ImageView ivDailyRecommend;
    private LinearLayout llUpload;
    // 上传素材
    private TextView ivPublish;
    private ImageView ivGuide;
    private ConsecutiveScrollerLayout scrollerLayout;
    // 信息流
    private MyDSBridgeWebView wvInfoFeed;

    private CountDownTimer showTimer;
    // 短视频信息流h5地址
    private String infoFeedUrl = "";
    // 是否允许把滚动事件分发给webview
    private boolean isAllowDispatchScrollToWebview = true;
    // 是否自动滚动
    private boolean isAutoScroll = false;
    private int offset = 0;

    @Override
    protected int getLayoutResId() {
        return R.layout.fragment_recommend;
    }

    @Override
    public boolean enabledVisibleToolBar() {
        return true;
    }

    @Override
    public ToolBarView.ToolBarBg initCommonToolBarBg() {
        return ToolBarView.ToolBarBg.WHITE;
    }

    @Override
    public RecommendMultiViewTypeAdapter initRecyclerAdapter() {
        return new RecommendMultiViewTypeAdapter();
    }

    @Override
    protected RecommendPresenter initPresenter() {
        return new RecommendPresenter();
    }

    @Override
    public void statusLayoutRetry(View view) {
        super.statusLayoutRetry(view);
        hideStatusLayout();
        autoRefresh();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MessageUtil.regist(this);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
    }

    @Override
    public void initView(View rootView, @Nullable Bundle savedInstanceState) {
        super.initView(rootView, savedInstanceState);
        commonHandler = new CommonHandler(this);
        // 设置标题
        setToolBarTitle(R.string.find);
        // 设置标题栏的分割线 不显示
        setToolBarBottomLineVisible(false);
        initRecycleView();
        llUpload = rootView.findViewById(R.id.ll_upload);
        ivPublish = rootView.findViewById(R.id.iv_publish);
        ivGuide = rootView.findViewById(R.id.iv_guide);
        scrollerLayout = rootView.findViewById(R.id.scroller_layout);
        scrollerLayout.setVerticalScrollBarEnabled(false);
        wvInfoFeed = rootView.findViewById(R.id.wv_view);
        ivPublish.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                PublishResourceCount.evUploadInClick();
                PublishResourceActivity.start(getGardenActivity(), null);
            }
        });

        initSearchView();
        initWebview();
        handlePublishGuide();

        // 初始化后需要设置下上传素材按钮的margin,避免控件还没初始化先调用handleUploadLocation无效
        handleUploadLocation(this.offset);
    }

    /**
     * 会跟迷你音频播放器,大咖直播课View的位置冲突,测试需要注意复现下
     */
    public void handleUploadLocation(int offset){
        this.offset = offset;
        LogUtil.e("handleUploadLocation", "offset="+offset);
        if (llUpload == null)
            return;
        FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) llUpload.getLayoutParams();
        layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin, layoutParams.rightMargin, ScreenUtils.dip2px(getGardenActivity(),offset));
        llUpload.setLayoutParams(layoutParams);
    }

    /**
     * 处理第一次使用上传素材,显示引导
     */
    private void handlePublishGuide() {
        boolean isFirstUse = SPUtil.loadBoolean(FIRST_USE_UPLOAD_RESOURCE);
        if(isFirstUse){
            ivGuide.setVisibility(View.GONE);
        }else{
            ivGuide.setVisibility(View.VISIBLE);
            // 显示4秒消失
            startShowTimer();
        }
    }

    /**
     * 显示引导图片倒计时
     */
    private void startShowTimer() {
        showTimer = new CountDownTimer(4000, 500) {
            @Override
            public void onTick(long millisUntilFinished) {

            }

            @Override
            public void onFinish() {
                ivGuide.setVisibility(View.GONE);
                SPUtil.record(FIRST_USE_UPLOAD_RESOURCE,true);
                cancelShowTimer();
            }
        };
        showTimer.start();
    }

    private void cancelShowTimer() {
        try {
            if (null != showTimer) {
                showTimer.cancel();
                showTimer = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 获取信息流h5地址
    private String getInfoFeedUrl() {
        String url = UserDataManager.getInstance().getRetBasicsInfo().getUgcInfoFeedListUrl();
        // 测试
//        url = "http://172.16.40.249:8088/ugc/index";
        return url;
    }

    private void setScrollerLayoutParams(boolean isParentScroll) {
        ConsecutiveScrollerLayout.LayoutParams lp = (ConsecutiveScrollerLayout.LayoutParams) wvInfoFeed.getLayoutParams();
        if (lp.isConsecutive != isParentScroll) {
            lp.isConsecutive = isParentScroll;
        }
        wvInfoFeed.setLayoutParams(lp);
        LogUtil.e("webview-isConsecutive", lp.isConsecutive+"");
    }

    private void setWebviewHeight() {
        // webview高度=屏幕高度-列表高度-底部tab高度-toolbar高度
        int height = ScreenUtils.getScreenHeight(getGardenActivity()) - getRecyclerView().getHeight()
                - ScreenUtils.dip2px(getGardenActivity(), 50f) * 2;
        wvInfoFeed.setWebViewHeight(Math.abs(height));
    }

    private void initWebview() {
        final MyX5WebView webView =  wvInfoFeed.getWebView();
        scrollerLayout.setOnVerticalScrollChangeListener(new ConsecutiveScrollerLayout.OnScrollChangeListener() {
            @Override
            public void onScrollChange(View view, int scrollY, int oldScrollY, int scrollState) {
                LogUtil.e("scrollerLayout-onScrollChange", "oldScrollY="+oldScrollY+", scrollY="+scrollY);
                handleScroll();
                if (scrollerLayout.isScrollBottom()) {
                    // webview 滑动1个偏移量,使之可以下拉
                    LogUtil.e("scrollerLayout-onScrollChange", "滑动到底部");
                    webView.scrollTo(0,1);
                }
            }
        });
        webView.setScrollChangedListener(new MyX5WebView.ScrollChangedListener() {
            @Override
            public void onScrollChanged(int l, int t, int oldl, int oldt, View view) {
                LogUtil.e("webView-onScrollChanged", "l="+l+", t="+t+", oldl="+oldl+", oldt="+oldt);
                if (t == 0) {
                    //滑动到webview的顶部 h5页面点击标签也会调到
                    setScrollerLayoutParams(true);
                }else if ( t > 0) {
                    handleScroll();
                }
            }
        });

        infoFeedUrl = getInfoFeedUrl();
        setWebviewHeight();
        // WebView在加载的过程中如果滑动的布局,可能会导致WebView与其他View在显示上断层,使用下面的方法一定程度上可以避免这个问题。
        wvInfoFeed.getWebView().setWebChromeClient(new WebChromeClient() {
            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                scrollerLayout.checkLayoutChange();
            }
        });
        wvInfoFeed.loadUrl(infoFeedUrl);
    }

    private void resetWebview() {
        wvInfoFeed.getWebView().reload();
    }

    private void initSearchView() {
        // 添加搜索UI为列表的头部View
        View searchView = LayoutInflater.from(getGardenActivity()).inflate(R.layout.item_search_view, null);
        LinearLayout llSearch = searchView.findViewById(R.id.ll_search);
        ivDailyRecommend = searchView.findViewById(R.id.iv_daily_recommend);
        if (UserDataManager.getInstance().isTeacher()){
            ivDailyRecommend.setImageResource(R.drawable.icon_school_garden);
        }else {
            ivDailyRecommend.setImageResource(R.drawable.icon_garder_speak);
        }
        View.OnClickListener clickListener = new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 优教搜索
                if (view.getId() == R.id.iv_daily_recommend) {
                    PublishResourceCount.evTeacherShareClick();
                    DailyRecommendHistoryActivity.start(getGardenActivity());
                } else if (view.getId() == R.id.ll_search) {
                    PublishResourceCount.evTeacherSearchClick();
                    ParentSearchActivity.jump(getGardenActivity());
                }
            }
        };
        llSearch.setOnClickListener(clickListener);
        ivDailyRecommend.setOnClickListener(clickListener);
        getAdapter().addHeaderView(searchView);
    }

    @Override
    protected void onVisible() {
        super.onVisible();
        if (!isPush()) {
            //说明:如果是从push跳转,此时更新了pathdata,就会造成跳转的二级页面,无法知道来源是从path过来的。
            LogUtil.i(TAG, "onVisible updatePathData() ... ");
            PathManage.getInstance().updatePathData(getGardenActivity().getPathId(), CountConstants.PV_FIND, "", page_location, "1");
        }
        fragmentPageShow();
    }

    @Override
    protected void onInVisible() {
        super.onInVisible();
        fragmentPageHide();
    }

    private boolean isPush() {
        PathBean fromPathData = PathManage.getInstance().getFromPathData(getGardenActivity().getPathId());
        if (fromPathData != null) {
            return fromPathData.getStartType() == PathManage.STARTTYPE_PUSH;
        }
        return false;
    }

    private void initRecycleView() {
        layoutManager = (LinearLayoutManager) getRecyclerView().getLayoutManager();
        getAdapter().setOnItemChildHolderClickListener(new BaseRecyclerAdapter.OnItemChildHolderClickListener<BaseBean, BaseViewHolder>() {
            @Override
            public void onItemChildClick(BaseViewHolder baseViewHolder, BaseBean baseBean, View view, int i) {
                if (ClickUtil.isFastClick()) {
                    return;
                }
                page_location = "block";
                PathManage.getInstance().updatePathData(getGardenActivity().getPathId(), CountConstants.PV_FIND, "", page_location, "1");
            }
        });

        getAdapter().setOnItemHolderClickListener(new BaseRecyclerAdapter.OnItemHolderClickListener<BaseBean, BaseViewHolder>() {
            @Override
            public void onItemClick(BaseViewHolder baseViewHolder, BaseBean baseBean, View view, int i) {
                if (ClickUtil.isFastClick()) {
                    return;
                }
                page_location = "block";
                PathManage.getInstance().updatePathData(getGardenActivity().getPathId(), CountConstants.PV_FIND, "", page_location, "1");
            }
        });

        getAdapter().setBannerListener(new SchoolBannerPagerListener() {
            @Override
            public void onBannerItemClickListener(BannerModel<BaseBean> currentBannerModel, CoordinateBean coordinateBean) {
                try {
                    if (ClickUtil.isFastClick() || null == currentBannerModel) {
                        return;
                    }
                    page_location = "focus";
                    PathManage.getInstance().updatePathData(getGardenActivity().getPathId(), CountConstants.PV_FIND, "", page_location, "1");
                    if (currentBannerModel.getItem() instanceof RecommendBannerItemBean) {
                        RecommendBannerItemBean itemBean = (RecommendBannerItemBean) currentBannerModel.getItem();
                        BannerJump.jump(getActivity(), DataParserUtil.parseAsJSONObject(itemBean.getData()), FindRecommendCount.PAGE_LOCATION_FOCUS);
                    } else if (currentBannerModel.getItem() instanceof AdvBean) {
                        AdvBean advBean = (AdvBean) currentBannerModel.getItem();
                        AdJump.advClickEvent(advBean, coordinateBean);
                        AdJump.onClickJump(getActivity(), advBean, CountConstants.PV_FIND);
                    }
                } catch (Exception e) {
                    LogUtil.e("recommandfragment", e.getMessage());
                    FLog.getInstance().getErr().e("recommandfragment", e.getMessage(), "");
                }
            }

            @Override
            public void onBannerPageSelected(int position, BannerModel<BaseBean> currentBannerModel) {
                LogUtil.i("BannerPage", "onBannerPageSelected  position=" + position);
                if (currentBannerModel.getItem() instanceof AdvBean) {
                    bannerExporesd((AdvBean) currentBannerModel.getItem());
                }
            }
        });
        getAdapter().setShortcutItemClickListener(new ShortcutItemClickListener() {
            @Override
            public void shortcutItemClick(int pos, ShortcutBean module, View view) {
                try {
                    if (ClickUtil.isFastClick()) {
                        return;
                    }
                    page_location = "icon";
                    PathManage.getInstance().updatePathData(getGardenActivity().getPathId(), CountConstants.PV_FIND, "", page_location, "1");
                    BannerJump.jump(getActivity(), DataParserUtil.parseAsJSONObject(module.getData()), FindRecommendCount.PAGE_LOCATION_ICON);
                } catch (Exception e) {
                    LogUtil.e("recommandfragment", "jump shortcut fail:" + e != null ? e.getMessage() : "");
                    FLog.getInstance().getErr().e("recommandfragment", "jump shortcut fail:" + e != null ? e.getMessage() : "", "");
                }

            }
        });

        getRecyclerView().addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                if (0 == newState) {
                    try {
                        int pathId = 0;
                        FragmentActivity activity = getActivity();
                        if (activity instanceof BaseGardenActivity) {
                            pathId = ((BaseGardenActivity) activity).getPathId();
                        }
                        //滑动结束上报展示的内容
                        FindRecommendCount.countBlockShow(pathId);
                        FindRecommendCount.countBlockContentShow(pathId);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                checkRecycleView();
            }
        });
    }


    //banner曝光
    private void bannerExporesd(AdvBean advBean) {
        if (null == advBean) {
            return;
        }
        if (null == layoutManager) {
            return;
        }
        if (layoutManager.findFirstVisibleItemPosition() > 0) {
            LogUtil.e("Banner", "广告被遮挡=" + layoutManager.findFirstVisibleItemPosition());
            return;
        }
        if (!advBean.isExposed()) {
            advBean.setExposed(true);
            ADReport.adExposuredReport(advBean);
            BannerCount.adCount(AdsConstant.AdCountStatus.STATUS_5, advBean, DataConstant.FEED_SPACE_ID, 0f);
        }
    }

    @Override
    public void handlerCallback(Message msg) {
        switch (msg.what) {
            case FindConstant.CHECK_RECYCLEVIEW:
                try {
                    int pathId = 0;
                    FragmentActivity activity = getActivity();
                    if (activity instanceof BaseGardenActivity) {
                        pathId = ((BaseGardenActivity) activity).getPathId();
                    }
                    //上报展示的内容
                    FindRecommendCount.countBlockShow(pathId);
                    FindRecommendCount.countBlockContentShow(pathId);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
        }
    }

    private void jumpDetail(Object object) {
        if (object instanceof PlateContentContentBean) {
            PlateContentContentBean bean = (PlateContentContentBean) object;
            PlateContentContentBean.Extra extra = bean.getExtra();
            String singleAlbumId = "";
            if (extra != null) {
                //单音视频数据,需要从extra字段取出albumId
                singleAlbumId = extra.getAlbumId();
            }
            FindJumpUtil.jumpDetailActivity(getActivity(), bean.getContentType(), bean.getContentId(), singleAlbumId, String.valueOf(bean.getPlateId()), FindRecommendCount.PAGE_LOCATION_BLOCK);
        }
    }

    @Override
    public void initLazyData() {
        super.initLazyData();
        getPresenter().loadCacheData();
    }

    public void fragmentPageShow() {
        try {
            if (getSmartRefreshLayout() != null && getAdapter() != null) {
                startAutoPlay();
                reportPv(true);
                if (isFirstShow) {
                    isFirstShow = false;
                    // umeng出现getSmartRefreshLayout空的时候,doRefresh内部报错
                    showLoadDialog();
                    doRefresh();
                    UmengStatistics.onEventValue(getContext(), FindRecommendCount.PAGE_DISCOVER);
                }
            } else {
                //该页面设为落地页的时候,初始化会没完成,会重新再initLazyData重新调用
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void fragmentPageHide() {
        try {
            stopAutoPlay();
            reportPv(false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void reportPv(boolean isStart) {
        if (isStart) {
            FindRecommendCount.pvDiscover(isStart, 0f, getGardenActivity().getPathId());
        } else {
            FindRecommendCount.pvDiscover(isStart, getStayTime(), getGardenActivity().getPathId());
        }
    }

    /**
     * 请求接口
     * @param page
     */
    @Override
    protected void doHttpRequest(int page) {
        try {
            super.doHttpRequest(page);
            if (isFirstPage()) {
                // 下拉刷新才去重新刷新banner、子频道
                getPresenter().getShortcurData();
                // 刷新weibview
                resetWebview();
            }
            FindRecommendCount.clickEvent(getGardenActivity(), FindRecommendCount.REFRESH_RECOMMEND_TRY, "discover", "");
            UmengStatistics.onEventValue(getContext(), FindRecommendCount.REFRESH_RECOMMEND_TRY);
            getPresenter().loadClassList();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    protected int startPage() {
        return 0;
    }

    @Override
    public void onShortcurDataSuccess(ArrayList<ShortcutBean> bean) {
        resetShortcut(bean);
    }

    @Override
    public void onBannerDataSuccess(ArrayList<BaseBean> bean) {
        resetBanner(bean);
    }

    @Override
    public void onDailyRecommendDataSuccess(DailyRecommendBean bean, boolean isShowMask) {
        if (bean != null) {
            if (Utils.isEmpty(bean.getDatas())) {
                ivDailyRecommend.setVisibility(View.GONE);
            } else {
                ivDailyRecommend.setVisibility(View.VISIBLE);
            }
        } else {
            // 没有每日推荐数据 关掉入口
            ivDailyRecommend.setVisibility(View.GONE);
        }
    }

    @Override
    public void setData(List<BaseBean> list) {
        if (list != null) {
            setAdapterData(list);
        }
        if (isFirstPage()) {
            getPresenter().resetShortcurData();
            getAdapter().setTopPosition(haveShortcut() + 1);
            if (null != commonHandler) {
                commonHandler.sendEmptyMessageDelayed(FindConstant.CHECK_RECYCLEVIEW, 200);
            }

        }
    }

    @Override
    public void hideLoadDialog() {
        hideProgressDialog();
    }

    @Override
    public void showLoadDialog() {
        showProgressDialog();
    }

    @Override
    public void changeDailyRecommendSuccess() {
        if (getAdapter() == null) {
            return;
        }
        commonHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                getAdapter().notifyDataSetChanged();
            }
        }, 300);

    }

    @Override
    public void onDailyRecommendAuthSuccess(RecommendAuthBean bean, int authType) {

    }

    @Override
    public void dismissloadMore() {
        loadComplete();
    }

    @Override
    public void showNoMore() {
        loadComplete();
        loadMoreEnd(true);
    }

    @Override
    public void showEmpty() {
        if (isRefresh()) {
            setData(null);
            //没有banner跟快捷键的时候,才能显示空界面
            if (haveBannerItem() == -1 && haveShortcut() == -1) {
                showEmptyLayout();
            } else {
                showNoMore();
            }
        } else {
            showNoMore();
        }
    }

    @Override
    public void showError(int code) {
        if (isRefresh()) {
            if (getAdapter().getDataCount() == getAdapter().getLoadMoreViewCount()) {
                setData(null);
                switch (code) {
                    case Net.HttpErrorCode.NET_DISCONNECT:
                    case Net.HttpErrorCode.NET_TIMEOUT:
                        showNetErrorLayout();
                        break;
                    default:
                        showLoadErrorLayout();
                        break;
                }
            } else {
                loadMoreFail();
            }
        } else {
            loadMoreFail();
        }
    }


    /**
     * FeedL
     * 刷新快捷入口
     */
    private void resetShortcut(ArrayList<ShortcutBean> shortcutBeans) {
        List<BaseBean> datas = getAdapter().getData();
        if (ArrayUtils.isEmpty(shortcutBeans)) {//接口没有返回快捷入口
            if (!ArrayUtils.isEmpty(datas)) {
                for (Iterator<BaseBean> iterator = datas.iterator(); iterator.hasNext(); ) {
                    BaseBean baseBean = iterator.next();
                    // 找到快捷方式并删除adater 项
                    if (baseBean.getViewType() == FindRecommendViewType.TYPE_SHORTCUT) {
                        iterator.remove();
                        getAdapter().notifyDataSetChanged();
                        return;
                    }
                }
            }
            return;
        }
        filterShortcut(shortcutBeans);
        hideStatusLayout();
        RecommendShortcutBean shortcutBean = new RecommendShortcutBean();
        shortcutBean.setIconList(shortcutBeans);
        if (haveShortcut() == -1) {
            int insterPos = haveBannerItem() + 1;
            datas.add(insterPos, shortcutBean);
        } else {
            datas.set(haveShortcut(), shortcutBean);
        }
        getAdapter().setShortcutRefresh();
        getAdapter().notifyDataSetChanged();
    }

    /**
     * 6.11.1
     * 过滤掉不满足显示条件的,比如教学资料库,需要当前关联学校已开通超级园长会员的才显示
     *
     * @param shortcutBeans
     */
    private void filterShortcut(ArrayList<ShortcutBean> shortcutBeans) {
        ArrayList<ShortcutBean> removeList = null;
        if (shortcutBeans == null) {
            return;
        }
        for (ShortcutBean bean : shortcutBeans) {
            if (bean == null || bean.getData() == null || TextUtils.isEmpty(bean.getData())) {
                continue;
            }
            JSONObject jsonObject = DataParserUtil.parseAsJSONObject(bean.getData());
            String contentType = DataParserUtil.getJsonStr(jsonObject, "type");
            if (ContentTypeConstant.CONTENT_TYPE_EDUCATION_DATABASE.equals(contentType)) {
                boolean vipStatus = UserDataManager.getInstance().getVipStatus();
                LogUtil.d(TAG, "RecommendFragment  vipStatus=" + vipStatus);
                if (!vipStatus) {
                    if (removeList == null) {
                        removeList = new ArrayList<>();
                    }
                    removeList.add(bean);
                }
            }
        }
        if (removeList != null) {
            shortcutBeans.removeAll(removeList);
        }
    }

    /**
     * 移动至指定位置
     *
     * @param position
     */
    private void moveToPosition(int position) {
        RecyclerView recyclerView = getRecyclerView();
        if (recyclerView == null) {
            LogUtil.d(TAG, "recyclerView == null , 无效操作!");
        }
        if (position != -1) {
            recyclerView.scrollToPosition(position);
            LinearLayoutManager mLayoutManager =
                    (LinearLayoutManager) recyclerView.getLayoutManager();
            if (mLayoutManager == null) {
                LogUtil.d(TAG, "mLayoutManager == null , 无效操作!");
                return;
            }
            mLayoutManager.scrollToPositionWithOffset(position, 0);
        }
    }

    /**
     * 刷新banner
     */
    private void resetBanner(ArrayList<BaseBean> bannerBeans) {
        List<BaseBean> datas = getAdapter().getData();
        if (ArrayUtils.isEmpty(bannerBeans)) {//接口没有返回焦点图
            if (datas.size() > 0 && datas.get(0).getViewType() == FindRecommendViewType.TYPE_BANNER) {
                datas.remove(0);
                getAdapter().notifyDataSetChanged();
            }
            return;
        }
        hideStatusLayout();
        getAdapter().pullToUpdateState();
        RecommendBannerBean bannerBean = new RecommendBannerBean();
        bannerBean.setFrist(true);
        bannerBean.setList(bannerBeans);
        if (datas.size() == 0) {//列表为空的时候
            getAdapter().addData(bannerBean);
        } else if (datas.get(0).getViewType() == FindRecommendViewType.TYPE_BANNER) {//如果在队列中
            getAdapter().setData(0, bannerBean);
        } else {//不在队列中
            getAdapter().addData(0, bannerBean);
        }
    }

    /**
     * 队列中是否有banner
     *
     * @return 如果没有则返回 -1
     */
    public int haveBannerItem() {
        List<BaseBean> datas = getAdapter().getData();
        if (datas != null && datas.size() > 0 && datas.get(0).getViewType() == FindRecommendViewType.TYPE_BANNER) {
            return 0;
        }
        return -1;
    }

    /**
     * 队列中是否有Shortcut
     *
     * @return 如果没有则返回 -1
     */
    public int haveShortcut() {
        List<BaseBean> datas = getAdapter().getData();
        if (datas != null) {
            for (int i = 0; i < datas.size(); i++) {
                if (datas.get(i).getViewType() == FindRecommendViewType.TYPE_SHORTCUT) {
                    return i;
                }
            }
        }
        return -1;
    }

    public void startAutoPlay() {
        if (getAdapter() != null) {
            getAdapter().startAutoPlay();
        }
    }

    public void stopAutoPlay() {
        if (getAdapter() != null) {
            getAdapter().stopAutoPlay();
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        stopAutoPlay();
        MessageUtil.unregist(this);
        cancelShowTimer();
    }

    /**
     * 检查显示的内容
     */
    private void checkRecycleView() {
        try {
            if (null == layoutManager) {
                return;
            }
            int firstPosition = layoutManager.findFirstVisibleItemPosition();
            recordBlockShow(firstPosition);
            int lastPosition = layoutManager.findLastVisibleItemPosition();
            recordBlockShow(lastPosition);
            //列表中完全显示的View
            for (int completePos = firstPosition + 1; completePos < lastPosition; completePos++) {
                recordBlockShow(completePos);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 记录板块展现过得信息
     */
    public void recordBlockShow(int position) {
        List<BaseBean> datas = getAdapter().getData();
        if (ArrayUtils.isEmpty(datas) || datas.size() <= position) {
            return;
        }
        //专题板块,内容板块
        if ((datas.get(position).getViewType() == FindRecommendViewType.TYPE_PLATE_SUBJECT_HEAD
                || datas.get(position).getViewType() == FindRecommendViewType.TYPE_PLATE_CONTENT_HEAD)
                && datas.get(position) instanceof PlateHeaderBean) {
            FindRecommendCount.addShowBlockId(((PlateHeaderBean) datas.get(position)).getContentType(),
                    ((PlateHeaderBean) datas.get(position)).getId());

        } else if (datas.get(position).getViewType() == FindRecommendViewType.TYPE_PLATE_SUBJECT_CONTENT
                && datas.get(position) instanceof PlateSubjectContentBean) {
            //专题板块-内容
            FindRecommendCount.addShowBlockContentId(((PlateSubjectContentBean) datas.get(position)).getContentType(),
                    ((PlateSubjectContentBean) datas.get(position)).getContentId());
        } else if (datas.get(position).getViewType() == FindRecommendViewType.TYPE_PLATE_CONTENT_MAIN_PUSH
                || datas.get(position).getViewType() == FindRecommendViewType.TYPE_PLATE_CONTENT_CONTENT) {
            //内容板块-内容
            //主推
            if (datas.get(position) instanceof PlateContentContentBean) {
                FindRecommendCount.addShowBlockContentId(((PlateContentContentBean) datas.get(position)).getContentType(),
                        ((PlateContentContentBean) datas.get(position)).getContentId());
            } else if (datas.get(position) instanceof CombBean) {
                //2个内容
                CombBean<PlateContentContentBean> mCombBean = ((CombBean) datas.get(position));
                for (PlateContentContentBean bean : mCombBean.getDatas()) {
                    FindRecommendCount.addShowBlockContentId(bean.getContentType(),
                            bean.getContentId());
                }
            }
        } else if (datas.get(position).getViewType() == FindRecommendViewType.TYPE_PLATE_CONTENT_MAIN_RIGHT
                || datas.get(position).getViewType() == FindRecommendViewType.TYPE_PLATE_CONTENT_CONTENT_RIGHT) {
            //内容板块-内容-左文右图
            //主推-左文右图
            if (datas.get(position) instanceof PlateContentContentBean) {
                FindRecommendCount.addShowBlockContentId(((PlateContentContentBean) datas.get(position)).getContentType(),
                        ((PlateContentContentBean) datas.get(position)).getContentId());
            }
        }

    }

    @Override
    public void publishSuccess(BaseRecommendItemBean itemBean) {

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    private void handleScroll() {
        View firstView = scrollerLayout.findFirstVisibleView();
        // 只要recyclerview是可见的 就把滚动交给父控件
        if (firstView != null && (firstView instanceof RecyclerView)) {
            setScrollerLayoutParams(true);
        }else {
            if (isAllowDispatchScrollToWebview) {
                setScrollerLayoutParams(false);
            } else {
                setScrollerLayoutParams(true);
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onRefreshEducationVideoList(RefreshEducationVideoListEvent event) {
        if (event != null) {
            int type = event.type;
            LogUtil.d(TAG, " onRefreshEducationVideoList-type=" + type);
            if (type == 0) {
                AppToJsUtils.updateIndexTab("1", wvInfoFeed.getWebView());
            } else if (type == 1) {
                AppToJsUtils.updateListData(wvInfoFeed.getWebView());
            }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onWebviewLoaded(WebviewLoadedEvent event) {
        LogUtil.d(TAG, " onWebviewLoaded()");
        if (event != null) {
           // 判断webview的内容是否有超过1屏 内容高度<=webview高度
            int contentHeight = event.height;
            int webviewHeight = wvInfoFeed.getWebView().getHeight();
            LogUtil.e("onWebviewLoaded", "contentHeight="+contentHeight+", webviewHeight="+webviewHeight);
            if (contentHeight <= webviewHeight) {
                isAutoScroll = false;
                isAllowDispatchScrollToWebview = false;
            }else{
                isAllowDispatchScrollToWebview = true;
                isAutoScroll = true;
            }
            if (isAutoScroll) {
                wvInfoFeed.getWebView().scrollTo(0, 1);
                isAutoScroll = false;
            }
            handleScroll();
        }
    }

    @Override
    public void change(BaseRecommendItemBean bean) {

    }

    @Override
    public void changeModel(int authType) {

    }

    @Override
    public void akeyForward(BaseRecommendItemBean bean) {

    }
}

MyX5WebView.java

package cn.szy.yd.education.publishresource.view;

import android.content.Context;
import android.os.Build;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewParent;
import android.widget.AbsListView;
import android.widget.HorizontalScrollView;
import android.widget.ScrollView;

import com.donkingliang.consecutivescroller.IConsecutiveScroller;

import java.util.ArrayList;
import java.util.List;

import cn.szy.yd.web.X5WebView;

/**
 * 由于腾讯x5的VebView是一个FrameLayout嵌套WebView的布局,而不是一个WebView的子类,
 * 所以要在ConsecutiveScrollerLayout里使用它,需要把它的滑动交给它里面的WebView。
 * 自定义MyWebView继承腾讯的WebView,重写它的scrollBy()方法即可。
 */
public class MyX5WebView extends X5WebView{

    private ScrollChangedListener scrollChangedListener;

    public MyX5WebView(Context arg0, AttributeSet arg1) {
        super(arg0, arg1);
        init();
    }

    public MyX5WebView(Context arg0) {
        super(arg0);
        init();
    }

    private void init() {
        View view = getView();
        view.setVerticalScrollBarEnabled(false);
        view.setHorizontalScrollBarEnabled(false);
        view.setOverScrollMode(OVER_SCROLL_NEVER);
    }

    @Override
    public void scrollBy(int x, int y) {
       // 把滑动交给它的子view
        getView().scrollBy(x, y);
    }

    @Override
    public void scrollTo(int x, int y) {
        // 把滑动交给它的子view
        getView().scrollTo(x, y);
    }

    // 重写以下方法,解决和viewpager滑动冲突 但是会导致ConsecutiveScrollerLayout的滑动无效 弃用
//    @Override
//    protected void tbs_onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY, View view) {
//        if (clampedX) {
//            ViewParent viewParent = findViewParentIfNeeds(this);
//            viewParent.requestDisallowInterceptTouchEvent(false);
//        }
//        super.tbs_onOverScrolled(scrollX, scrollY, clampedX, clampedY, view);
//    }
//
//    @Override
//    public boolean tbs_onTouchEvent(MotionEvent event, View view) {
//        if (event.getAction() == MotionEvent.ACTION_DOWN) {
//            ViewParent viewParent = findViewParentIfNeeds(this);
//            if (viewParent != null)
//                viewParent.requestDisallowInterceptTouchEvent(true);
//        }
//        return super.tbs_onTouchEvent(event,view);
//    }

    @Override
    protected void tbs_onScrollChanged(int l, int t, int oldl, int oldt, View view) {
        super.tbs_onScrollChanged(l, t, oldl, oldt, view);
        if(scrollChangedListener != null) {
            scrollChangedListener.onScrollChanged(l,t,oldl,oldt,view);
        }
    }

    private ViewParent findViewParentIfNeeds(View tag) {
        ViewParent parent = tag.getParent();
        if (parent == null) {
            return null;
        }
        if (parent instanceof ViewPager || parent instanceof AbsListView
                || parent instanceof ScrollView || parent instanceof HorizontalScrollView) {
            return parent;
        } else {
            if (parent instanceof View) {
                findViewParentIfNeeds((View) parent);
            } else {
                return parent;
            }
        }
        return parent;
    }

    public void setScrollChangedListener(ScrollChangedListener listener) {
        scrollChangedListener = listener;
    }


    public interface ScrollChangedListener {
        void onScrollChanged(int l, int t, int oldl, int oldt, View view);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值