码迷,mamicode.com
首页 > 移动开发 > 详细

GridView & ListView (Android盒子开发)

时间:2015-09-14 21:19:44      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:

一.GridView在Android4.4下关于焦点的bug的解决方式

Android4.4下,关于GridView有一个关于焦点的bug。这个bug并不容易被发现,但是在电视盒子的开发过程中就很明显。具体表现是,Gridview会一直持有一个焦点,只要有数据,就一直会有一个子View是Selected状态。而且,当数据从无到有的时候,GridView还会抢焦点。

最后解决这个bug的方式是这样的,建立一个自定义的GridView,重写一个方法,

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

我并没有弄懂为啥,但是加上这句话确实就解决了这个bug。

二.选中项有放大效果的GirdView的实现

先在AnimaFactory类中包装静态缩放动画。

/**
 * 缩放动画,用于缩放控件
 * @param startScale 控件的起始尺寸倍率
 * @param endScale 控件的终点尺寸倍率
 * @return
 */
public static Animation zoomAnimation(float startScale, float endScale, int duration){
    ScaleAnimation anim = new ScaleAnimation(startScale, endScale, startScale, endScale,
            Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    anim.setFillAfter(true);
    anim.setDuration(duration);
    return anim;
}

然后在自定义GridView中加入如下方法。

/**
 * 实现本类onFocusChangeListener时调用此方法
 * @param v
 * @param hasFocus
 */
public void onFocusChange(View v, boolean hasFocus) {
    if (hasFocus) {
        zoomInView(lastView);
    } else {
        zoomOutView(lastView);
    }
}

/**
 * 外面调用OnItemSelectedListener的时候,调用这个方法
 * @param parent
 * @param view
 * @param position
 * @param id
 */
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
    zoomInView(view);
    if (view != lastView) {
        zoomOutView(lastView);
    }
    lastView=view;
}

/**
 * 放大
 * @param v
 */
private void zoomInView(View v) {
    if (v != null) {
        v.startAnimation(AnimaFactory.zoomAnimation(1.0f, 1.1f, 100));
    }
}

/**
 * 缩小
 * @param v
 */
private void zoomOutView(View v) {
    if (v != null) {
        v.startAnimation(AnimaFactory.zoomAnimation(1.1f, 1.0f, 100));
    }
}

其中,onSelected方法的调用效果是,把正在选中的View放大,把上一个选中的View即lastView缩小。然后lastView更新为当前选中的View。

这个方法在外面给GridView设置OnSelectedListener的时候调用。

同理,设置OnFocusChangeListener中要调用的onFucusChange方法。

这里还有一点要说的,虽然选中项放大了,但是它并不一定被画在最前面。为了保证不会被挡住,我们还要加一个方法。

/**
 * @description: <修改默认加载顺序(核心代码)>
 * @see android.view.ViewGroup#getChildDrawingOrder(int, int)
 * @param childCount 当前屏幕中显示的item个数
 * @param i 在数组中的位置,从0开始到childCount-1
 * @return 加载顺序
 */
@Override
protected int getChildDrawingOrder(int childCount, int i) {
    if (this.getSelectedItemPosition() != -1) {
        if (i + this.getFirstVisiblePosition() == this.getSelectedItemPosition()) {// 这是原本要在最后一个刷新的item
            return childCount - 1;
        }
        if (i == childCount - 1) {// 这是最后一个需要刷新的item
            return this.getSelectedItemPosition() - this.getFirstVisiblePosition();
        }
    }
    return i;
}

这段代码加上后,要在构造方法中加一句,

setChildrenDrawingOrderEnabled(true);

来保证加载顺序正确。

三.重置数据setList()方法中要注意的

有两种重置数据的方法,如果在Adapter中传入的数据,那么直接给gridView调用setAdapter即能重置数据。

另一种,是在Adapter中,写setList方法来传入数据。比如:

public void setList(List<VideoObject> list){
    notifyDataSetInvalidated();
    mList=list;
    notifyDataSetChanged();
}

