Android 对Tv开发的总结

在新公司干了快一个月了,感觉对tv开发有了一定的经验。主要对recyclerview有了一定的认识。

1.调试盒子。

盒子的ip地址与电脑的ip地址保持一致

adb connect  ip地址  

adb uninstall 包名

2.焦点控制需要的一些方法。

requestFocus()  //获得焦点

setNextFocusXXX//就是让下一个按上下左右键聚焦的view

3.Recyclerview的用法

TV布局:1.如果是简单的页面(死界面),建议直接就用textview直接布局,焦点逻辑用setNextFocusXXX就可以了。像这种:

Android 对Tv开发的总结_第1张图片

动态界面:较复杂的那种,就需要自定义recyclerview,像:


主要是一个recyclerview来布局这个页面,用到recyclerview的分类,gridlayout的“合并单元格”的知识点。这个已经总结过了。下面开始总结我开发中问道的头疼的问题。

.滑动焦点错乱了

.当页面遥控器控制不了滑动了怎么办

.如何判定分页以及分页加载刷新后焦点逻辑

.删除后我的焦点该如何控制

.导航栏下来如何保存导航的状态以及第一个聚焦的始终是第一个item。

滑动焦点错乱了

.当遥控一直按住的时候,突然不知道焦点飞哪去了。

1.看看position是否在乱跳,我的主要是position乱跳导致焦点乱跳,然后我把布局都用LinearLayout限定宽高解决的

2.当遥控器按到底部的时候,如果底部还有数据但并没有显示在屏幕上,可能也会导致焦点乱跳。所以尽量让底部的界面露出来一些像上图一样。当然也可代码判断当焦点失去的时候,让页面先滑上来一些

3.什么去除recyclerview的动画以及写找不到焦点的处理方法

private void initView() {
        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
        setHasFixedSize(true);
        setWillNotDraw(true);
        setOverScrollMode(View.OVER_SCROLL_NEVER);
        setChildrenDrawingOrderEnabled(true);

        setClipChildren(false);
        setClipToPadding(false);

        setClickable(false);
        setFocusable(true);
        setFocusableInTouchMode(true);
        /**
         防止RecyclerView刷新时焦点不错乱bug的步骤如下:
         (1)adapter执行setHasStableIds(true)方法
         (2)重写getItemId()方法,让每个view都有各自的id
         (3)RecyclerView的动画必须去掉
         */
        setItemAnimator(null);
    }

onSearchFocusfailed方法百度很多,我没用到过

当页面遥控器控制不了滑动了怎么办

当遥控器向下按时没问题的,但向上按的时候滑不上去了比如下图:


此时屏幕上部应该还有数据,但并不显示在屏幕上,此时如果焦点在第一个item上,遥控器向上按就没反应,超出屏幕的部分应该是获取不到焦点的

解决方案有两种:

1.同事的方案:

package com.familybox.ui.family.widget;

import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;

/**
 * 日期:2018/4/4
 * 

* 作者:xudiwei *

* 描述:用于TV垂直方向的RecyclerView. */ public class ParentRecyclerView extends RecyclerView { private static final String TAG = "ParentSchoolRecyclerVie"; public ParentRecyclerView(Context context) { super(context); init(); } public ParentRecyclerView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public ParentRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { setClipChildren(false); setClipToPadding(false); setWillNotDraw(false); setChildrenDrawingOrderEnabled(true); } @Override public void smoothScrollBy(int dx, int dy) { if (dy > 0) { super.smoothScrollBy(dx, dy + 350); } else if (dy < 0) { super.smoothScrollBy(dx, dy - 350); } else { super.smoothScrollBy(dx, dy); } } @Override public boolean dispatchKeyEvent(KeyEvent event) { Log.d(TAG, "dispatchKeyEvent:--> "+event.isLongPress()); return super.dispatchKeyEvent(event); } private int focusViewIndex; private int focusId; /** * 自定义重绘排序,好让获取焦点的子view最后绘制,这样子view放大时不会被遮住. * * @param childCount * @param i * @return */ @Override protected int getChildDrawingOrder(int childCount, int i) { focusViewIndex = indexOfChild(getFocusedChild()); Log.d(TAG, "getChildDrawingOrder:--> Index: " + focusViewIndex); if (focusViewIndex == -1) { return i; } if (focusViewIndex == i) { focusId = i; return childCount - 1; } else if (i == childCount - 1) { return focusId; } else { return i; } } }

重写了smoothScrollby的方法,让每次recyclerview默认滑动的时候多滑一段距离。就是始终保持顶部会露出一点(有缺陷的,不适用于这个界面,适用于界面比较固定,不会有二级标题的那种

焦点搜索失败同样也处理了

package com.familybox.ui.family.widget;

import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * 日期:2018/4/8
 * 

* 作者:XXX *

* 描述:处理找不到焦点时的处理方式的GridLayoutManager */ public class FocusGridLayoutManager extends GridLayoutManager { private static final String TAG = "FocusGridLayoutManager"; public FocusGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public FocusGridLayoutManager(Context context, int spanCount) { super(context, spanCount); } public FocusGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) { super(context, spanCount, orientation, reverseLayout); } /* @Override public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { try { super.onLayoutChildren(recycler, state); } catch (IndexOutOfBoundsException e) { Log.e("probe", "meet a IOOBE in RecyclerView"); } }*/ @Override public View onFocusSearchFailed(View focused, int focusDirection, RecyclerView.Recycler recycler, RecyclerView.State state) { // ViewParent parent = focused.getParent(); // if (parent instanceof RecyclerView) { // RecyclerView recyclerView = (RecyclerView) parent; // if (focusDirection == View.FOCUS_DOWN) { // recyclerView.smoothScrollBy(0, 1); // } else if (focusDirection == View.FOCUS_UP) { // recyclerView.smoothScrollBy(0, -1); // } // } return focused; // return super.onFocusSearchFailed(focused, focusDirection, recycler, state); } }

我的方案就是重写了recyclerview分发事件的方法,当滑动的时候如果焦点得不到了(指的是超出屏幕外,就让它滑出来)缺点也很明显,先滑出来再按一下才聚焦

 @Override
    public boolean dispatchKeyEvent(KeyEvent event) {


        Log.i("VVCCC::", event.getKeyCode() + "");


        if (mInterceptLister != null && mInterceptLister.onIntercept(event)) {
            return true;
        }


        if (KeyEvent.KEYCODE_BACK == event.getKeyCode()) {
            Log.i("RRRRFF::", "isreturn");
            return false;
        }

        boolean result = super.dispatchKeyEvent(event);
        View focusView = this.getFocusedChild();
        currentfocus = getChildPosition(focusView);//把当前的聚焦对象的位置记录下来


        if (focusView == null) {
            Log.d(TAG, "dispatchKeyEvent:--> focusView == null" + currentfocus);
            return result;
        } else {
            int dy = 0;
            int dx = 0;
            if (getChildCount() > 0) {
                View firstView = this.getChildAt(0);
                dy = firstView.getHeight();
                dx = firstView.getWidth();
            }
            if (event.getAction() == KeyEvent.ACTION_UP) {
                Log.i("FFDDD225::", "");

                return true;
            } else {
                switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_DPAD_RIGHT:
                        View rightView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_RIGHT);
                        View leftViews = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_LEFT);
                        if (rightView == null && leftViews == null) {
                            if (getAdapter() != null) {
                                ((PersonalityGrowthAdapter) getAdapter()).func(1);
                            }
                        }
                        Log.i(TAG, "rightView is null:" + (rightView == null));
                        Log.i(TAG, "leftViews is null:" + (leftViews == null));

                        if (rightView != null) {
                            rightView.requestFocus();
                            return true;
                        } else {
                            this.smoothScrollBy(dx, 0);
                            return true;
                        }
                    case KeyEvent.KEYCODE_SETTINGS:
                        if (mOnLoadMoreListener != null) {
                            mOnLoadMoreListener.ParentsSubscribe();
                        }
                        return true;

                    case KeyEvent.KEYCODE_DPAD_LEFT:
                        View leftView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_LEFT);
                        View rightViews = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_RIGHT);

                        if (rightViews == null && leftView == null) {
                            if (getAdapter() != null) {
                                ((PersonalityGrowthAdapter) getAdapter()).func(-1);
                            }
                        }
                        Log.i(TAG, "leftView is null:" + (leftView == null));
                        if (leftView != null) {
                            leftView.requestFocus();
                            return true;
                        } else {
                            this.smoothScrollBy(-dx, 0);
                            return true;
                        }
                    case KeyEvent.KEYCODE_DPAD_DOWN:
                        //让第一个默认选中
                        View lView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_LEFT);
                        View rView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_RIGHT);
                        View downView;
                        if (lView == null && rView == null) {
                            //焦点左边的view与焦点右边的view都是空的话,说明此事焦点在头部,
                            // 说明此时是从导航栏按下来,要让第一个item获得焦点
                            downView = getChildAt(2);//第一个item就是第二个position的位置
                        } else {
                            downView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_DOWN);
                        }


                        Log.i(TAG, " downView is null:" + (downView == null));
                        if (downView != null) {
                            downView.requestFocus();

                        } else {
                            this.smoothScrollBy(0, dy);
                        }
                        if (mOnLoadMoreListener != null) {
                            if (downView == null) {
                                if (isSlideToBottom(this)) {
                                    mOnLoadMoreListener.onLoadMore(currentfocus);
                                }
                            }
                        }
                        return true;
                    case KeyEvent.KEYCODE_DPAD_UP:
                        View upView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_UP);
                        //  Log.i(TAG, "upView is null:" + (upView == null));
                        if (event.getAction() == KeyEvent.ACTION_UP) {
                            Log.i("FFDDD::", "66666");
                            return true;
                        } else {
                            if (upView != null) {
                                Log.i("FFDDD::", "DDDD");
                                View topView = FocusFinder.getInstance().findNextFocus(this, upView, View.FOCUS_UP);
                                if (topView != null) {
                                    this.smoothScrollBy(0, -dy);
                                } else {
                                    //this.smoothMoveToPosition(0);
                                    //  this.smoothScrollBy(0, -this.getChildAt(0).getHeight()*2);
                                }

                                upView.requestFocus();
                                return true;
                            } else {
                                Log.i("FFDDD::", "顶部view为空");
                                LayoutManager layoutManager = getLayoutManager();
                                int childLayoutPosition = getChildLayoutPosition(focusView);
                                if (layoutManager instanceof GridLayoutManager) {
                                    int spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
                                    if (childLayoutPosition <= spanCount) {
                                        return result;
                                    }
                                } else if (layoutManager instanceof LinearLayoutManager) {
                                    if (childLayoutPosition == 0) {
                                        return result;
                                    }
                                }
                                this.smoothScrollBy(0, -dy);
                                return true;
                            }
                        }
                }
            }
        }
        return result;
    }
