GridView & ListView (Android盒子开发)

一.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盒子开发)

时间: 2024-10-21 10:40:20

GridView & ListView (Android盒子开发)的相关文章

Android 快速开发系列 打造万能的ListView GridView 适配器

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38902805 ,本文出自[张鸿洋的博客] 1.概述 相信做Android开发的写得最多的就是ListView,GridView的适配器吧,记得以前开发一同事开发项目,一个项目下来基本就一直在写ListView的Adapter都快吐了~~~对于Adapter一般都继承BaseAdapter复写几个方法,getView里面使用ViewHolder模式,其实大部分的代码基本都是类似的

Android开发:自定义GridView/ListView数据源

http://mobile.51cto.com/android-259861.htm 在开发中,我们常常会遇到比较复杂的GridView/ListView的布局,重新实现BaseAdapter不但能帮助我们实现我们想要的布局效果,并且在绑定大数据量时也不会感觉有卡壳现象.记得以前用一个ListView直接去绑定手机内的联系人Cursor(一百多号人),滑动的时候就会有卡的感觉.今天决定写个Demo是因为在项目中可能会要实现这样的一个效果:一个GridView中绑定4个ImageButton,有些

Android 高速开发系列 打造万能的ListView GridView 适配器

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38902805 ,本文出自[张鸿洋的博客] 1.概述 相信做Android开发的写得最多的就是ListView,GridView的适配器吧,记得曾经开发一同事开发项目.一个项目下来基本就一直在写ListView的Adapter都快吐了~~~对于Adapter一般都继承BaseAdapter复写几个方法,getView里面使用ViewHolder模式.事实上大部分的代码基本都是相似

Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载)

Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载) POSTED ON 2014年6月27日 BY 天边的星星 本文内容: 1.横向ListView的所有实现思路; 2.其中一个最通用的思路HorizontalListView,并基于横向ListView开发一个简单的相册: 3.实现的横向ListView在点击.浏览时item背景会变色,并解决了listview里setSelected造成item的选择状态混乱的问题.

android应用开发全程实录-你有多熟悉listview

http://blog.csdn.net/notice520/article/details/7040962 今天给大家带来<android应用开发全程实录>中关于listview和adatper中的部分.包括listview的基本使用,listview的优化等. 我们经常会在应用程序中使用列表的形式来展现一些内容,所以学好ListView是非常必需的.ListView也是Android中比较难以使用的控件,这节内容就将详细解读ListView的用法. 一个ListView通常有两个职责. (

【转】android应用开发全程实录-你有多熟悉listview?---不错

原文网址:http://www.cnblogs.com/noTice520/archive/2011/12/05/2276379.html 今天给大家带来<android应用开发全程实录>中关于listview和adatper中的部分.包括listview的基本使用,listview的优化等. 我们经常会在应用程序中使用列表的形式来展现一些内容,所以学好ListView是非常必需的.ListView也是Android中比较难以使用的控件,这节内容就将详细解读ListView的用法. 一个Lis

Android中取消GridView &amp; ListView默认的点击背景色

方法一: gridView.setSelector(new ColorDrawable(Color.TRANSPARENT)); listView.setSelector(new ColorDrawable(Color.TRANSPARENT)); 在代码中初始化的时候设置其属性. 方法二: <GridView android:listSelector="@android:color/transparent" android:numColumns="auto_fit&q

【读书笔记-《Android游戏编程之从零开始》】6.Android 游戏开发常用的系统控件(TabHost、ListView)

3.9 TabSpec与TabHost TabHost类官方文档地址:http://developer.android.com/reference/android/widget/TabHost.html Android 实现tab视图有2种方法,一种是在布局页面中定义<tabhost>标签,另一种就是继承tabactivity.但是我比较喜欢第二种方式,应为如果页面比较复杂的话你的XML文件会写得比较庞大,用第二种方式XML页面相对要简洁得多. <?xml version="1

Android应用开发编译框架流程与IDE及Gradle概要

1 背景 建议阅读本文之前先阅读<Android Studio入门到精通>和<Groovy脚本基础全攻略>及<Gradle脚本基础全攻略>三篇博客作为背景知识,这样才能更好.更系统的串起来.本文的核心就是下图: 关于Gradle的Android插件本文不会过多的说明,只给一个抛砖引玉的提示,详细使用参见文档API及Gradle配置,其实个性化的构建配置一般都是Gradle与Groovy的编写,与Android插件没太多关系,所以重点还在Groovy与Gradle构建.