android 打造变化多端的SeekBar(垂直和水平)

SeekBar相信用的人不是很多,一般都是用水平SeekBar就可以了。但是之前项目中考虑使用垂直的SeekBar,就要继承重写SeekBar才能用。而垂直SeekBar在百度搜了一下,关于这方面文章还是很少,有一些还是不全面。我又去了github找了一下,找到了一个垂直的效果以及源码,我就写了一个滚动SeekBar翻页listview的数据效果。所以这篇博客中源码下载中,有三个项目源码,干货多多。

下载地址:http://download.csdn.net/detail/qq_16064871/9445535

1、先看一下水平SeekBar

这种是用系统SeekBar,是水平的。我在滚动SeekBar上面加了页码提示。滚动页码时候也可以翻页listview的数据。先看效果。

看着上面效果还是很不错吧,觉得很赞。接下来看看原理。

其实这个原理很简单,这个滚动SeekBar以及listview管理都是一系列的序号,就是多少项数据的索引吧。用一个list记住每一页的表头第一项的索引值,因为每一页数据都是固定。就比如每一页数据是30,那么第一页第一项索引就是0,第二页是30,第三页是60.。。。以此类推,还有根据你滑动进度条,获得那一页数据,再根据这一页表头索引加上30就是这一页的数据。所以管理都是序号或者说索引。所以所以最后获取数据是这样的mArrayList.get(mPageItemsIndex.get(position).intValue())。而这个就是每一页数据索引值mPageItemsIndex.get(position).intValue()。好了说了那么多,看代码吧。

先看这个public class LevelPageSeekBar extends SeekBar

package com.org.view;

import com.org.pageseekbar.R;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.SeekBar;
import android.widget.TextView;
//自定义页码进度条
public class LevelPageSeekBar extends SeekBar {
	private QuickAction mSeekBarTipsQuickAction;
	private int mPageCount = 0;
	private boolean mIsTouch = false;
	private TextView mTipsTitle;
	private OnSeekBarPageChangeListener mBarPageChangeListener;

	public LevelPageSeekBar(Context context, AttributeSet attrs) {
		super(context, attrs);

		mSeekBarTipsQuickAction = new QuickAction(context, QuickAction.HORIZONTAL);
		ActionItem tipsItem      = new ActionItem(0, context.getResources().getString(R.string.Move), null);
		tipsItem.setIcon(null);
		mSeekBarTipsQuickAction.addActionItem(tipsItem);
		mTipsTitle = (TextView)mSeekBarTipsQuickAction.GetActionItemsGroup().getChildAt(0).findViewById(R.id.tv_title);

		//设置系统进度条的监听
		setOnSeekBarChangeListener(mSeekBarChangeListener);
		//最大页码是10000
		setMax(10000);
	}

	//进度条改变的接口
	public interface OnSeekBarPageChangeListener {
		public abstract void setSeekBarScrolling(TextView tips, int page);
		public abstract void setSeekBarPageChanged(int page);
	}

	//注册接口
	public void setSeekBarPageChangeListener(OnSeekBarPageChangeListener listener) {
		mBarPageChangeListener = listener;
	}

	//设置进度条页数
	public void setPagesCount(int count) {
		mPageCount = count;
	}

	//设置不显示弹出第几页提示
	public void setHideSeekPopWindow() {
		mSeekBarTipsQuickAction.dismiss();
	}

	private int getProgressIsPageIndex(int progress, int max) {
		if (mPageCount < 2) {
			if (progress == 0) return 0;
			else return 1;
		}
		if (progress == 0) return 0;
		// 获取每一块的进度值
		int progressSizeEveryPage = getMax()/(mPageCount-1);
		for (int i = 1; i < mPageCount; i++) {
			if (progress <= (i)*progressSizeEveryPage && progress > ((i-1)*progressSizeEveryPage)) {
				if (progress > (2*i-1)*progressSizeEveryPage/2 ) return i;
				else return i-1;
			}
		}
		return mPageCount-1;
	}

