Android TV开发记录

开发记录

1.seekBar的onStartTrackingTouch() 和 onStopTrackingTouch()失效,因为使用的Key事件,故并不回调上述两个方法。

     /**
     * seekBar在TV上由于没有触摸事件,导致onStartTrackingTouch / onStopTrackingTouch方法失效
     * 使用onKey方法监听seekBar的拖拽和暂停
     *
     * @param v       view
     * @param keyCode keyCode
     * @param event   event
     * @return false
     */
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
        int action = event.getAction();
        switch (action) {
            case KeyEvent.ACTION_DOWN:
                if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                    isDragging = true;
                }
                break;
            case KeyEvent.ACTION_UP:
                isDragging = false;
                if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {
                    if (listener != null) {
                        listener.onProgressChanged(sbProgress, sbProgress.getProgress(), true);
                    }
                }
                break;
        }
        return false;
    }

2.解析字幕
在解析字幕,使用readLine()读取字幕记录行,第一行通过Interger.parseInt()方法,出现格式化失败的情况。原因是文件第一行有一个空字符。

/*BufferedReader.readLine()读取第一行会出现bug,首行第一个字符会是一个空字符 */
       char s = line.charAt(0);
       //65279是空字符
       if (s == 65279) {
             if (line.length() > 1) {
                   line = line.substring(1);
             }
       }
       int num = Integer.parseInt(line);
/*BufferedReader.readLine()读取第一行会出现bug,首行第一个字符会是一个空字符 */

3.RecycleView获取选中的条目

    LinearLayoutManager manager = (LinearLayoutManager) recycleView.getLayoutManager();
    int firstVis = manager.findFirstVisibleItemPosition();
    int itemCount = manager.getItemCount();
    int targetPos = Math.max(0, Math.min(itemCount - 1, focusPos)) - firstVis;//获取目标item的位置
    View childAt = recycleView.getChildAt(targetPos);  //目标的子条目View

4.RecycleView上下滑动,获焦条目垂直居中

// 在RecyclerView的源码中,scrollTopPosition和smoothScrollToPosition都是直接调用LayoutManager对应的方法
// code in RecyclerView.java

    public void scrollToPosition(int position) {
        if (mLayoutFrozen) {
            return;
        }
        stopScroll();
        if (mLayout == null) {
            Log.e(TAG, "Cannot scroll to position a LayoutManager set. " +
                    "Call setLayoutManager with a non-null argument.");
            return;
        }
        mLayout.scrollToPosition(position);
        awakenScrollBars();
    }

    public void smoothScrollToPosition(int position) {
        if (mLayoutFrozen) {
            return;
        }
        if (mLayout == null) {
            Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. " +
                    "Call setLayoutManager with a non-null argument.");
            return;
        }
        mLayout.smoothScrollToPosition(this, mState, position);
    }

我们要做的就是在LayoutManager上做点文章,RecyclerView库为我们提供了LinearSmoothScroller类去实现线性滑动效果,我们只需继承此类,根据需求在重写方法中计算滑动delta值,然后复写LayoutManager的scroll相关方法即可。
以常见的GridLayoutManager为例:

public class CenterScrollGridLayoutManager extends GridLayoutManager {

    private Context context;

    private boolean isInLayout;
    private boolean isScrolling;
    
    /* ... constructors... */
    
    public void smoothScrollToCenter(int position) {
        isScrolling = true;
        RecyclerView.SmoothScroller smoothScroller = new CenterScroller(context);
        smoothScroller.setTargetPosition(position);
        startSmoothScroll(smoothScroller);
        isScrolling = false;
    }

    @Override
    public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
        smoothScrollToCenter(position);
    }

    // 关键方法 - 焦点改变时触发滚动
    @Override
    public boolean onRequestChildFocus(RecyclerView parent, View child, View focused) {
        if (!isInLayout && !isScrolling) {
            smoothScrollToCenter(getPosition(child));
        }
        return true;
    }

    // 重写此方法用于在数据加载完成时触发滚动到中部
    @Override
    public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
        isInLayout = true;
        try {
            super.onLayoutChildren(recycler, state);
            if (getFocusedChild() != null &&  !isScrolling) {
                if (getChildCount() - getPosition(getFocusedChild()) >= getSpanCount()) {
                    smoothScrollToCenter(getPosition(getFocusedChild()));
                }
            }
        } catch (IndexOutOfBoundsException ignored) {}
        isInLayout = false;
    }
    // 自定义滚动效果的Scroller
    private class CenterScroller extends LinearSmoothScroller {

        private static final float MILLISECONDS_PER_INCH = 50f; //default is 25f (bigger = slower)

        public CenterScroller(Context context) {
            super(context);
        }
        // 这里计算滚动到中部的偏移量
        @Override
        public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int snapPreference) {
            return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
        }
        // 滚动速度控制
        @Override
        protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
            return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、简历准备 1、个人技能 (1)自定义控件、UI设计、常用动画特效 自定义控件 ①为什么要自定义控件? Andr...
    lucas777阅读 5,278评论 2 54
  • 1.下列哪些语句关于内存回收的说明是正确的? (b )A、 程序员必须创建一个线程来释放内存B、内存回收程序负责释...
    悠悠我心_4a00阅读 580评论 0 2
  • 本人初学Android,最近做了一个实现安卓简单音乐播放功能的播放器,收获不少,于是便记录下来自己的思路与知识总结...
    落日柳风阅读 19,254评论 2 41
  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,879评论 1 45
  • 或许是由于老妈最近很喜欢养生,或许是因为前段时间买了车,作为新手要早点上路避开交通高峰期,或许是因为参加了一些微信...
    儒媛阅读 225评论 0 0