如何判定分页以及分页加载刷新后焦点逻辑


判定分页,也就是判定滑动到底部了,通常按道理来说可以和手机recyeclerview一样在这里处理

@Override
    public void onScrollStateChanged(int state) {
        if (state == SCROLL_STATE_IDLE) {
            // 加载更多回调,个人认为要保存一下上次焦点的位置
            /*if (null != mOnLoadMoreListener) {
                if (getLastVisiblePosition() ==getAdapter().getItemCount() - (1 + mLoadMoreBeforehandCount)) {
                    mOnLoadMoreListener.onLoadMore(currentfocus);
                    isBottom=true;
                }else{
                    isBottom=false;
                }
            }*/
        }
        super.onScrollStateChanged(state);
        if (mShouldScroll) {
            mShouldScroll = false;
            smoothMoveToPosition(mToPosition);
        }
    }

但我用了之后发现了一个问题:就是我遥控器控制的焦点还没有到底部的时候,就触发了。我的方案是在遥控器下按的时候,判断是否完全到了屏幕底部,在触发加载更多的事件

                  case KeyEvent.KEYCODE_DPAD_DOWN:
                        //让第一个默认选中
                        View lView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_LEFT);
                        View rView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_RIGHT);
                        View downView;
                        if (lView == null && rView == null) {
                            //焦点左边的view与焦点右边的view都是空的话,说明此事焦点在头部,
                            // 说明此时是从导航栏按下来,要让第一个item获得焦点
                            downView = getChildAt(2);//第一个item就是第二个position的位置
                        } else {
                            downView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_DOWN);
                        }


                        Log.i(TAG, " downView is null:" + (downView == null));
                        if (downView != null) {
                            downView.requestFocus();

                        } else {
                            this.smoothScrollBy(0, dy);
                        }
                        if (mOnLoadMoreListener != null) { if (downView == null) { if (isSlideToBottom(this)) { mOnLoadMoreListener.onLoadMore(currentfocus); } } }
                        return true;

判断当前recyclerview是否真正的滑到底部

public static boolean isSlideToBottom(RecyclerView recyclerView) {
        if (recyclerView == null) return false;
        if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset()
                >= recyclerView.computeVerticalScrollRange())
            return true;
        return false;
    }

至于分页加载之后,焦点逻辑的处理,始终头脑里要清醒知道,不能全部刷新,而要局部刷新

notifyItemChanged(int position) 对单个item进行刷新

notifyItemRangeChanged(int startpos,int n)从起始位置(startpos)开始刷新 n个item

这两个方法是我用到最多的方法。主要其他的什么notifyXXXinsert 或者 notifyXXXRemove这两个有几个大坑,就是貌似界面刷新了,但position的位置其实没改动,就会导致数据错乱。至于起始点的确认这边就需要算法了。一般是数据源的删除后的大小减去一,如果有头部的话就是数据源删除后的大小。

 //加载新一页的数据

    public void loadmore(List list) {
        if (dataList != null && dataList.size() != 0 && list != null && list.size() != 0) {
            Log.i("NNMMM::", "DD");
            int start = dataList.size();
            int length = list.size();
            dataList.addAll(list);
            if (!onBind) {
                notifyItemRangeChanged(start, length);//处理焦点的错乱
            }
        } else if (dataList.size() != 0 && list.size() == 0) {
            Log.i("NNMMM2::", "DD");
            //没数据不刷新
        } else if (dataList.size() == 0 && list.size() != 0) {
            Log.i("NNMMM3::", "DD");
            int start = 0;
            int length = list.size();
            dataList.addAll(list);
            if (!onBind) {
                notifyItemRangeChanged(start + 1, length);//处理焦点的错乱
            }
        } else if (dataList.size() == 0 && list.size() == 0) {
            Log.i("NNMMM4::", "DD");
            if (remoteControlListener != null) {
                remoteControlListener.showEmpty();
            }
        }
    }
删除后的焦点该如何控制


这里还是涉及到一定的算法,我分为正向删除(从上往下删)和反向删除(从最后向上删除),屏幕里全都删除完了,就默认加载下一页的数据。

正向删除:我把焦点控制在下一个标题的第一个item。主要记录我当前取消订阅的position的位置+2-删除的条数(包括取消)。如下图:


删除后数据刷新就要考虑下了,我应该是从要删除的数据第一个item的位置刷新,刷新的条目应该是剩余的所有数据的个数。(如果控制的个数不对就会导致数据错乱)