	//外面调用上下按键翻页,需要同时滚动进度条效果
	public void setProgressSpecialPage(int pageIndex, int count) {
		if (count <= 1) {
			setProgress(0);
			return;
		}

		mPageCount = count;
		if (pageIndex < 0 || pageIndex >= mPageCount) return;

		int progressSizeEveryPage = getMax()/(mPageCount-1);
		setProgress( progressSizeEveryPage*pageIndex);
	}

	//弹出当前显示第几页的提示
	private void showSeekPopWindow() {
		if (mSeekBarTipsQuickAction == null) return;
		// 获取每一刻度的宽度
		float thumb_x = ((float)this.getWidth() - 44)/(float)this.getMax();
		// 获取控件的屏幕位置
		int[] location = new int[2];
		this.getLocationOnScreen(location);

		int x = (int) ((float)thumb_x*(float)getProgress()) + 22;

		if (mBarPageChangeListener != null)
			mBarPageChangeListener.setSeekBarScrolling(mTipsTitle, getProgressIsPageIndex(getProgress(), getMax()));
		mSeekBarTipsQuickAction.show(this, (int)(x + location[0]), location[1]);
	}

	//系统进度条的监听方法
	private OnSeekBarChangeListener mSeekBarChangeListener = new OnSeekBarChangeListener() {
		@Override
		public void onStopTrackingTouch(SeekBar arg0) {
			mIsTouch = false;
			setHideSeekPopWindow();
		}

		@Override
		public void onStartTrackingTouch(SeekBar arg0) {
			mIsTouch = true;
		}

		@Override
		public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
			if (mIsTouch) showSeekPopWindow();
			if (mBarPageChangeListener != null)
				mBarPageChangeListener.setSeekBarPageChanged( getProgressIsPageIndex(getProgress(), getMax()));
		}
	};
}

再看怎么调用或者说使用。看MainActivity

package com.org.pageseekbar;

import java.util.ArrayList;

