自定义 弧形滑动条 CricleScrollView
来源:互联网 发布:ant for mac 下载 编辑:程序博客网 时间:2024/05/16 11:57
3.那么问题来了,如何去确认背景弧长,活动条弧长呢?其实估计大家都能想到drawArc方法可以通过传入起始角度和活动距离,分别来画出背景和滑动条的长度.
4.那么问题又来了,如何去让CricleScrollView滑动块的位置与listview 的上下拉同步了.刚开始我是想通过滑动总的弧度除以listViewitem的总数,然后通过ListView的滑动监听传入firstVisibleItem 来设置滑动块的起始角度 ,调用View的invalidate()的方法来重新绘制View.然而这种方法存在一个问题就是滑动块不能滑到滑动背景的底部,去掉背景效果会好点,但不美观,而且滑动块一格一格的跳,滑动效果太生硬了.产品经理一定会拍了我肩膀两下,说"小伙子还是老老实实给我弄个有背景又流畅的效果出来吧".
5.ListView本生不具备获取下拉滑动距离的方法,但可以从网上找到不少计算的方法.直接把滑动距离传进去就好了吗?答案当然不行.还需要计算每个弧度单位,类似上面的方法. 注意点:下拉获取的最大滑动距离并不是整个 item的高度 X item个数的距离 所以 每个弧度单位=滑动背景的总弧度应该 /(item X (item的总数-可见item的个数))[这个也只是与最大滑动距离接近而已],然后通过 每次的滑获取的距离 X 弧度单位 来确定 滑动块的起始角度,再通过invalidate()方法重新绘制来设定滑动块的位置.但这样也存在一个问题,因为 每个弧度单位 的获取不是通过 除以最大的滑动距离获得的,滑到底部时会存在要么滑动块超出范围,要么滑动块差一点才能滑到底部. 这时可以通过判断 当滑动距离>(item X (item的总数-可见item的个数)) 时,将滑动距离传入 ,重新计算 每个弧度单位,这样就可以 完美的避免了滑到底部的偏差.
6.滑动的问题是解决了,但往往特殊情况的解决才是重点, 例如item的总个数不满一屏时上面的方法是行不通的,当然通过不显示滑动条可以解决. 但当一屏的可见item是变化的例如总item=4, 可见item个数有3,4两种情况,这种判断条件.那么如何避免这种情况?我的方案是通过集合来收集可见item的情况来判断是否显示CricleScrollView, 条件如下
if(firstVisibleItem==0 && totalItemCount-1<visibleItemCount&&visibleItemNumber.size()==1),满足条件证明总item的个数 不满一屏,不显示CricleScrollView.
7.当写 5 的时候,获取ListView的子View时,在Activity的onCreate中获取是获取不到的,因为ListView获取子View需要在ListView 获取焦点后才能获得子View的, 所以需要将6 的步骤在 ListView 监听焦点变化的方法中初始化.
public class CircelScrollView extends ImageView {
private Context context;
private static Paint paintScroll=new Paint();
private static Paint paintBackgroud=new Paint();
private int mRadiu;//半径
private float mProgress;
private float mPreAngle;//每个item弧度
private float mRecfAngle;//弧长角度
private RectF mRect ;
private int mScrollState;
private int mScrollLength;
private int mScrollStroke;
private int maxListViewScrollY;
private int maxVisibleItemCount;
private boolean isScrollLast=false;
private ArrayList<Integer> visibleItemNumber;
public CircelScrollView(Context context) {
this(context, null);
}
public CircelScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
visibleItemNumber=new ArrayList<Integer>();
}
private void initPaint(int stroke) {
paintScroll.setAntiAlias(true);
paintScroll.setStyle(Paint.Style.STROKE);
paintScroll.setStrokeWidth(stroke);
paintScroll.setColor(0xffee7b1d);
paintBackgroud.setAntiAlias(true);
paintBackgroud.setStyle(Paint.Style.STROKE);
paintBackgroud.setStrokeWidth(stroke);
paintBackgroud.setColor(Color.GRAY);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureHeight(heightMeasureSpec));
}
/**
* 初始化弧长
* @param listViewHeightlistView下拉可达到的最大值
* @param recfAngle弧长角度
* @param radiu圆弧半径
* @param scrollLength 滑动条长度弧长对应的角度
*/
private void initCirculScroll(float listViewHeight,float recfAngle,int radiu,int scrollLength,int scrollStroke)
{
mRecfAngle=recfAngle;
if(listViewHeight<=0)
{
mPreAngle=recfAngle/180;
}
else
{
mPreAngle=recfAngle/listViewHeight;
}
mRadiu=radiu;
mScrollLength=scrollLength;
mScrollStroke=scrollStroke;
//初始化画笔
initPaint(scrollStroke);
invalidate();
}
/**
* 重新定义
* @param scrollY
*/
private void remusePreAngle(int scrollY)
{
mPreAngle=mRecfAngle/scrollY;
}
/**
* 初始化CircelScrollView
* @param lstView
* @param recfAngle 总弧长对应的角度
* @param radiu半径
* @param scrollLength 滑动条长度
* @param scrollStroke 滑动条粗细
*/
public void initCirculScroll(ListView lstView,float recfAngle,int radiu,int scrollLength,int scrollStroke)
{
int height=0;
int count = lstView.getCount();
View childAt = lstView.getChildAt(0);
if(childAt!=null)
{
height=childAt.getHeight();
}
if(!isScrollLast)
{
maxListViewScrollY=(count-maxVisibleItemCount)*height;
}
initCirculScroll(maxListViewScrollY,recfAngle,radiu
,scrollLength,scrollStroke);
}
/**
* 设置 实时滑动距离
* @param progress
* @param scrollState
*/
private void setScrollDistance(float progress,int scrollState)
{
this.mProgress=progress;
mScrollState=scrollState;
invalidate();
}
/**
* 设置 scroll滑动 位置,
* @param view
* @param firstVisibleItem
* @param visibleItemCount
* @param totalItemCount
*/
public void setScrollDistance(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if(maxVisibleItemCount<visibleItemCount )
{
maxVisibleItemCount=visibleItemCount;
visibleItemNumber.add(visibleItemCount);
}
if(totalItemCount==0 )
{
setScrollDistance(0, 0);
return;
}
if(firstVisibleItem==0 && totalItemCount-1<visibleItemCount&&visibleItemNumber.size()==1)
{
setScrollDistance(0, 0);
return;
}
View c = ((ListView)view).getChildAt(0);
int firstVisiblePosition = view.getFirstVisiblePosition();
int top = c.getTop();
int headerHeight=0;
if (firstVisiblePosition >= 1) {
headerHeight = view.getHeight();
}
int scrollY = -top + firstVisibleItem * c.getHeight();
if(scrollY>maxListViewScrollY&&firstVisibleItem!=0)
{
remusePreAngle(scrollY);
}
setScrollDistance(scrollY, 1);
}
@Override
protected void onDraw(Canvas canvas) {
//绘制圆弧
canvas.drawColor(Color.TRANSPARENT);
if(mRect==null)
{
mRect = new RectF(getWidth()/2 - mRadiu-mScrollStroke/2, getWidth()/2 - mRadiu-mScrollStroke/2, getWidth()/2
+ mRadiu-mScrollStroke/2, getWidth()/2 + mRadiu-mScrollStroke/2);
}
if(mScrollState==1)
{
canvas.drawArc(mRect,-mRecfAngle/2-mScrollLength/2, mRecfAngle+mScrollLength, false, paintBackgroud);
canvas.drawArc(mRect, mProgress*mPreAngle-mRecfAngle/2-mScrollLength/2, mScrollLength, false, paintScroll);
// canvas.drawArc(mRect, mProgress*mPreAngle-mRecfAngle/2, mProgress==0?(mProgress*mPreAngle)+30-mRecfAngle/2:(mProgress*mPreAngle)/(mPreAngle)+30-mRecfAngle/2, false, paint);
}
super.onDraw(canvas);
}
private int measureWidth(int widthMeasureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(widthMeasureSpec);
int specSize = MeasureSpec.getSize(widthMeasureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = Utils.dip2px(context, 120);
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
private int measureHeight(int measuredHeight) {
int result = 0;
int specMode = MeasureSpec.getMode(measuredHeight);
int specSize = MeasureSpec.getSize(measuredHeight);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = Utils.dip2px(context, 120);
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
}
- 自定义 弧形滑动条 CricleScrollView
- 自定义进度弧形条
- 自定义 LayoutManager 实现弧形以及滑动放大效果 RecyclerView
- 自定义 LayoutManager 实现弧形以及滑动放大效果 RecyclerView
- unity 圆形滑动条slider 弧形滑动条效果及代码分析
- ViewPager自定义滑动条
- Android自定义SeekBar滑动条
- 自定义qml滑动条Slider
- android 弧形自定义view
- 自定义弧形进度条
- ugui制作弧形血条
- unity3d制作弧形血条,魔条
- Android中自定义滑动条风格
- cocos2dx自定义的滑动滚条
- iOS自定义范围滑动条控件
- angularjs自定义折线图+滑动条指令
- 自定义Android渐变式圆环滑动条
- Anroid自定义可滑动的音量条
- 9.16选择器,文本属性
- Insert into ..... on duplicate key update ...与Replace into的区别
- android SDK 安装目录结构详解及各工具
- 9.17表格,背景,文本与图片位置关系
- 【软考总结】——再学操作系统
- 自定义 弧形滑动条 CricleScrollView
- JS调试
- Bitcode 一种中间代码 Xcode7 && ios9
- POJ-2006
- c++学习(2)
- Android:LayoutParameter不匹配问题
- 黑马程序员-java基础-网络编程
- 如何提高Linux系统安全性的十大招数
- 第三周项目2--建设”顺序表“算法库