反向删除:就是从屏幕最后一条开始删除,这个简单,我应该是从要删除的数据第一个item的位置刷新,刷新的个数就是删除的个数。

 public void cancelSubscribe(String title) {
        if (deleteIdList != null) {
            deleteIdList.add(title);//将要取消订阅的id存储起来
        }

        List readyToDeleteList = new ArrayList();
        List moveList = new ArrayList();
        for (int i = 0; i < dataList.size(); i++) {
            if (dataList.get(i).getDelete_title().equals(title) || dataList.get(i).getConnect_title().equals(title)) {
                readyToDeleteList.add(dataList.get(i));
                moveList.add(i + 1);
            }
        }

        currentCancelFocus = moveList.get(moveList.size() - 1) + 2 - moveList.size();
        Log.i("BBVVSS::",currentCancelFocus+"");

        int flashCount=dataList.size()-moveList.get(moveList.size()-1);
        dataList.removeAll(readyToDeleteList);//将数据删掉

        if (currentCancelFocus
刷新数据的时候要有默认标记位,标记此次是删除操作,处理焦点的ui变化。


.导航栏下来如何保存导航的状态以及第一个聚焦的始终是第一个item。


确定焦点在导航栏,判断此时聚焦的view左右两边的view都为null,我就认为是导航。然后我给每个导航的textview设置向下按的焦点ID为XXX,在adapter中判断第3个item的设置ID也为XXX就可以了

附件:

package com.familybox.adapter;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.familybox.R;
import com.familybox.model.bean.PersonalityGrowthBean;
import com.shan.library.glide.ImageUtils;

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

/**
 * Created by hcy on 2018/4/11.
 * func:个性成长详情页的适配器
 */
public class PersonalityGrowthAdapter extends RecyclerView.Adapter {
    //定义数据
    private List dataList;
    //上下文
    private Context context;
    private LayoutInflater inflater;
    //recyclerview的分类
    //头部
    private static final int TYPE_HEAD = 1;
    //标题
    private static final int TYPE_TITLE = 2;
    //内容
    private static final int TYPE_CONTENT = 3;

    //当取消订阅页面没有数据的时候,
    // 就会自动加载下一页,如果下一页没数据的话,要刷新一次界面
    public void setTheLastPageHasNoData() {
        if (getCurrentNavIndex() == 2) {
            if (isCancel) {
                notifyDataSetChanged();
            }
        }
    }

    public void clearData() {
        dataList.clear();
        notifyDataSetChanged();
    }

    private boolean isFocus = false;

    //强制给第一个内容配置焦点
    public void forceGiveFocus() {
        isFocus = true;
    }

    //重置删除列表
    public void resetDeleteList() {
        if (deleteIdList != null) {
            deleteIdList = new ArrayList();
        }

    }

    public void flashHasSee(int position) {
        Log.i("BBVVV::", position + "");
        dataList.get(position - 1).setSelect(true);
        notifyItemChanged(position);
    }

    public interface onRemoteControlListener {
        //遥控器确定操作
        void makeSure(int navPosition, int currentItemFocusPostion, String content_id);

        //切换导航
        void changeNav(int navPosition);

        //取消订阅
        void cancelSubscribe(String title);

        //调用家长订阅下一页的数据
        void getNextPageData();

        //显示没有数据的界面
        void showEmpty();

        //影藏没数据的界面
        void dissEmpty();
    }


    private onRemoteControlListener remoteControlListener;

    public void setRemoteControlListener(onRemoteControlListener remoteControlListener) {
        this.remoteControlListener = remoteControlListener;
    }

    public String getDeleteList() {
        if (deleteIdList != null && deleteIdList.size() != 0) {
            //里面有要取消的内容
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < deleteIdList.size(); i++) {
                sb.append(deleteIdList.get(i)).append(",");
            }
            Log.i("取消订阅id集合222::", sb.toString().substring(0, sb.toString().length() - 1));

            return sb.toString().substring(0, sb.toString().length() - 1);
        }
        return null;
    }

    @Override
    public int getItemViewType(int position) {
        if (position == 0) {
            return TYPE_HEAD;
        } else {
            PersonalityGrowthBean testData01 = dataList.get(position - 1);
            if (testData01.getType() == 0) {
                return TYPE_TITLE;
            } else if (testData01.getType() == 1) {
                return TYPE_CONTENT;
            }
        }
        return super.getItemViewType(position);
    }

    private LinearLayout ll_tbar;
    private int currentNavIndex = 0;

    public int getCurrentNavIndex() {
        return currentNavIndex;
    }

    //用于导航栏左右逻辑
    public void func(int dir) {
        //当前是否在导航栏上,正数向右,负数向左
        // Toast.makeText(context,"当前在导航栏上", Toast.LENGTH_SHORT).show();
        if (dir > 0) {
            if (currentNavIndex >= 0 && currentNavIndex < 2) {
                currentNavIndex++;
                if (currentNavIndex >= 0 && currentNavIndex <= 2) {
                    Log.i("BBNVVV::", currentNavIndex + "");
                    remoteControlListener.changeNav(currentNavIndex);
                }
            }
            for (int i = 0; i < ll_tbar.getChildCount(); i++) {
                ll_tbar.getChildAt(i).setSelected(false);
//                TextPaint tp = ((TextView) ll_tbar.getChildAt(i)).getPaint();
//                tp.setFakeBoldText(false);
            }
            ll_tbar.getChildAt(currentNavIndex).setSelected(true);
//            TextPaint tp = ((TextView) ll_tbar.getChildAt(currentNavIndex)).getPaint();
//            tp.setFakeBoldText(true);
        }

        if (dir < 0) {
            if (currentNavIndex > 0 && currentNavIndex <= 2) {
                currentNavIndex--;

                isCancel = false;//关闭取消订阅焦点聚焦在第一个的位置
                if (currentNavIndex >= 0 && currentNavIndex <= 2) {
                    Log.i("BBNVVV::", currentNavIndex + "");
                    remoteControlListener.changeNav(currentNavIndex);
                }
            }


            for (int i = 0; i < ll_tbar.getChildCount(); i++) {
                ll_tbar.getChildAt(i).setSelected(false);
//                TextPaint tp = ((TextView) ll_tbar.getChildAt(i)).getPaint();
//                tp.setFakeBoldText(false);
            }
            ll_tbar.getChildAt(currentNavIndex).setSelected(true);
//            TextPaint tp = ((TextView) ll_tbar.getChildAt(currentNavIndex)).getPaint();
//            tp.setFakeBoldText(true);
        }
        if (remoteControlListener != null) {
            if (currentNavIndex == 2) {
                //家长订阅
                //重置取消id的列表
                //deleteIdList = new ArrayList();
            } else {
                //取消订阅了
                if (currentNavIndex == 1) {
                    if (deleteIdList != null && deleteIdList.size() != 0) {
                        //里面有要取消的内容
                        StringBuffer sb = new StringBuffer();
                        for (int i = 0; i < deleteIdList.size(); i++) {
                            sb.append(deleteIdList.get(i)).append(",");
                        }
                        Log.i("取消订阅id集合::", sb.toString().substring(0, sb.toString().length() - 1));
                        remoteControlListener.cancelSubscribe(sb.toString().substring(0, sb.toString().length() - 1));
                    }
                }
            }
           /* isCancel = false;//关闭取消订阅焦点聚焦在第一个的位置
            if (currentNavIndex>=0&¤tNavIndex<=2){
                Log.i("BBNVVV::",currentNavIndex)
                remoteControlListener.changeNav(currentNavIndex);
            }*/
        }

    }


    public PersonalityGrowthAdapter(Context context) {
        dataList = new ArrayList();
        this.context = context;
        inflater = LayoutInflater.from(context);
        deleteIdList = new ArrayList();
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_HEAD) {
            return new PGView_HeadHolder(inflater.inflate(R.layout.item_personality_growth_adapter_head, parent, false));
        } else if (viewType == TYPE_TITLE) {
            return new PGView_TitleHolder(inflater.inflate(R.layout.item_personality_growth_adapter_title, parent, false));
        } else if (viewType == TYPE_CONTENT) {
            return new PGView_ContentHolder(inflater.inflate(R.layout.item_personality_growth_adapter_content, parent, false));
        }
        return null;
    }


    @Override
    public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    if (position == 0 || getItemViewType(position) == 2) {
                        return 5;
                    } else {
                        return 1;
                    }
                }
            });
        }
    }

    private void itemFocus(RecyclerView.ViewHolder holder, final int position, PersonalityGrowthBean testData01, View view) {
        onBind = true;
        mCurrentfocus = position;
    /*    if (testData01.isSelect()) {
            ((PGView_ContentHolder) holder).iv_isHasSee.setVisibility(View.GONE);
        } else {
            ((PGView_ContentHolder) holder).iv_isHasSee.setVisibility(View.GONE);
        }*/
        Drawable drawable = context.getResources().getDrawable(R.drawable.pg_content_bg);
        ((PGView_ContentHolder) holder).rl_top.setBackgroundDrawable(drawable);
        ((PGView_ContentHolder) holder).iv_isHasSee.setVisibility(View.GONE);
        if (!testData01.isFunc()) {
            ((PGView_ContentHolder) holder).rl_content_s.setVisibility(View.VISIBLE);
            ((PGView_ContentHolder) holder).tv_content.setVisibility(View.GONE);
        }
        enlargeAnim(view);
        onBind = false;
    }


    private void itemNotFocus(RecyclerView.ViewHolder holder, final int position, PersonalityGrowthBean testData01, View view, boolean isAnim) {
        onBind = true;
        if (testData01.isSelect()) {
            ((PGView_ContentHolder) holder).iv_isHasSee.setVisibility(View.VISIBLE);
        } else {
            ((PGView_ContentHolder) holder).iv_isHasSee.setVisibility(View.GONE);
        }
        Drawable drawable = context.getResources().getDrawable(R.drawable.pg_bg_unselect);
        ((PGView_ContentHolder) holder).rl_top.setBackgroundDrawable(drawable);
        if (!testData01.isFunc()) {
            ((PGView_ContentHolder) holder).rl_content_s.setVisibility(View.GONE);
            ((PGView_ContentHolder) holder).tv_content.setVisibility(View.VISIBLE);
        }
        if (isAnim) {
            reduceAnim(view);
        }
        onBind = false;
    }


    private Boolean isCancel = false;


    private int currentCancelFocus;

    private List deleteIdList;//取消订阅的id集合


    public void cancelSubscribe(String title) {
        if (deleteIdList != null) {
            deleteIdList.add(title);//将要取消订阅的id存储起来
        }

        List readyToDeleteList = new ArrayList();
        List moveList = new ArrayList();
        for (int i = 0; i < dataList.size(); i++) {
            if (dataList.get(i).getDelete_title().equals(title) || dataList.get(i).getConnect_title().equals(title)) {
                readyToDeleteList.add(dataList.get(i));
                moveList.add(i + 1);
            }
        }

        currentCancelFocus = moveList.get(moveList.size() - 1) + 2 - moveList.size();
        Log.i("BBVVSS::",currentCancelFocus+"");

        int flashCount=dataList.size()-moveList.get(moveList.size()-1);
        dataList.removeAll(readyToDeleteList);//将数据删掉

        if (currentCancelFocus list) {
        dataList = list;
        if (remoteControlListener != null) {
            if (dataList.size() == 0) {
                remoteControlListener.showEmpty();
            } else {
                remoteControlListener.dissEmpty();
            }
        }
        if (!onBind) {
            notifyDataSetChanged();
        }
    }

    //加载新一页的数据

    public void loadmore(List list) {
        if (dataList != null && dataList.size() != 0 && list != null && list.size() != 0) {
            Log.i("NNMMM::", "DD");
            int start = dataList.size();
            int length = list.size();
            dataList.addAll(list);
            if (!onBind) {
                notifyItemRangeChanged(start, length);//处理焦点的错乱
            }
        } else if (dataList.size() != 0 && list.size() == 0) {
            Log.i("NNMMM2::", "DD");
            //没数据不刷新
        } else if (dataList.size() == 0 && list.size() != 0) {
            Log.i("NNMMM3::", "DD");
            int start = 0;
            int length = list.size();
            dataList.addAll(list);
            if (!onBind) {
                notifyItemRangeChanged(start + 1, length);//处理焦点的错乱
            }
        } else if (dataList.size() == 0 && list.size() == 0) {
            Log.i("NNMMM4::", "DD");
            if (remoteControlListener != null) {
                remoteControlListener.showEmpty();
            }
        }
    }

    public class PGView_HeadHolder extends RecyclerView.ViewHolder {
        private LinearLayout ll_tool;

        public PGView_HeadHolder(View itemView) {
            super(itemView);
            ll_tool = itemView.findViewById(R.id.ll_tool);
            ll_tool.setTag(-1);
            ll_tool.getChildAt(0).setSelected(true);
            //字体加粗
//            TextPaint tp = ((TextView) ll_tool.getChildAt(0)).getPaint();
//            tp.setFakeBoldText(true);
            currentNavIndex = 0;
            ll_tbar = ll_tool;
        }
    }

    public class PGView_TitleHolder extends RecyclerView.ViewHolder {
        private TextView tv_title;

        public PGView_TitleHolder(View itemView) {
            super(itemView);
            itemView.setFocusable(false);
            tv_title = (TextView) itemView.findViewById(R.id.tv_title);
        }
    }

    public class PGView_ContentHolder extends RecyclerView.ViewHolder {
        private TextView tv_content_s;
        private TextView tv_content;
        private ImageView iv_ico;
        private ImageView iv_isHasSee;//用于标记是否已看
        private RelativeLayout rl_top;
        private RelativeLayout rl_content_s;



        public PGView_ContentHolder(View itemView) {
            super(itemView);
            itemView.setFocusable(true);
            rl_top = itemView.findViewById(R.id.rl_top);
            rl_content_s = itemView.findViewById(R.id.rl_content_s);
            tv_content_s = itemView.findViewById(R.id.tv_content_s);
            tv_content = itemView.findViewById(R.id.tv_content);
            iv_isHasSee = itemView.findViewById(R.id.iv_isHasSee);
            iv_ico = itemView.findViewById(R.id.iv_ico);
        }
    }


    //获取焦点view实现放大效果
    private void enlargeAnim(View view) {
        if (Build.VERSION.SDK_INT >= 21) {//android 5.0以上
            ViewCompat.animate(view).scaleX(1.13f).scaleY(1.13f).translationZ(1.13f).start();
        } else {
            Animation a = android.view.animation.AnimationUtils.loadAnimation(view.getContext(), R.anim.pg_uikit_enlarge);
            a.setFillAfter(true);
            view.clearAnimation();
            view.setAnimation(a);
            view.bringToFront();
            a.start();
        }
    }

    //失去焦点view实现缩小效果
    private void reduceAnim(View view) {
        if (Build.VERSION.SDK_INT >= 21) {//android 5.0以上
            ViewCompat.animate(view).scaleX(1.0f).scaleY(1.0f).translationZ(1.0f).start();
        } else {
            Animation a = android.view.animation.AnimationUtils.loadAnimation(view.getContext(), R.anim.pg_uikit_reduce);
            a.setFillAfter(true);
            view.clearAnimation();
            view.startAnimation(a);
            a.start();
        }
    }

}
package com.familybox.ui.family.widget.thrid_party;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.os.Build;
import android.support.v4.view.ViewCompat;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.view.FocusFinder;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