import com.org.view.LevelPageSeekBar;
import com.org.view.LevelPageSeekBar.OnSeekBarPageChangeListener;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity
implements OnSeekBarPageChangeListener,OnClickListener{

	//页码进度条
	private LevelPageSeekBar mPageSeekBar;
	//数据源
	private ArrayList<String> mArrayList;
	// 一页最多多少条数据
	protected int mMaxShowLinesPage = 20;
	// 当前是第几页
	protected int mCurrentSelectPageIndex = 0;
	// 当前有多少页
	protected int mPagesCount = 0;
	// 当前的有效记录数
	protected int mRecordCount = 0;
	// 存放每页数据第一条数据的索引
	protected ArrayList<Integer> mEveryPageOffestArray = new ArrayList<Integer>();
	// 当前页面的每一项的偏移数据 方便检索数据和删除数据
	protected ArrayList<Integer> mPageItemsIndex = new ArrayList<Integer>();
	//listview的适配器
	protected ListViewAdapter mAdapter;
	//测试数据的条数
	private int mnTestCount = 530;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		initDatas();
		initView();
	}

	private void initDatas() {
		if (mArrayList == null) {
			mArrayList = new ArrayList<String>();
			for (int i = 0; i < mnTestCount; i++) {
				mArrayList.add("第   " + String.valueOf(i) + " 项");
			}
		}
	}

	private void initView() {
		mPageSeekBar = (LevelPageSeekBar)findViewById(R.id.seekBar);
		mPageSeekBar.setSeekBarPageChangeListener(this);

		Button imageviewUp = (Button)findViewById(R.id.imageviewUp);
		imageviewUp.setOnClickListener(this);
		Button imageviewDown = (Button)findViewById(R.id.imageviewDown);
		imageviewDown.setOnClickListener(this);
	    ListView listView = (ListView)findViewById(R.id.listView1);
	    mAdapter = new ListViewAdapter(this);
	    listView.setAdapter(mAdapter);

	    initResetListView(0);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.imageviewUp:
			setPrePage();
			break;
		case R.id.imageviewDown:
			setAftPage();
			break;
		default:
			break;
		}
	}

	//初始化进度条管理数据显示
	protected void initResetListView(int pageIndex) {
		mRecordCount = mArrayList.size();

		// 计算有多少页数据
	    mPagesCount = mRecordCount/mMaxShowLinesPage + (mRecordCount%mMaxShowLinesPage == 0 ? 0 : 1);

	    // 判断 页面数目是2的时候, 简化为1页
	    if (mPagesCount == 2) {
	    	mMaxShowLinesPage = mMaxShowLinesPage * 2;
	    	mPagesCount = 1;
	    } else {
	    	mMaxShowLinesPage = 20;
	    }

		// 设置当前选中也为0
		mCurrentSelectPageIndex = pageIndex;
		if (mCurrentSelectPageIndex >= mPagesCount)
			mCurrentSelectPageIndex = mPagesCount - 1;
		//刷新每一页的首偏移
		setResetEveryPageOffestArray();
		//根据首偏移,得到这一页偏移序号
	    setResetPageItemsIndex(mCurrentSelectPageIndex);
		//上下按键翻页,需要同时滚动进度条效果.如果只有两页数据,不显示进度条
	    setSelectPageControl(mCurrentSelectPageIndex, mPagesCount,false);

		//总共几页,设置到进度条控件
	    mPageSeekBar.setPagesCount(mPagesCount);
	}

	//刷新每一页的首偏移
	protected void setResetEveryPageOffestArray() {
		int nValidItemNums = 0;
		mEveryPageOffestArray.clear();
		//记住每页的首偏移序号
		for (int i = 0; i < mPagesCount; i++) {
			int nRecordIndex = GetCountSpecialPage(i);
				mEveryPageOffestArray.add(nValidItemNums);
				nValidItemNums = nValidItemNums + nRecordIndex;
		}

		if (nValidItemNums != mRecordCount) {
			mRecordCount = nValidItemNums;
			// 计算有多少页数据
		    mPagesCount = mRecordCount/mMaxShowLinesPage + (mRecordCount%mMaxShowLinesPage == 0 ? 0 : 1);
		}
	}

	//根据首偏移,得到这一页偏移序号
	protected void setResetPageItemsIndex(int pageIndex) {
		if (pageIndex >= mEveryPageOffestArray.size()) return;
		int pageItemsCount = GetCountSpecialPage(pageIndex);
		int nRecordIndex = mEveryPageOffestArray.get(pageIndex).intValue();
		mPageItemsIndex.clear();
		//首偏移开始累加
		for(int i = nRecordIndex; i < pageItemsCount + nRecordIndex; i++) {
			mPageItemsIndex.add(i);
		}

		//刷新listview的适配器
		if (mAdapter != null) {
			mAdapter.notifyDataSetChanged();
		}
	}

	// 获取当前页面多少数据
	protected int GetCountSpecialPage(int nPage) {
		if (nPage < 0) return 0;
		if(nPage < (mPagesCount-1)) return mMaxShowLinesPage;
		//如果是最后一页,就是总的数据减去前面几页*每一页的数据
		//因为页码是从0开始,所以这里是最后一页
		if (nPage == mPagesCount - 1) return mRecordCount - mMaxShowLinesPage*(mPagesCount-1);
		return 0;
	}

	//上一页
	protected void setPrePage() {
		if (mCurrentSelectPageIndex == 0) return;
		mCurrentSelectPageIndex -= 1;
		//根据首偏移,得到这一页偏移序号
		setResetPageItemsIndex(mCurrentSelectPageIndex);
		// 翻页控件
		setSelectPageControl(mCurrentSelectPageIndex, mPagesCount,true);
	}

	//下一页
	protected void setAftPage() {
		if (mCurrentSelectPageIndex == (mPagesCount-1)) return;
		mCurrentSelectPageIndex += 1;
		//根据首偏移,得到这一页偏移序号
		setResetPageItemsIndex(mCurrentSelectPageIndex);
		// 翻页控件
		setSelectPageControl(mCurrentSelectPageIndex, mPagesCount,true);
	}

	//进度条滑动改变的数据,进行刷新
	protected void setPageChanged(int index, boolean isSetProgress) {
		if (index < 0 || index >= mPagesCount || mCurrentSelectPageIndex == index) return;
		mCurrentSelectPageIndex = index;

		// 刷新每一项的索引数据
		setResetPageItemsIndex(mCurrentSelectPageIndex);
		// 翻页控件
		setSelectPageControl(mCurrentSelectPageIndex, mPagesCount, isSetProgress);
	}

	//上下按键翻页,需要同时滚动进度条效果.如果只有两页数据,不显示进度条
	protected void setSelectPageControl(int index, int count, boolean isSet) {
		View selectPageBar = findViewById(R.id.layoutShow);
		if (selectPageBar != null) {
			//如果只有两页数据,不显示进度条
		if (count <= 1) selectPageBar.setVisibility(View.GONE);
		else selectPageBar.setVisibility(View.VISIBLE);
		//上下按键翻页,需要同时滚动进度条效果
		if (mPageSeekBar != null && isSet == true)
			mPageSeekBar.setProgressSpecialPage(mCurrentSelectPageIndex, mPagesCount);
		}
	}

	//弹出滑动第几页显示
	@Override
	public void setSeekBarScrolling(TextView tips, int page) {
		if (tips == null) return;
		String tip_0 = String.format(getString(R.string.CurrentPageTipsFormate), page+1);
		String tip_1 = String.format(getString(R.string.CurrentPageTipsFormate2), mPagesCount);
		tips.setText(tip_0 + "/" + tip_1);
	}

	//进度条滑动改变的数据,进行刷新
	@Override
	public void setSeekBarPageChanged(int page) {
		setPageChanged(page, false);
	}

	private class ViewHolder{
		TextView textView;
	}

	private class ListViewAdapter extends BaseAdapter{
		private Context mContext;
		private LayoutInflater mLayoutInflater;
		public ListViewAdapter(Context context) {
			mContext = context;
			mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		}
		@Override
		public int getCount() {
			return mPageItemsIndex.size();
		}

		@Override
		public Object getItem(int position) {
			return 0;
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder vHolder = null;
			if (convertView == null) {
				vHolder = new ViewHolder();
				convertView = mLayoutInflater.inflate(R.layout.listview_item, null);
				vHolder.textView = (TextView)convertView.findViewById(R.id.textView1);
				convertView.setTag(vHolder);
			}else {
				vHolder = (ViewHolder) convertView.getTag();
			}
			vHolder.textView.setText(mArrayList.get(mPageItemsIndex.get(position).intValue()));
			return convertView;
		}
	}

}