notifiDataSetChange()方法比较好理解,因为重置数据后要刷新数据。那notifyDataSetInvalidated()起什么作用呢?它的作用是通知Adatper旧数据无效。如果不写这行代码,在重置数据的时候,可能会出现数组越界异常。

四.关于分页加载数据

因为电视盒子没有触屏,是通过遥控控制焦点来操作系统的。所以分页加载不是通过“下拉刷新”,而是通过焦点判断。而判断语句,在OnSelectedChangeListener中实现。

首先,要写代码来确定要需要请求数据的那一行的行数。这里我设为lastLineNum。

lastLineNum = (list.size() - 1) / gridView.getNumColumns();

这里的list是获取的数据,接下来设置监听。

gridView.setOnItemSelectedListener(new OnItemSelectedListener() {
    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        gridView.onItemSelected(parent, view, position, id);
        // 如果是分页加载最后一排,则要求分页数据
        if (lastLineNum != 0 && position / gridView.getNumColumns() == lastLineNum) {
            //在这里请求数据并更新视图
        }
        @Override
        public void onNothingSelected(AdapterView<?> parent) {

        }
});

请求数据更新视图,就在Adapter中addList,然后notifyDataSetChange就可以了。

五.获取正在显示的数据位置以及出现bug的修正方式

GridView和ListView都有一个方法是getFirstVisiblePosition(),是获取第一个正在显示的数据的位置。但是这个方法有个缺陷,就是当数据,只显示一半甚至更少的时候,这个方法判断它已经显示了。然而它并没有完全显示。

我当时要实现的功能是当ListView上侧有数据没有显示的时候,上侧有一个箭头,而ListView下侧有数据没有显示的时候,下侧有一个箭头。这两个箭头都是ImageView。

后来解决这个缺陷是用下面的这种方式。

lvChildCategory.setOnScrollListener(new OnScrollListener() {
    public void onScrollStateChanged(AbsListView view, int scrollState) {

    }
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        if (totalItemCount == 0 || visibleItemCount == 0) {
            //当无数据显示的时候,上下侧两个箭头均不显示
            ivArrayUp.setVisibility(View.INVISIBLE);
            ivArrayDown.setVisibility(View.INVISIBLE);
            return;
        } else {
            //当有数据显示的时候
            if (firstVisibleItem > 0) {
                //当第一个显示的数据不是第一个数据时,箭头显示
                ivArrayUp.setVisibility(View.VISIBLE);
            } else {
                //当第一个显示的数据是第一个数据的时候,加判断
                //第一个数据的上坐标
                int firstTop = view.getChildAt(0).getTop();
                //ListView的上坐标
                int paddingTop = view.getListPaddingTop();
                //如果第一个数据的上坐标没超过了ListView的边界,那么上箭头不显示
                int spaceAbove = paddingTop - firstTop;
                if (spaceAbove <= 0)
                    ivArrayUp.setVisibility(View.INVISIBLE);
            }
            //下箭头与上箭头同理
            if (firstVisibleItem + visibleItemCount < totalItemCount) {
                ivArrayDown.setVisibility(View.VISIBLE);
            } else {
                int lastBottom = view.getChildAt(view.getChildCount() - 1).getBottom();
                int paddingBottom = view.getListPaddingBottom();
                if (lastBottom <= (view.getHeight() - paddingBottom))
                    ivArrayDown.setVisibility(View.INVISIBLE);
            }
        }
    }
});

即获取子View的上坐标和ListView的上坐标来判断。解决此缺陷。

六.GridView的视图小细节

GridView中,selector会影响子布局的排版。一般并不明显,但是如果selector是一层比较厚的阴影的话,子布局加上selector则会缩水一圈。

要解决这个问题,可以调整GirdView的horizontalSpacing和verticalSpacing属性,分别表示子布局横向间隙和纵向间隙,这两个值是可以设置为负数的。如果子布局加上selector后缩水太严重,这两个值调整为负数能解决这个问题。

同时,GridView的子布局宽度是无法调整的,也是要通过设置numColumns和horizontalSpacing来调整宽度。

GridView & ListView (Android盒子开发)

标签:

原文地址:http://my.oschina.net/sfshine/blog/506027

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!