import com.familybox.R;
import com.familybox.adapter.PersonalityGrowthAdapter;

/**
 * Created by liuyu on 17/1/6.
 */
public class PGRecyclerView extends RecyclerView {
    private static final String TAG = "TvRecyclerView";
    private int position;
    //焦点是否居中
    private boolean mSelectedItemCentered;
    private int mSelectedItemOffsetStart;

    private int mSelectedItemOffsetEnd;

    //分页的时候使用
    private int mLoadMoreBeforehandCount = 0;

    //记录当前的focus的位置

    private int currentfocus = 0;

    public PGRecyclerView(Context context) {
        this(context, null);
    }

    public PGRecyclerView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public PGRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs, defStyle);
    }

    private void init(Context context, AttributeSet attrs, int defStyle) {
        initView();
        initAttr(context, attrs);
    }

    private void initView() {
        setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
        setHasFixedSize(true);
        setWillNotDraw(true);
        setOverScrollMode(View.OVER_SCROLL_NEVER);
        setChildrenDrawingOrderEnabled(true);

        setClipChildren(false);
        setClipToPadding(false);

        setClickable(false);
        setFocusable(true);
        setFocusableInTouchMode(true);
        /**
         防止RecyclerView刷新时焦点不错乱bug的步骤如下:
         (1)adapter执行setHasStableIds(true)方法
         (2)重写getItemId()方法,让每个view都有各自的id
         (3)RecyclerView的动画必须去掉
         */
        setItemAnimator(null);
    }

    private void initAttr(Context context, AttributeSet attrs) {
        if (attrs != null) {
            final TypedArray a = context.obtainStyledAttributes(attrs,
                    R.styleable.TvRecyclerView);
            /**
             * 如果是towWayView的layoutManager
             */
            final String name = a.getString(R.styleable.TvRecyclerView_tv_layoutManager);


            mSelectedItemCentered = a.getBoolean(R.styleable.TvRecyclerView_tv_selectedItemCentered, false);

            mLoadMoreBeforehandCount = a.getInteger(R.styleable.TvRecyclerView_tv_loadMoreBeforehandCount, 0);

            mSelectedItemOffsetStart = a.getDimensionPixelSize(R.styleable.TvRecyclerView_tv_selectedItemOffsetStart, 0);

            mSelectedItemOffsetEnd = a.getDimensionPixelSize(R.styleable.TvRecyclerView_tv_selectedItemOffsetEnd, 0);

            a.recycle();
        }
    }


    private int getFreeWidth() {
        return getWidth() - getPaddingLeft() - getPaddingRight();
    }

    private int getFreeHeight() {
        return getHeight() - getPaddingTop() - getPaddingBottom();
    }


    @Override
    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
    }

    @Override
    public boolean hasFocus() {
        return super.hasFocus();
    }

    @Override
    public boolean isInTouchMode() {
        // 解决4.4版本抢焦点的问题
        if (Build.VERSION.SDK_INT == 19) {
            return !(hasFocus() && !super.isInTouchMode());
        } else {
            return super.isInTouchMode();
        }

        //return super.isInTouchMode();
    }

    @Override
    public void requestChildFocus(View child, View focused) {
        if (null != child) {
            if (mSelectedItemCentered) {
                mSelectedItemOffsetStart = !isVertical() ? (getFreeWidth() - child.getWidth()) : (getFreeHeight() - child.getHeight());
                mSelectedItemOffsetStart /= 2;
                mSelectedItemOffsetEnd = mSelectedItemOffsetStart;
            }
        }
        super.requestChildFocus(child, focused);
    }

    @Override
    public boolean requestChildRectangleOnScreen(View child, Rect rect, boolean immediate) {
        final int parentLeft = getPaddingLeft();
        final int parentRight = getWidth() - getPaddingRight();

        final int parentTop = getPaddingTop();
        final int parentBottom = getHeight() - getPaddingBottom();
        final int childLeft = child.getLeft() + rect.left;
        final int childTop = child.getTop() + rect.top;
        final int childRight = childLeft + rect.width();
        final int childBottom = childTop + rect.height();
        final int offScreenLeft = Math.min(0, childLeft - parentLeft - mSelectedItemOffsetStart);
        final int offScreenRight = Math.max(0, childRight - parentRight + mSelectedItemOffsetEnd);
        final int offScreenTop = Math.min(0, childTop - parentTop - mSelectedItemOffsetStart);
        final int offScreenBottom = Math.max(0, childBottom - parentBottom + mSelectedItemOffsetEnd);
        final boolean canScrollHorizontal = getLayoutManager().canScrollHorizontally();
        final boolean canScrollVertical = getLayoutManager().canScrollVertically();

        // Favor the "start" layout direction over the end when bringing one side or the other
        // of a large rect into view. If we decide to bring in end because start is already
        // visible, limit the scroll such that start won't go out of bounds.
        final int dx;
        if (canScrollHorizontal) {
            if (ViewCompat.getLayoutDirection(this) == ViewCompat.LAYOUT_DIRECTION_RTL) {
                dx = offScreenRight != 0 ? offScreenRight
                        : Math.max(offScreenLeft, childRight - parentRight);
            } else {
                dx = offScreenLeft != 0 ? offScreenLeft
                        : Math.min(childLeft - parentLeft, offScreenRight);
            }
        } else {
            dx = 0;
        }

        // Favor bringing the top into view over the bottom. If top is already visible and
        // we should scroll to make bottom visible, make sure top does not go out of bounds.
        final int dy;
        if (canScrollVertical) {
            dy = offScreenTop != 0 ? offScreenTop : Math.min(childTop - parentTop, offScreenBottom);
        } else {
            dy = 0;
        }


        if (dx != 0 || dy != 0) {
            if (immediate) {
                scrollBy(dx, dy);
            } else {
                smoothScrollBy(dx, dy);
            }
            // 重绘是为了选中item置顶,具体请参考getChildDrawingOrder方法
            postInvalidate();
            return true;
        }


        return false;
    }


    @Override
    public int getBaseline() {
        return -1;
    }


    public int getSelectedItemOffsetStart() {
        return mSelectedItemOffsetStart;
    }

    public int getSelectedItemOffsetEnd() {
        return mSelectedItemOffsetEnd;
    }

    @Override
    public void setLayoutManager(LayoutManager layout) {
        super.setLayoutManager(layout);
    }

    /**
     * 判断是垂直,还是横向.
     */
    private boolean isVertical() {
        LayoutManager manager = getLayoutManager();
        if (manager != null) {
            LinearLayoutManager layout = (LinearLayoutManager) getLayoutManager();
            return layout.getOrientation() == LinearLayoutManager.VERTICAL;

        }
        return false;
    }

    /**
     * 设置选中的Item距离开始或结束的偏移量;
     * 与滚动方向有关;
     * 与setSelectedItemAtCentered()方法二选一
     *
     * @param offsetStart
     * @param offsetEnd   从结尾到你移动的位置.
     */
    public void setSelectedItemOffset(int offsetStart, int offsetEnd) {
        setSelectedItemAtCentered(false);
        mSelectedItemOffsetStart = offsetStart;
        mSelectedItemOffsetEnd = offsetEnd;
    }

    /**
     * 设置选中的Item居中;
     * 与setSelectedItemOffset()方法二选一
     *
     * @param isCentered
     */
    public void setSelectedItemAtCentered(boolean isCentered) {
        this.mSelectedItemCentered = isCentered;
    }


    @Override
    protected int getChildDrawingOrder(int childCount, int i) {
        View view = getFocusedChild();
        if (null != view) {
            position = getChildAdapterPosition(view) - getFirstVisiblePosition();
            if (position < 0) {
                return i;
            } else {
                if (i == childCount - 1) {//这是最后一个需要刷新的item
                    if (position > i) {
                        position = i;
                    }
                    return position;
                }
                if (i == position) {//这是原本要在最后一个刷新的item
                    return childCount - 1;
                }
            }
        }
        return i;
    }

    public int getFirstVisiblePosition() {
        if (getChildCount() == 0)
            return 0;
        else
            return getChildAdapterPosition(getChildAt(0));
    }

    public int getLastVisiblePosition() {
        final int childCount = getChildCount();
        if (childCount == 0)
            return 0;
        else
            return getChildAdapterPosition(getChildAt(childCount - 1));
    }


    /***********
     * 按键加载更多 start
     **********/

    private OnLoadMoreListener mOnLoadMoreListener;

    public interface OnLoadMoreListener {
        void onLoadMore(int currentfocus);

        void ParentsSubscribe();
    }


    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
        this.mOnLoadMoreListener = onLoadMoreListener;
    }

    protected OnInterceptListener mInterceptLister;


    public void setOnInterceptListener(OnInterceptListener listener) {
        this.mInterceptLister = listener;
    }

    /**
     * 设置为0,这样可以防止View获取焦点的时候,ScrollView自动滚动到焦点View的位置
     */

    protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
        return 0;
    }

    private boolean isBottom = false;

    @Override
    public void onScrollStateChanged(int state) {
        if (state == SCROLL_STATE_IDLE) {
            // 加载更多回调,个人认为要保存一下上次焦点的位置
            /*if (null != mOnLoadMoreListener) {
                if (getLastVisiblePosition() ==getAdapter().getItemCount() - (1 + mLoadMoreBeforehandCount)) {
                    mOnLoadMoreListener.onLoadMore(currentfocus);
                    isBottom=true;
                }else{
                    isBottom=false;
                }
            }*/
        }
        super.onScrollStateChanged(state);
        if (mShouldScroll) {
            mShouldScroll = false;
            smoothMoveToPosition(mToPosition);
        }
    }

    /**
     * 子类如果要重写dispatchKeyEvent的话请调用个
     *
     * @param event
     * @return
     */
    protected boolean customDispatchKeyEvent(KeyEvent event) {
        return super.dispatchKeyEvent(event);
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {


        Log.i("VVCCC::", event.getKeyCode() + "");


        if (mInterceptLister != null && mInterceptLister.onIntercept(event)) {
            return true;
        }


        if (KeyEvent.KEYCODE_BACK == event.getKeyCode()) {
            Log.i("RRRRFF::", "isreturn");
            return false;
        }

        boolean result = super.dispatchKeyEvent(event);
        View focusView = this.getFocusedChild();
        currentfocus = getChildPosition(focusView);//把当前的聚焦对象的位置记录下来


        if (focusView == null) {
            Log.d(TAG, "dispatchKeyEvent:--> focusView == null" + currentfocus);
            return result;
        } else {
            int dy = 0;
            int dx = 0;
            if (getChildCount() > 0) {
                View firstView = this.getChildAt(0);
                dy = firstView.getHeight();
                dx = firstView.getWidth();
            }
            if (event.getAction() == KeyEvent.ACTION_UP) {
                Log.i("FFDDD225::", "");

                return true;
            } else {
                switch (event.getKeyCode()) {
                    case KeyEvent.KEYCODE_DPAD_RIGHT:
                        View rightView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_RIGHT);
                        View leftViews = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_LEFT);
                        if (rightView == null && leftViews == null) {
                            if (getAdapter() != null) {
                                ((PersonalityGrowthAdapter) getAdapter()).func(1);
                            }
                        }
                        Log.i(TAG, "rightView is null:" + (rightView == null));
                        Log.i(TAG, "leftViews is null:" + (leftViews == null));

                        if (rightView != null) {
                            rightView.requestFocus();
                            return true;
                        } else {
                            this.smoothScrollBy(dx, 0);
                            return true;
                        }
                    case KeyEvent.KEYCODE_SETTINGS:
                        if (mOnLoadMoreListener != null) {
                            mOnLoadMoreListener.ParentsSubscribe();
                        }
                        return true;

                    case KeyEvent.KEYCODE_DPAD_LEFT:
                        View leftView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_LEFT);
                        View rightViews = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_RIGHT);

                        if (rightViews == null && leftView == null) {
                            if (getAdapter() != null) {
                                ((PersonalityGrowthAdapter) getAdapter()).func(-1);
                            }
                        }
                        Log.i(TAG, "leftView is null:" + (leftView == null));
                        if (leftView != null) {
                            leftView.requestFocus();
                            return true;
                        } else {
                            this.smoothScrollBy(-dx, 0);
                            return true;
                        }
                    case KeyEvent.KEYCODE_DPAD_DOWN:
                        //让第一个默认选中
                        View lView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_LEFT);
                        View rView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_RIGHT);
                        View downView;
                        if (lView == null && rView == null) {
                            //焦点左边的view与焦点右边的view都是空的话,说明此事焦点在头部,
                            // 说明此时是从导航栏按下来,要让第一个item获得焦点
                            downView = getChildAt(2);//第一个item就是第二个position的位置
                        } else {
                            downView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_DOWN);
                        }


                        Log.i(TAG, " downView is null:" + (downView == null));
                        if (downView != null) {
                            downView.requestFocus();

                        } else {
                            this.smoothScrollBy(0, dy);
                        }
                        if (mOnLoadMoreListener != null) {
                            if (downView == null) {
                                if (isSlideToBottom(this)) {
                                    mOnLoadMoreListener.onLoadMore(currentfocus);
                                }
                            }
                        }
                        return true;
                    case KeyEvent.KEYCODE_DPAD_UP:
                        View upView = FocusFinder.getInstance().findNextFocus(this, focusView, View.FOCUS_UP);
                        //  Log.i(TAG, "upView is null:" + (upView == null));
                        if (event.getAction() == KeyEvent.ACTION_UP) {
                            Log.i("FFDDD::", "66666");
                            return true;
                        } else {
                            if (upView != null) {
                                Log.i("FFDDD::", "DDDD");
                                View topView = FocusFinder.getInstance().findNextFocus(this, upView, View.FOCUS_UP);
                                if (topView != null) {
                                    this.smoothScrollBy(0, -dy);
                                } else {
                                    //this.smoothMoveToPosition(0);
                                    //  this.smoothScrollBy(0, -this.getChildAt(0).getHeight()*2);
                                }

                                upView.requestFocus();
                                return true;
                            } else {
                                Log.i("FFDDD::", "顶部view为空");
                                LayoutManager layoutManager = getLayoutManager();
                                int childLayoutPosition = getChildLayoutPosition(focusView);
                                if (layoutManager instanceof GridLayoutManager) {
                                    int spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
                                    if (childLayoutPosition <= spanCount) {
                                        return result;
                                    }
                                } else if (layoutManager instanceof LinearLayoutManager) {
                                    if (childLayoutPosition == 0) {
                                        return result;
                                    }
                                }
                                this.smoothScrollBy(0, -dy);
                                return true;
                            }
                        }
                }
            }
        }
        return result;
    }

    public static boolean isSlideToBottom(RecyclerView recyclerView) {
        if (recyclerView == null) return false;
        if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset()
                >= recyclerView.computeVerticalScrollRange())
            return true;
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent e) {
        return super.onInterceptTouchEvent(e);
    }


    /**
     * 设置默认选中.
     */
    public void setSelectedPosition(int pos) {
        this.smoothScrollToPosition(pos);
    }

    //防止Activity时,RecyclerView崩溃
    @Override
    protected void onDetachedFromWindow() {
        if (getLayoutManager() != null) {
            super.onDetachedFromWindow();
        }
    }


    /**
     * 是否是最右边的item,如果是竖向,表示右边,如果是横向表示下边
     *
     * @param childPosition
     * @return
     */
    public boolean isRightEdge(int childPosition) {
        LayoutManager layoutManager = getLayoutManager();

        if (layoutManager instanceof GridLayoutManager) {

            GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            GridLayoutManager.SpanSizeLookup spanSizeLookUp = gridLayoutManager.getSpanSizeLookup();

            int totalSpanCount = gridLayoutManager.getSpanCount();
            int totalItemCount = gridLayoutManager.getItemCount();
            int childSpanCount = 0;

            for (int i = 0; i <= childPosition; i++) {
                childSpanCount += spanSizeLookUp.getSpanSize(i);
            }
            if (isVertical()) {
                if (childSpanCount % gridLayoutManager.getSpanCount() == 0) {
                    return true;
                }
            } else {
                int lastColumnSize = totalItemCount % totalSpanCount;
                if (lastColumnSize == 0) {
                    lastColumnSize = totalSpanCount;
                }
                if (childSpanCount > totalItemCount - lastColumnSize) {
                    return true;
                }
            }

        } else if (layoutManager instanceof LinearLayoutManager) {
            if (isVertical()) {
                return true;
            } else {
                return childPosition == getLayoutManager().getItemCount() - 1;
            }
        }

        return false;
    }

    /**
     * 是否是最左边的item,如果是竖向,表示左方,如果是横向,表示上边
     *
     * @param childPosition
     * @return
     */
    public boolean isLeftEdge(int childPosition) {
        LayoutManager layoutManager = getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            GridLayoutManager.SpanSizeLookup spanSizeLookUp = gridLayoutManager.getSpanSizeLookup();

            int totalSpanCount = gridLayoutManager.getSpanCount();
            int childSpanCount = 0;
            for (int i = 0; i <= childPosition; i++) {
                childSpanCount += spanSizeLookUp.getSpanSize(i);
            }
            if (isVertical()) {
                if (childSpanCount % gridLayoutManager.getSpanCount() == 1) {
                    return true;
                }
            } else {
                if (childSpanCount <= totalSpanCount) {
                    return true;
                }
            }

        } else if (layoutManager instanceof LinearLayoutManager) {
            if (isVertical()) {
                return true;
            } else {
                return childPosition == 0;
            }

        }

        return false;
    }

    /**
     * 是否是最上边的item,以recyclerview的方向做参考
     *
     * @param childPosition
     * @return
     */
    public boolean isTopEdge(int childPosition) {
        LayoutManager layoutManager = getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            GridLayoutManager.SpanSizeLookup spanSizeLookUp = gridLayoutManager.getSpanSizeLookup();

            int totalSpanCount = gridLayoutManager.getSpanCount();

            int childSpanCount = 0;
            for (int i = 0; i <= childPosition; i++) {
                childSpanCount += spanSizeLookUp.getSpanSize(i);
            }

            if (isVertical()) {
                if (childSpanCount <= totalSpanCount) {
                    return true;
                }
            } else {
                if (childSpanCount % totalSpanCount == 1) {
                    return true;
                }
            }


        } else if (layoutManager instanceof LinearLayoutManager) {
            if (isVertical()) {
                return childPosition == 0;
            } else {
                return true;
            }

        }

        return false;
    }

    /**
     * 是否是最下边的item,以recyclerview的方向做参考
     *
     * @param childPosition
     * @return
     */
    public boolean isBottomEdge(int childPosition) {
        LayoutManager layoutManager = getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            GridLayoutManager.SpanSizeLookup spanSizeLookUp = gridLayoutManager.getSpanSizeLookup();
            int itemCount = gridLayoutManager.getItemCount();
            int childSpanCount = 0;
            int totalSpanCount = gridLayoutManager.getSpanCount();
            for (int i = 0; i <= childPosition; i++) {
                childSpanCount += spanSizeLookUp.getSpanSize(i);
            }
            if (isVertical()) {
                //最后一行item的个数
                int lastRowCount = itemCount % totalSpanCount;
                if (lastRowCount == 0) {
                    lastRowCount = gridLayoutManager.getSpanCount();
                }
                if (childSpanCount > itemCount - lastRowCount) {
                    return true;
                }
            } else {
                if (childSpanCount % totalSpanCount == 0) {
                    return true;
                }
            }

        } else if (layoutManager instanceof LinearLayoutManager) {
            if (isVertical()) {
                return childPosition == getLayoutManager().getItemCount() - 1;
            } else {
                return true;
            }

        }
        return false;
    }

    /**
     * 目标项是否在最后一个可见项之后
     */
    private boolean mShouldScroll;
    /**
     * 记录目标项位置
     */
    private int mToPosition;

    /**
     * 滑动到指定位置
     *
     * @param
     * @param position
     */
    public void smoothMoveToPosition(int position) {
        // 第一个可见位置
        int firstItem = getChildLayoutPosition(getChildAt(0));
        // 最后一个可见位置
        int lastItem = getChildLayoutPosition(getChildAt(getChildCount() - 1));

        if (position < firstItem) {
            // 如果跳转位置在第一个可见位置之前,就smoothScrollToPosition可以直接跳转
            smoothScrollToPosition(position);
        } else if (position <= lastItem) {
            // 跳转位置在第一个可见项之后,最后一个可见项之前
            // smoothScrollToPosition根本不会动,此时调用smoothScrollBy来滑动到指定位置
            int movePosition = position - firstItem;
            if (movePosition >= 0 && movePosition < getChildCount()) {
                int top = getChildAt(movePosition).getTop();
                smoothScrollBy(0, top);
            }
        } else {
            // 如果要跳转的位置在最后可见项之后,则先调用smoothScrollToPosition将要跳转的位置滚动到可见位置
            // 再通过onScrollStateChanged控制再次调用smoothMoveToPosition,执行上一个判断中的方法
            smoothScrollToPosition(position);
            mToPosition = position;
            mShouldScroll = true;
        }
    }

}
package com.familybox.ui.baby.personality_growth;