至于弹出显示页码的效果,这个代码有点多,就不一一展示了。有兴趣下载本博客源码。

弹出显示页码的效果有兴趣可以看看这个,也是差不多的:Android 单击listview弹出popupwindow弹出框

2、现在看看我在github上找的垂直SeekBar效果

这里面原理是这样的。你的进度条旋转了,你的画布也要旋转。还有你的Thumb这要重新调转位置,跟着一起滑动。有两种情况,从上图都可以看出了。一种是从上而下,还有一种就是从下而上。

从上而下那个调整画布是这样的,还有一些计算。。。看源码也是继承SeekBar

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(h, w, oldh, oldw);
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(heightMeasureSpec, widthMeasureSpec);
        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
    }

    //初始值从上往下
    protected void onDraw(Canvas c) {
        c.rotate(90);
        c.translate(0, -getWidth());

        super.onDraw(c);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            return false;
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
            	int i=0;
            	i=getMax() - (int) (getMax() * event.getY() / getHeight());
                setProgress(100-i);
                Log.i("Progress",getProgress()+"");
                onSizeChanged(getWidth(), getHeight(), 0, 0);
                break;

            case MotionEvent.ACTION_CANCEL:
                break;
        }
        return true;
    }

那么从下往上滑动,肯定要反过来旋转了

   protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(h, w, oldh, oldw);
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(heightMeasureSpec, widthMeasureSpec);
        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
    }

    //初始值从下往上
    protected void onDraw(Canvas c) {
        c.rotate(-90);
        c.translate(-getHeight(),0);

        super.onDraw(c);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            return false;
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
            	int i=0;
            	i=getMax() - (int) (getMax() * event.getY() / getHeight());
                setProgress(i);
                Log.i("Progress",getProgress()+"");
                onSizeChanged(getWidth(), getHeight(), 0, 0);
                break;

            case MotionEvent.ACTION_CANCEL:
                break;
        }
        return true;
    }

其实就是这么简单的。

3、看看我写的垂直SeekBar效果

