横向ListView(四) —— 添加滚动条

在前面的文章已经介绍了横向ListView的基础实现及头尾视图的添加等的实现,这篇文章将介绍为横向ListView添加滚动条;这一功能的添加和前面章节有些不同,前面章节添加功能都是在原来的控件上追加的,而滚动条的实现是以一个独立的控件存在的,以组合的形式添加到横向ListView中。

 

滚动条的实现思路:

    1.计算横向ListView可见区域的宽度

    2.计算整个横向ListView中所有数据都显示时的视图宽度(即理论上整个列表应该有的宽度)

    3.计算出左边不可见的部分理论上应该有的宽度

    4.根据比例计算出当前滚动条的显示宽度及显示位置(即width和left的值)

    5.将滚动条控件组合到横向ListView中,同时设置显示开关

 

先上完整源码:

1.滚动条控件源码:

package com.hss.os.horizontallistview;

import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;

/**
 * Created by Administrator on 2017/8/9.
 */

public class ScrollBar extends View {

    private AlphaAnimation animation;
    private int defaultVal=5;//滚动条的默认宽高值
    private ShowType type=ShowType.horizontal;

    private enum ShowType{
        horizontal,
        vertical
    }

    public ScrollBar(Context context) {
        super(context);
        init(context);
    }

    public ScrollBar(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ScrollBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public ScrollBar(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    private void init(Context context){
        setBackgroundColor(Color.parseColor("#3c3f41"));//设置默认背景颜色
        //创建AlphaAnimation(透明度动画)
        animation=new AlphaAnimation(1.0f, 0.1f);
        //设置动画时间
        animation.setDuration(1500);
        //设置动画重复次数
        animation.setRepeatCount(0);
        animation.setAnimationListener(animationListener);
    }

    Handler handler=new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            startAnimation(animation);
            return false;
        }
    });


    private Animation.AnimationListener animationListener=new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            setVisibility(INVISIBLE);//使用INVISIBLE而不是使用GONE,是因为GONE会触发requestLayout()执行,导致界面刷新
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }
    };

    /**
     * 将滚动条从父布局中移除
     * 必须调用这个方法执行移除操作,否则动画执行会有问题
     * @param parent
     */
    public void remove(ViewGroup parent){
        handler.removeMessages(0);
        //必须在从父布局中移除之前调用clearAnimation(),否则之后的动画执行会有问题
        clearAnimation();
        parent.removeViewInLayout(this);
    }

    /**
     * 控件没有使用头尾视图设定时使用
     * @param parent             父容器视图
     * @param firstItemIndex     在可见区域内第一个item的下标(不包含头视图)
     * @param lastItemIndex      在可见区域内最后一个item的下标(不包含尾视图)
     * @param itemCount          所有的item总个数(不包含头尾视图)
     */
    public void showVertical(ViewGroup parent,int firstItemIndex,int lastItemIndex,int itemCount){
        showVertical(parent,firstItemIndex,lastItemIndex,itemCount,0,0);
    }

    /**
     * 控件有使用头尾视图时使用
     * @param parent             父容器视图
     * @param firstItemIndex     在可见区域内第一个item的下标(不包含头视图)
     * @param lastItemIndex      在可见区域内最后一个item的下标(不包含尾视图)
     * @param itemCount          所有的item总个数(不包含头尾视图)
     * @param headVal            显示的头视图高度
     * @param footVal            显示的尾视图高度
     */
    public void showVertical(ViewGroup parent,int firstItemIndex,int lastItemIndex,int itemCount,int headVal,int footVal){
        type=ShowType.vertical;
        show(parent,firstItemIndex,lastItemIndex,itemCount,headVal,footVal);
    }

    /**
     * 控件没有使用头尾视图设定时使用
     * @param parent             父容器视图
     * @param firstItemIndex     在可见区域内第一个item的下标(不包含头视图)
     * @param lastItemIndex      在可见区域内最后一个item的下标(不包含尾视图)
     * @param itemCount          所有的item总个数(不包含头尾视图)
     */
    public void showHorizontal(ViewGroup parent,int firstItemIndex,int lastItemIndex,int itemCount){
        showHorizontal(parent,firstItemIndex,lastItemIndex,itemCount,0,0);
    }

    /**
     * 控件有使用头尾视图时使用
     * @param parent             父容器视图
     * @param firstItemIndex     在可见区域内第一个item的下标(不包含头视图)
     * @param lastItemIndex      在可见区域内最后一个item的下标(不包含尾视图)
     * @param itemCount          所有的item总个数(不包含头尾视图)
     * @param headVal            显示的头视图宽度
     * @param footVal            显示的尾视图宽度
     */
    public void showHorizontal(ViewGroup parent,int firstItemIndex,int lastItemIndex,int itemCount,int headVal,int footVal){
        type=ShowType.horizontal;
        show(parent,firstItemIndex,lastItemIndex,itemCount,headVal,footVal);
    }


    private int estimateVal=0;//预估的整个视图所有子项都显示出来时的高/宽(包含头尾视图)
    private int averageVal=0;//预估的每一个子视图的高/宽(item的平均高度)
    private int showCount=0;//当前显示的子项个数(不包含头、尾视图)

    /**
     *
     * @param parent             父容器视图
     * @param firstItemIndex     在可见区域内第一个item的下标(不包含头视图)
     * @param lastItemIndex      在可见区域内最后一个item的下标(不包含尾视图)
     * @param itemCount          所有的item总个数(不包含头尾视图)
     * @param headVal            显示的头视图高度
     * @param footVal            显示的尾视图高度
     */
    private void show(ViewGroup parent,int firstItemIndex,int lastItemIndex,int itemCount,int headVal,int footVal){
        setVisibility(INVISIBLE);//使用INVISIBLE而不是使用GONE,是因为GONE会触发requestLayout()执行,导致界面刷新
        if(parent.getChildCount()==0) return;//没有子视图则不显示滚动条
        //以下五行对数据的调整,是为了确保数据在逻辑上的正确性,确保之下的计算不会出现逻辑以外的情况
        firstItemIndex=firstItemIndex<0?0:firstItemIndex;
        lastItemIndex=lastItemIndex<0?0:lastItemIndex;
        lastItemIndex=lastItemIndex<firstItemIndex?firstItemIndex:lastItemIndex;
        itemCount=itemCount<=0?1:itemCount;
        itemCount=itemCount<=lastItemIndex? lastItemIndex+1:itemCount;

        if(lastItemIndex==0&&headVal==0&&footVal==0) return;//如果没有显示内容,则不显示滚动条

        showCount=lastItemIndex-firstItemIndex+1;
        ViewGroup.LayoutParams params=getLayoutParams();
        int left=0,top=0,right=0,bottom=0;
        switch (
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值