import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.BitmapDrawable;
import android.support.v7.widget.GridLayoutManager;
import android.util.Log;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;

import com.familybox.R;
import com.familybox.ui.BaseActivity;
import com.familybox.ui.IView.PersonalityGrowthActivityView;
import com.familybox.ui.family.behavior_correct.BehaviorCorrectActivity;
import com.familybox.ui.family.widget.thrid_party.PGRecyclerView;
import com.familybox.utils.PGRecyclerViewItemDecoration;
import com.familybox.presenter.personality_growth.PersonalityGrowthActivityPresenter;
import com.familybox.adapter.PersonalityGrowthAdapter;
import com.familybox.model.bean.PersonalityGrowthBean;
import com.familybox.video.PlayerActivity;
import java.util.List;
import butterknife.BindView;
/**
 * Created by hcy on 2018/4/11.
 * 个性成长
 * func:家长订阅的取消订阅的功能
 */
public class PersonalityGrowthActivity extends BaseActivity implements PersonalityGrowthActivityView {


    @BindView(R.id.rv_main)
    PGRecyclerView rv_main;
    private GridLayoutManager gridLayoutManager;
    private static final String TAG = "PGActivity:::";
    private PersonalityGrowthAdapter adapter;
    private PersonalityGrowthActivityPresenter presenter;
    private int currentPage = 1;
    @BindView(R.id.tv_tag_01)
    TextView tv_tag_01;
    @BindView(R.id.tv_tag_02)
    TextView tv_tag_02;
    @BindView(R.id.ll_tag)
    LinearLayout ll_tag;
    @BindView(R.id.ll_empty)
    LinearLayout ll_empty;