还是一样,先看效果。

也是对这个listview的数据管理的。就是没有弹出页码的提示,因为弹出感觉不好看,就删了。

看源码:VerticalPageSeekBar extends SeekBar

package com.vertical.view;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.SeekBar;
//自定义页码进度条
public class VerticalPageSeekBar extends SeekBar {
	private int mPageCount = 0;
	private OnSeekBarPageChangeListener mBarPageChangeListener;

    public VerticalPageSeekBar(Context context) {
        super(context);
    }

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

	public VerticalPageSeekBar(Context context, AttributeSet attrs) {
		super(context, attrs);

		//设置系统进度条的监听
		super.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

			@Override
			public void onStopTrackingTouch(SeekBar arg0) {
			}

			@Override
			public void onStartTrackingTouch(SeekBar arg0) {
			}

			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
					boolean fromUser) {
				if (mBarPageChangeListener != null)
					//接口回调
					mBarPageChangeListener.setSeekBarPageChanged( getProgressIsPageIndex(progress, getMax()));
			}
		});

		setMax(1000);
	}

	//进度条改变的接口
	public interface OnSeekBarPageChangeListener {
		public abstract void setSeekBarPageChanged(int page);
	}

	//注册接口
	public void setSeekBarPageChangeListener(OnSeekBarPageChangeListener listener) {
		mBarPageChangeListener = listener;
	}

	//Thumb的变化情况
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(h, w, oldh, oldw);
    }

    //测量宽度也需要旋转
    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(heightMeasureSpec, widthMeasureSpec);
        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
    }

    //画布旋转90
    protected void onDraw(Canvas c) {
        c.rotate(-90);
        c.translate(-getHeight(),0);

        super.onDraw(c);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            return false;
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
            case MotionEvent.ACTION_UP:
            	int i=0;
            	//设置y值为进度条的值
            	i=getMax() - (int) (getMax() * event.getY() / getHeight());
                setProgress(i);
                onSizeChanged(getWidth(), getHeight(), 0, 0);
                break;

            case MotionEvent.ACTION_CANCEL:
                break;
        }
        return true;
    }

	//设置进度条页数
	public void setPagesCount(int count) {
		mPageCount = count;
	}

	//分页的进度条的段值
	private int getProgressIsPageIndex(int progress, int max) {
		if (mPageCount < 2) {
			if (progress == 0) return 0;
			else return 1;
		}
		if (progress == 0) return 0;
		// 获取每一块的进度值
		int progressSizeEveryPage = getMax()/(mPageCount-1);
		for (int i = 1; i < mPageCount; i++) {
			if (progress <= (i)*progressSizeEveryPage && progress > ((i-1)*progressSizeEveryPage)) {
				if (progress > (2*i-1)*progressSizeEveryPage/2 ) return i;
				else return i-1;
			}
		}
		return mPageCount-1;
	}

	//外面调用上下按键翻页,需要同时滚动进度条效果
	public void setProgressSpecialPage(int pageIndex, int count) {
		if (count <= 1) {
			setProgress(0);
			return;
		}

		mPageCount = count;
		if (pageIndex < 0 || pageIndex >= mPageCount) return;

		int progressSizeEveryPage = getMax()/(mPageCount-1);

		setProgress( progressSizeEveryPage*pageIndex);
		//设置进度条按钮跟着移动
        onSizeChanged(getWidth(), getHeight(), 0, 0);
	}
}

还有怎么使用MainActivity

package com.vertical.pageseekbar;

import java.util.ArrayList;

import com.vertical.pageseekbar.R;
import com.vertical.view.VerticalPageSeekBar;
import com.vertical.view.VerticalPageSeekBar.OnSeekBarPageChangeListener;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity
implements OnSeekBarPageChangeListener,OnClickListener{

	//页码进度条
	private VerticalPageSeekBar mPageSeekBar;
	//数据源
	private ArrayList<String> mArrayList;
	// 一页最多多少条数据
	protected int mMaxShowLinesPage = 20;
	// 当前是第几页
	protected int mCurrentSelectPageIndex = 0;
	// 当前有多少页
	protected int mPagesCount = 0;
	// 当前的有效记录数
	protected int mRecordCount = 0;
	// 存放每页数据第一条数据的索引
	protected ArrayList<Integer> mEveryPageOffestArray = new ArrayList<Integer>();
	// 当前页面的每一项的偏移数据 方便检索数据和删除数据
	protected ArrayList<Integer> mPageItemsIndex = new ArrayList<Integer>();
	//listview的适配器
	protected ListViewAdapter mAdapter;
	//测试数据的条数
	private int mnTestCount = 230;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		initDatas();
		initView();
	}

	private void initDatas() {
		if (mArrayList == null) {
			mArrayList = new ArrayList<String>();
			for (int i = 0; i < mnTestCount; i++) {
				mArrayList.add("第   " + String.valueOf(i) + " 项");
			}
		}
	}

	private void initView() {
		mPageSeekBar = (VerticalPageSeekBar)findViewById(R.id.seekBar);
		mPageSeekBar.setSeekBarPageChangeListener(this);

		Button imageviewUp = (Button)findViewById(R.id.imageviewUp);
		imageviewUp.setOnClickListener(this);
		Button imageviewDown = (Button)findViewById(R.id.imageviewDown);
		imageviewDown.setOnClickListener(this);
	    ListView listView = (ListView)findViewById(R.id.listView1);
	    mAdapter = new ListViewAdapter(this);
	    listView.setAdapter(mAdapter);

	    initResetListView(0);
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.imageviewUp:
			setPrePage();
			break;
		case R.id.imageviewDown:
			setAftPage();
			break;
		default:
			break;
		}
	}

	//初始化进度条管理数据显示
	protected void initResetListView(int pageIndex) {
		mRecordCount = mArrayList.size();

		// 计算有多少页数据
	    mPagesCount = mRecordCount/mMaxShowLinesPage + (mRecordCount%mMaxShowLinesPage == 0 ? 0 : 1);

	    // 判断 页面数目是2的时候, 简化为1页
	    if (mPagesCount == 2) {
	    	mMaxShowLinesPage = mMaxShowLinesPage * 2;
	    	mPagesCount = 1;
	    } else {
	    	mMaxShowLinesPage = 20;
	    }

		// 设置当前选中也为0
		mCurrentSelectPageIndex = pageIndex;
		if (mCurrentSelectPageIndex >= mPagesCount)
			mCurrentSelectPageIndex = mPagesCount - 1;
		//刷新每一页的首偏移
		setResetEveryPageOffestArray();
		//根据首偏移,得到这一页偏移序号
	    setResetPageItemsIndex(mCurrentSelectPageIndex);
		//上下按键翻页,需要同时滚动进度条效果.如果只有两页数据,不显示进度条
	    setSelectPageControl(mCurrentSelectPageIndex, mPagesCount,false);
		//总共几页,设置到进度条控件
	    mPageSeekBar.setPagesCount(mPagesCount);
	}

	//刷新每一页的首偏移
	protected void setResetEveryPageOffestArray() {
		int nValidItemNums = 0;
		mEveryPageOffestArray.clear();
		//记住每页的首偏移序号
		for (int i = 0; i < mPagesCount; i++) {
			int nRecordIndex = GetCountSpecialPage(i);
				mEveryPageOffestArray.add(nValidItemNums);
				nValidItemNums = nValidItemNums + nRecordIndex;
		}

		if (nValidItemNums != mRecordCount) {
			mRecordCount = nValidItemNums;
			// 计算有多少页数据
		    mPagesCount = mRecordCount/mMaxShowLinesPage + (mRecordCount%mMaxShowLinesPage == 0 ? 0 : 1);
		}
	}

	//根据首偏移,得到这一页偏移序号
	protected void setResetPageItemsIndex(int pageIndex) {
		if (pageIndex >= mEveryPageOffestArray.size()) return;
		int pageItemsCount = GetCountSpecialPage(pageIndex);
		int nRecordIndex = mEveryPageOffestArray.get(pageIndex).intValue();
		mPageItemsIndex.clear();
		//首偏移开始累加
		for(int i = nRecordIndex; i < pageItemsCount + nRecordIndex; i++) {
			mPageItemsIndex.add(i);
		}

		//刷新listview的适配器
		if (mAdapter != null) {
			mAdapter.notifyDataSetChanged();
		}
	}

	// 获取当前页面多少数据
	protected int GetCountSpecialPage(int nPage) {
		if (nPage < 0) return 0;
		if(nPage < (mPagesCount-1)) return mMaxShowLinesPage;
		//如果是最后一页,就是总的数据减去前面几页*每一页的数据
		//因为页码是从0开始,所以这里是最后一页
		if (nPage == mPagesCount - 1) return mRecordCount - mMaxShowLinesPage*(mPagesCount-1);
		return 0;
	}

	//上一页
	protected void setPrePage() {
		if (mCurrentSelectPageIndex == 0) return;
		mCurrentSelectPageIndex -= 1;
		//根据首偏移,得到这一页偏移序号
		setResetPageItemsIndex(mCurrentSelectPageIndex);
		// 翻页控件
		setSelectPageControl(mCurrentSelectPageIndex, mPagesCount,true);
	}

	//下一页
	protected void setAftPage() {
		if (mCurrentSelectPageIndex == (mPagesCount-1)) return;
		mCurrentSelectPageIndex += 1;
		//根据首偏移,得到这一页偏移序号
		setResetPageItemsIndex(mCurrentSelectPageIndex);
		// 翻页控件
		setSelectPageControl(mCurrentSelectPageIndex, mPagesCount,true);
	}

	//进度条滑动改变的数据,进行刷新
	protected void setPageChanged(int index, boolean isSetProgress) {
		if (index < 0 || index >= mPagesCount || mCurrentSelectPageIndex == index) return;
		mCurrentSelectPageIndex = index;

		// 刷新每一项的索引数据
		setResetPageItemsIndex(mCurrentSelectPageIndex);
		// 翻页控件
		setSelectPageControl(mCurrentSelectPageIndex, mPagesCount, isSetProgress);
	}

	//上下按键翻页,需要同时滚动进度条效果.如果只有两页数据,不显示进度条
	protected void setSelectPageControl(int index, int count, boolean isSet) {
		View selectPageBar = findViewById(R.id.layoutShow);
		if (selectPageBar != null) {
			//如果只有两页数据,不显示进度条
		if (count <= 1) selectPageBar.setVisibility(View.GONE);
		else selectPageBar.setVisibility(View.VISIBLE);
		//上下按键翻页,需要同时滚动进度条效果
		if (mPageSeekBar != null && isSet == true)
			mPageSeekBar.setProgressSpecialPage(mCurrentSelectPageIndex, mPagesCount);
		}
	}

	//进度条滑动改变的数据,进行刷新
	@Override
	public void setSeekBarPageChanged(int page) {
		setPageChanged(page, false);
	}

	private class ViewHolder{
		TextView textView;
	}

	private class ListViewAdapter extends BaseAdapter{
		private Context mContext;
		private LayoutInflater mLayoutInflater;
		public ListViewAdapter(Context context) {
			mContext = context;
			mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		}
		@Override
		public int getCount() {
			return mPageItemsIndex.size();
		}

		@Override
		public Object getItem(int position) {
			return 0;
		}

		@Override
		public long getItemId(int position) {
			return 0;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			ViewHolder vHolder = null;
			if (convertView == null) {
				vHolder = new ViewHolder();
				convertView = mLayoutInflater.inflate(R.layout.listview_item, null);
				vHolder.textView = (TextView)convertView.findViewById(R.id.textView1);
				convertView.setTag(vHolder);
			}else {
				vHolder = (ViewHolder) convertView.getTag();
			}
			vHolder.textView.setText(mArrayList.get(mPageItemsIndex.get(position).intValue()));
			return convertView;
		}
	}

}