    private int playPosition = 0;


    @Override
    protected void onResume() {
        super.onResume();
        dismissPopWindow();

    }

    public static void launch(Activity activity) {
        Intent intent = new Intent(activity, PersonalityGrowthActivity.class);
        activity.startActivity(intent);
    }

    @Override
    protected int setLayoutId() {
        return R.layout.activty_personality_growth;
    }

    @Override
    protected void init() {
        initUI();
        initData();
    }


    @Override
    protected void requestInitFocus() {


    }


    private Boolean load_more_tag = true;

    private void initData() {
        //数据模拟

        //定义数据:0代表课程相关 1代表测试推荐,2代表家长订阅
        presenter = new PersonalityGrowthActivityPresenter(this);
        //首次加载家长订阅的第一页数据;
        currentPage = 1;
        presenter.getDataFromServer(adapter.getCurrentNavIndex(), currentPage, PersonalityGrowthActivity.this);


        adapter.setRemoteControlListener(new PersonalityGrowthAdapter.onRemoteControlListener() {
            @Override
            public void makeSure(int navPosition, int currentItemFocusPostion, String content_id) {

                playPosition = currentItemFocusPostion;

                PlayerActivity.launch(PersonalityGrowthActivity.this, 1, Integer.valueOf(content_id));


            }

            @Override
            public void changeNav(int navPosition) {

                SparseArray> sparseArray = presenter.getSparseArray();
                Log.i("缓存?::", navPosition + "");
                List testData01s = (List) sparseArray.get(navPosition);

                if (testData01s != null) {
                    Log.i("缓存::", "缓存有数据");
                    if (adapter != null) {
                        adapter.setData(testData01s);
                    }
                } else {
                    Log.i("缓存::", "缓存没数据");
                    if (adapter != null) {
                        adapter.clearData();
                        showEmptys();
                    }
                }


                currentPage = 1;
                isBottom = false;
                load_more_tag = true;
                presenter.getDataFromServer(adapter.getCurrentNavIndex(), currentPage, PersonalityGrowthActivity.this);
            }

            @Override
            public void cancelSubscribe(String title) {
                presenter.cancelSubscribe(title, PersonalityGrowthActivity.this);


            }

            @Override
            public void getNextPageData() {
                currentPage++;
                presenter.load_more_data(adapter.getCurrentNavIndex(), currentPage, PersonalityGrowthActivity.this);

            }

            @Override
            public void showEmpty() {
                showEmptys();
            }

            @Override
            public void dissEmpty() {
                ll_empty.setVisibility(View.GONE);
            }
        });


        rv_main.setOnLoadMoreListener(new PGRecyclerView.OnLoadMoreListener() {
            @Override
            public void onLoadMore(int currentfocus) {
                if (adapter != null) {
                    if (adapter.getItemCount() != 1) {
                        if (load_more_tag) {
                            load_more_tag = false;
                            if (!isBottom) {
                                currentPage++;
                                //Toast.makeText(PersonalityGrowthActivity.this,"正在加载"+currentPage+"页的数据",Toast.LENGTH_SHORT).show();
                                presenter.load_more_data(adapter.getCurrentNavIndex(), currentPage, PersonalityGrowthActivity.this);
                            }
                        }

                    }
                }
            }

            @Override
            public void ParentsSubscribe() {
                //处理家长订阅的时候,如果有取消订阅的话,强求取消订阅的接口
                if (adapter != null) {
                    String title = adapter.getDeleteList();
                    if (title != null) {
                        presenter.cancelSubscribe(title, PersonalityGrowthActivity.this);
                    }
                }

                showPopWindow();


                //跳转到家长订阅
                // startActivity(new Intent(PersonalityGrowthActivity.this, BehaviorCorrectActivity.class));
            }
        });

    }

    private void initUI() {
        initPopWindow();
        adapter = new PersonalityGrowthAdapter(PersonalityGrowthActivity.this);
        gridLayoutManager = new GridLayoutManager(PersonalityGrowthActivity.this, 5);
        rv_main.setLayoutManager(gridLayoutManager);
        rv_main.setHasFixedSize(true);
        //设置item间距
        rv_main.addItemDecoration(new PGRecyclerViewItemDecoration(PersonalityGrowthActivity.this));
        rv_main.setAdapter(adapter);
        adapter.onAttachedToRecyclerView(rv_main);
    }


    private void showEmptys() {
        Log.i("BBB::", "显示kong");
        ll_empty.setVisibility(View.VISIBLE);
        switch (adapter.getCurrentNavIndex()) {
            case 0:
                ll_tag.setVisibility(View.GONE);
                tv_tag_01.setText("未收到课程相关推荐");
                tv_tag_02.setVisibility(View.VISIBLE);
                tv_tag_02.setText("可能是老师尚未制定本月教学内容");
                break;
            case 1:
                ll_tag.setVisibility(View.GONE);
                tv_tag_01.setText("暂未收到测评相关推荐");
                tv_tag_02.setVisibility(View.VISIBLE);
                tv_tag_02.setText("测评内容需要老师观察并记录每周六进行发送");

                break;
            case 2:
                tv_tag_01.setText("尚未订阅节目内容");
                tv_tag_02.setVisibility(View.GONE);
                ll_tag.setVisibility(View.VISIBLE);

                break;
        }
    }