到这里就结束了,有什么疑问,欢迎评论。。。

下载地址:http://download.csdn.net/detail/qq_16064871/9445535

时间: 2024-10-15 21:22:25

android 打造变化多端的SeekBar(垂直和水平)的相关文章

Android学习笔记技巧之垂直和水平滚动视图

[java] view plain copy <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_conte

Android打造通用的下拉刷新组件

还记得上一篇 blog 的内容吗?如果不记得建议先去了解一下,Android 事件处理全面剖析 ,因为下拉刷新需要用到手势的处理,而上一篇文章中,对事件处理做了很详细的说明,了解了事件的处理机制,对理解本篇文章有很大的帮助.好了,这里就当大家都已经对事件处理有了一定的了解,开始我们的下拉刷新征程. 还是老规矩,先上效果图,再根据效果图来分析实现的原理: 一 .分析原理 我们都知道,listView 控件为我们提供了 addHeaderView.和 addFootView 的方法,我们通过此方法可

Android打造不一样的新手引导页面(一)

Android打造不一样的新手引导页面(一) 本系列主要分为两篇博客 打造不一样的新手引导页面(一) Android打造不一样的新手引导页面(二) 关于页面导航器的,可以查看我的这一篇博客仿网易新闻的顶部导航指示器 本篇博客主要讲解怎样自定义一个circleIndicator控件? 下一遍博客主要讲解怎样更改ViewPager切换的效果, 预计明天晚上之前更新. 效果图如下 1)首先我们先来看一下要怎样使用我们的circleIndicator控件 其实很简单,值需要两个步骤 1) 在xml布局文