    @Override
    public void showProgress() {

    }

    @Override
    public void hideProgress() {

    }

    @Override
    public void showMessage(String msg) {

    }


    @Override
    public void return_data(List list) {
//        if (currentPage == 1) {
//            if (list == null || list.size() == 0) {
//                ll_empty.setVisibility(View.VISIBLE);//落网状态下
//                showEmpty();
//            } else {
//                ll_empty.setVisibility(View.GONE);
//            }
//        }
        if (adapter != null && list != null) {
            adapter.setData(list);
        }
    }

    private boolean isBottom;

    @Override
    public void loadmore(List list) {
        load_more_tag = true;
        if (list == null || list.size() == 0) {
            currentPage--;
            isBottom = true;
           // Toast.makeText(PersonalityGrowthActivity.this, "没有更多数据了", Toast.LENGTH_SHORT).show();
            if (adapter != null) {
                //通知取消订阅页面没有数据了
                adapter.loadmore(list);
            }
        } else {
            if (adapter != null) {
                adapter.loadmore(list);
                if (adapter.getItemCount() > 1) {
                    rv_main.scrollBy(0, 100);
                }
            }
        }
    }

    @Override
    public void cancelSubscribe(boolean isCancel) {
        //取消删除成功
        //重置删除列表
        if (adapter != null) {
            adapter.resetDeleteList();
        }

    }


    private PopupWindow subWindow;
    private ImageView iv_tag;

    private void initPopWindow() {
        View dialogView = LayoutInflater.from(PersonalityGrowthActivity.this).inflate(R.layout.dialog_sublesson, null);
        subWindow = new PopupWindow(dialogView, WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);
        subWindow.setAnimationStyle(R.style.take_photo_anim);
        subWindow.setFocusable(true);
        subWindow.setOutsideTouchable(true);
        subWindow.setBackgroundDrawable(new BitmapDrawable());
        iv_tag = dialogView.findViewById(R.id.iv_tag);
        iv_tag.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                dismissPopWindow();
                //跳转之前要保存焦点位置

                startActivityForResult(new Intent(PersonalityGrowthActivity.this, BehaviorCorrectActivity.class), REQUEST_CODE);
            }
        });
    }

    private static final int REQUEST_CODE = 1;

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE && resultCode == 100) {
            Log.i("HHGGDD::", "YYGGG");
            //当订阅的页面,用户成功订阅的时候才会提示个性成长页面家长页面刷新数据
            if (adapter.getCurrentNavIndex() == 2) {
                currentPage = 1;
                rv_main.smoothMoveToPosition(0);//滑到顶部加载数据
               /* if (adapter!=null){
                    adapter.forceGiveFocus();
                }*/
                presenter.getDataFromServer(adapter.getCurrentNavIndex(), currentPage, PersonalityGrowthActivity.this);
            }
        }

        if (requestCode == REQUEST_CODE && resultCode == 200) {
            //刷新已观看
            Log.i("HHGGDD::", "YYGGG222");

            adapter.flashHasSee(playPosition);

        }


    }

    private void showPopWindow() {
        if (subWindow != null && !subWindow.isShowing()) {
            subWindow.showAtLocation(rv_main, Gravity.LEFT, 0, 0);
        }
    }


    private void dismissPopWindow() {
        if (subWindow != null && subWindow.isShowing()) {
            subWindow.dismiss();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        isBottom = false;
        load_more_tag = true;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //当在家长订阅的页面退出的时候,也要判断用户是否操作了取消订阅,然后与服务器同步数据
        if (adapter != null) {
            if (adapter.getCurrentNavIndex() == 2) {
                String title = adapter.getDeleteList();
                if (title != null) {
                    presenter.cancelSubscribe(title, PersonalityGrowthActivity.this);
                }
            }
        }
    }
}







你可能感兴趣的:(Android)