【Android】一个activity中垂直排列两个listview

为了实现这种效果,一开始我想到的办法是ilistVew中加上一个footerview,footerview里面嵌套一个listview,但是实际操作之后发现footerview里的listview只显示一项,这个问题困扰了半天,一直没有找到合适的解决办法,直到昨天晚上偶然看到一篇博文介绍说,scrollview里嵌套listview也出现了同样的问题,解决办法是动态设置listview的高度,于是我用这种方法也试了试,结果还真解决了. MainActivity.java package com.

Android 学习心得 TextView 添加垂直滚动条

XMl文件中: 添加android:scrollbars="vertical" 添加android:maxLines="10"  //设置一页最多显示10行 activity文件中: textview = (TextView)findViewById(R.id.httpCLient_textView); textview.setMovementMethod(ScrollingMovementMethod.getInstance());完成!! ^_^!! Andro

海外最新的垂直市场水平化攻略。拿走,不谢!

编者注:本文来自国外著名的VC Josh Breinlinger的个人博客,中文版由天地会珠海分舵进行编译,发布当天同时上了36氪和虎嗅头条,希望csdn的朋友也会喜欢.文中作者对当今炙手可热但众说纷纭的垂直市场进行了非常深入的分析,别开生面的提出了垂直市场水平化的这一新颖的概念,以市场象限模型图的形式指引大家走出众说纷纭的迷雾,找到属于自己的盈利模式- 在创业圈子里,大家对描述"Craigslist分类现象"的那张盛传已久的图片应该并不陌生(编者注:该图片描述的就是,针对美国数一数二

Android基础控件SeekBar拖动条的使用

1.简介 SeekBar继承ProgressBar,相关属性和三种不同状态下的触发方法: <!--<SeekBar--> <!--android:layout_width="match_parent"--> <!--android:layout_height="wrap_content"--> <!--android:max="100"--> <!--android:progress=&

Android中如何实现多行、水平滚动的分页的Gridview?

功能要求: (1)比如每页显示2X2,总共2XN,每个item显示图片+文字(点击有链接). 如果单行水平滚动,可以用Horizontalscrollview实现. 如果是多行水平滚动,则结合Gridview(一般是垂直滚动的)和Horizontalscrollview实现. (2)水平滚动翻页,下面有显示当前页的icon. 1.      实现自定义的HorizontalScrollView(HorizontalScrollView.java): 因为要翻页时需要传当前页给调用者,所以flin

Android打造属于自己的数据库操作类。

1.概述 开发Android的同学都知道sdk已经为我们提供了一个SQLiteOpenHelper类来创建和管理SQLite数据库,通过写一个子类去继承它,就可以方便的创建.管理数据库.但是当我们需要去做增删改查的操作的时候,就得通过getWritableDatabase获取一个SQLiteDataBase然后老老实实去写操作值的put以及查询返回的Cursor处理,其实我们可以搞一个对象来帮我们干这些事情,打造属于你自己的数据库操作类. 2.操作类的初显形 假设现在我们什么都没有,我们要去搞一