Skip to content

Commit 7de6832

Browse files
committed
v2.0.2
- 修复不循环模式下点击空白item处出现数组越界问题 - 修复循环模式下只有一条数据的时候只显示三条而不是填充满高度问题
1 parent dd498f8 commit 7de6832

7 files changed

Lines changed: 86 additions & 36 deletions

File tree

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ PickerView (2.x系列)
99

1010
####使用gradle 依赖:
1111
```java
12-
compile 'com.bigkoo:pickerview:2.0.1'
12+
compile 'com.bigkoo:pickerview:2.0.2’
1313
```
1414
1515
## Demo 图片
@@ -29,6 +29,10 @@ PickerView (2.x系列)
2929
- 去掉popupWindow,改用View,类名也对应修改为TimePickerView和 OptionsPickerView <br />
3030
- 加入遮罩效果 <br />
3131
32+
>v2.0.2
33+
- 修复不循环模式下点击空白item处出现数组越界问题 <br />
34+
- 修复循环模式下只有一条数据的时候只显示三条而不是填充满高度问题 <br />
35+
3236
3337
3438

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ android {
2222
dependencies {
2323
compile fileTree(dir: 'libs', include: ['*.jar'])
2424
compile project(':pickerview')
25-
// compile 'com.bigkoo:pickerview:2.0.1'
25+
// compile 'com.bigkoo:pickerview:2.0.2'
2626
compile 'com.android.support:appcompat-v7:23.1.0'
2727
}

app/src/main/java/com/bigkoo/pickerviewdemo/MainActivity.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ public void onClick(View v) {
5959
//选项1
6060
options1Items.add(new ProvinceBean(0,"广东","广东省,以岭南东道、广南东路得名","其他数据"));
6161
options1Items.add(new ProvinceBean(1,"湖南","湖南省地处中国中部、长江中游,因大部分区域处于洞庭湖以南而得名湖南","芒果TV"));
62+
options1Items.add(new ProvinceBean(3,"广西","嗯~~",""));
6263

6364
//选项2
6465
ArrayList<String> options2Items_01=new ArrayList<String>();
@@ -70,12 +71,16 @@ public void onClick(View v) {
7071
ArrayList<String> options2Items_02=new ArrayList<String>();
7172
options2Items_02.add("长沙");
7273
options2Items_02.add("岳阳");
74+
ArrayList<String> options2Items_03=new ArrayList<String>();
75+
options2Items_03.add("桂林");
7376
options2Items.add(options2Items_01);
7477
options2Items.add(options2Items_02);
78+
options2Items.add(options2Items_03);
7579

7680
//选项3
7781
ArrayList<ArrayList<String>> options3Items_01 = new ArrayList<ArrayList<String>>();
7882
ArrayList<ArrayList<String>> options3Items_02 = new ArrayList<ArrayList<String>>();
83+
ArrayList<ArrayList<String>> options3Items_03 = new ArrayList<ArrayList<String>>();
7984
ArrayList<String> options3Items_01_01=new ArrayList<String>();
8085
options3Items_01_01.add("白云");
8186
options3Items_01_01.add("天河");
@@ -125,9 +130,13 @@ public void onClick(View v) {
125130
options3Items_02_02.add("岳8");
126131
options3Items_02_02.add("岳9");
127132
options3Items_02.add(options3Items_02_02);
133+
ArrayList<String> options3Items_03_01=new ArrayList<String>();
134+
options3Items_03_01.add("好山水");
135+
options3Items_03.add(options3Items_03_01);
128136

129137
options3Items.add(options3Items_01);
130138
options3Items.add(options3Items_02);
139+
options3Items.add(options3Items_03);
131140

132141
//三级联动效果
133142
pvOptions.setPicker(options1Items, options2Items, options3Items, true);

app/src/main/java/com/bigkoo/pickerviewdemo/bean/ProvinceBean.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public void setOthers(String others) {
5050

5151
//这个用来显示在PickerView上面的字符串,PickerView会通过反射获取getPickerViewText方法显示出来。
5252
public String getPickerViewText() {
53+
//这里还可以判断文字超长截断再提供显示
5354
return name;
5455
}
5556
}

pickerview/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
22
apply plugin: 'com.github.dcendents.android-maven'
33
apply plugin: 'com.jfrog.bintray'
44

5-
version = "2.0.1"
5+
version = "2.0.2"
66

77
android {
88
compileSdkVersion 21

pickerview/src/main/java/com/bigkoo/pickerview/lib/SmoothScrollTimerTask.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ public final void run() {
3131
}
3232
}
3333
if (Math.abs(realTotalOffset) <= 0) {
34+
35+
//这里如果不是循环模式,则点击空白位置需要回滚,不然就会出现选到-1 item的 情况
36+
if (!loopView.isLoop) {
37+
float itemHeight = loopView.lineSpacingMultiplier * loopView.maxTextHeight;
38+
if (loopView.totalScrollY <= (int) ((float) (-loopView.initPosition) * itemHeight)) {
39+
loopView.totalScrollY = (int) ((float) (-loopView.initPosition) * itemHeight);
40+
loopView.handler.sendEmptyMessage(MessageHandler.WHAT_INVALIDATE_LOOP_VIEW);
41+
} else if (loopView.totalScrollY >= (int) ((float) (loopView.getItemsCount() - 1 - loopView.initPosition) * itemHeight)) {
42+
loopView.totalScrollY = (int) ((float) (loopView.getItemsCount() - 1 - loopView.initPosition) * itemHeight);
43+
loopView.handler.sendEmptyMessage(MessageHandler.WHAT_INVALIDATE_LOOP_VIEW);
44+
}
45+
}
46+
3447
loopView.cancelFuture();
3548
loopView.handler.sendEmptyMessage(MessageHandler.WHAT_ITEM_SELECTED);
3649
} else {

pickerview/src/main/java/com/bigkoo/pickerview/lib/WheelView.java

Lines changed: 56 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import java.util.concurrent.TimeUnit;
2626

2727
/**
28-
* 3d滚轮控件
28+
* 3d滚轮控件,
2929
*/
3030
public class WheelView extends View {
3131

@@ -168,13 +168,19 @@ private void remeasure() {
168168

169169
measureTextWidthHeight();
170170

171+
//最大Text的高度乘间距倍数得到 可见文字实际的总高度,半圆的周长
171172
halfCircumference = (int) (maxTextHeight * lineSpacingMultiplier * (itemsVisible - 1)) ;
173+
//整个圆的周长除以PI得到直径,这个直径用作控件的总高度
172174
measuredHeight = (int) ((halfCircumference * 2) / Math.PI);
175+
//求出半径
173176
radius = (int) (halfCircumference / Math.PI);
177+
//控件宽度,这里支持weight
174178
measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
179+
//计算两条横线和控件中间点的Y位置
175180
firstLineY = (int) ((measuredHeight - lineSpacingMultiplier * maxTextHeight) / 2.0F);
176181
secondLineY = (int) ((measuredHeight + lineSpacingMultiplier * maxTextHeight) / 2.0F);
177182
centerY = (int) ((measuredHeight + maxTextHeight) / 2.0F - CENTERCONTENTOFFSET);
183+
//初始化显示的item的position,根据是否loop
178184
if (initPosition == -1) {
179185
if (isLoop) {
180186
initPosition = (adapter.getItemsCount() + 1) / 2;
@@ -186,6 +192,9 @@ private void remeasure() {
186192
preCurrentIndex = initPosition;
187193
}
188194

195+
/**
196+
* 计算最大len的Text的宽高度
197+
*/
189198
private void measureTextWidthHeight() {
190199
Rect rect = new Rect();
191200
for (int i = 0; i < adapter.getItemsCount(); i++) {
@@ -280,78 +289,92 @@ protected void onDraw(Canvas canvas) {
280289
return;
281290
}
282291

283-
Object as[] = new Object[itemsVisible];
292+
//可见的item数组
293+
Object visibles[] = new Object[itemsVisible];
294+
//更加滚动的Y值高度除去每行Item的高度,得到滚动了多少个item,即change数
284295
change = (int) (totalScrollY / (lineSpacingMultiplier * maxTextHeight));
285296
try {
297+
//滚动中实际的预选中的item(即经过了中间位置的item) = 滑动前的位置 + 滑动相对位置
286298
preCurrentIndex = initPosition + change % adapter.getItemsCount();
287299
}catch (ArithmeticException e){
288300
System.out.println("出错了!adapter.getItemsCount() == 0,联动数据不匹配");
289301
}
290-
if (!isLoop) {
302+
if (!isLoop) {//不循环的情况
291303
if (preCurrentIndex < 0) {
292304
preCurrentIndex = 0;
293305
}
294306
if (preCurrentIndex > adapter.getItemsCount() - 1) {
295307
preCurrentIndex = adapter.getItemsCount() - 1;
296308
}
297-
} else {
298-
if (preCurrentIndex < 0) {
309+
} else {//循环
310+
if (preCurrentIndex < 0) {//举个例子:如果总数是5,preCurrentIndex = -1,那么preCurrentIndex按循环来说,其实是0的上面,也就是4的位置
299311
preCurrentIndex = adapter.getItemsCount() + preCurrentIndex;
300312
}
301-
if (preCurrentIndex > adapter.getItemsCount() - 1) {
313+
if (preCurrentIndex > adapter.getItemsCount() - 1) {//同理上面,自己脑补一下
302314
preCurrentIndex = preCurrentIndex - adapter.getItemsCount();
303315
}
304316
}
305317

306-
//change的另外一个变量,跟滚动流畅度有关
307-
int j2 = (int) (totalScrollY % (lineSpacingMultiplier * maxTextHeight));
308-
// 设置as数组中每个元素的值
309-
int k1 = 0;
310-
while (k1 < itemsVisible) {
311-
int l1 = preCurrentIndex - (itemsVisible / 2 - k1);
318+
//跟滚动流畅度有关,总滑动距离与每个item高度取余,即并不是一格格的滚动,每个item不一定滚到对应Rect里的,这个item对应格子的偏移值
319+
int itemHeightOffset = (int) (totalScrollY % (lineSpacingMultiplier * maxTextHeight));
320+
// 设置数组中每个元素的值
321+
int counter = 0;
322+
while (counter < itemsVisible) {
323+
int index = preCurrentIndex - (itemsVisible / 2 - counter);//索引值,即当前在控件中间的item看作数据源的中间,计算出相对源数据源的index值
324+
//判断是否循环,如果是循环数据源也使用相对循环的position获取对应的item值,如果不是循环则超出数据源范围使用""空白字符串填充,在界面上形成空白无数据的item项
312325
if (isLoop) {
313-
if (l1 < 0) {
314-
l1 = l1 + adapter.getItemsCount();
326+
if (index < 0) {
327+
index = index + adapter.getItemsCount();
328+
if(index < 0){
329+
index = 0;
330+
}
315331
}
316-
if (l1 > adapter.getItemsCount() - 1) {
317-
l1 = l1 - adapter.getItemsCount();
332+
if (index > adapter.getItemsCount() - 1) {
333+
index = index - adapter.getItemsCount();
334+
if (index > adapter.getItemsCount() - 1){
335+
index = adapter.getItemsCount() - 1;
336+
}
318337
}
319-
as[k1] = adapter.getItem(l1);
320-
} else if (l1 < 0) {
321-
as[k1] = "";
322-
} else if (l1 > adapter.getItemsCount() - 1) {
323-
as[k1] = "";
338+
visibles[counter] = adapter.getItem(index);
339+
} else if (index < 0) {
340+
visibles[counter] = "";
341+
} else if (index > adapter.getItemsCount() - 1) {
342+
visibles[counter] = "";
324343
} else {
325-
as[k1] = adapter.getItem(l1);
344+
visibles[counter] = adapter.getItem(index);
326345
}
327-
k1++;
346+
counter++;
347+
328348
}
349+
350+
//中间两条横线
329351
canvas.drawLine(0.0F, firstLineY, measuredWidth, firstLineY, paintIndicator);
330352
canvas.drawLine(0.0F, secondLineY, measuredWidth, secondLineY, paintIndicator);
353+
//单位的Label
331354
if(label != null) {
332355
int drawRightContentStart = measuredWidth - getTextWidth(paintCenterText,label);
333356
//靠右并留出空隙
334357
canvas.drawText(label, drawRightContentStart - CENTERCONTENTOFFSET, centerY, paintCenterText);
335358
}
336-
int j1 = 0;
337-
while (j1 < itemsVisible) {
359+
counter = 0;
360+
while (counter < itemsVisible) {
338361
canvas.save();
339362
// L(弧长)=α(弧度)* r(半径) (弧度制)
340363
// 求弧度--> (L * π ) / (π * r) (弧长X派/半圆周长)
341364
float itemHeight = maxTextHeight * lineSpacingMultiplier;
342-
double radian = ((itemHeight * j1 - j2) * Math.PI) / halfCircumference;
365+
double radian = ((itemHeight * counter - itemHeightOffset) * Math.PI) / halfCircumference;
343366
// 弧度转换成角度(把半圆以Y轴为轴心向右转90度,使其处于第一象限及第四象限
344367
float angle = (float) (90D - (radian / Math.PI) * 180D);
345368
if (angle >= 90F || angle <= -90F) {
346369
canvas.restore();
347370
} else {
348-
String contentText = getContentText(as[j1]);
371+
String contentText = getContentText(visibles[counter]);
349372

350373
//计算开始绘制的位置
351374
measuredCenterContentStart(contentText);
352375
measuredOutContentStart(contentText);
353376
int translateY = (int) (radius - Math.cos(radian) * radius - (Math.sin(radian) * maxTextHeight) / 2D);
354-
//根据Math.sin(radian)来更改文字高度拉长和缩放,形成弧形3d视觉差
377+
//根据Math.sin(radian)来更改canvas坐标系原点,然后缩放画布,使得文字高度进行缩放,形成弧形3d视觉差
355378
canvas.translate(0.0F, translateY);
356379
canvas.scale(1.0F, (float) Math.sin(radian));
357380
if (translateY <= firstLineY && maxTextHeight + translateY >= firstLineY) {
@@ -382,10 +405,10 @@ protected void onDraw(Canvas canvas) {
382405
// 中间条目
383406
canvas.clipRect(0, 0, measuredWidth, (int) (itemHeight));
384407
canvas.drawText(contentText, drawCenterContentStart, maxTextHeight - CENTERCONTENTOFFSET, paintCenterText);
385-
//根据滚动多少个item和初始显示的item位置,计算出中间的item是第几个
386-
int middleCount = (int) Math.round((change + initPosition) % (adapter.getItemsCount() * 1.0));
387-
selectedItem = middleCount >= 0 ? middleCount : adapter.getItemsCount() + middleCount;
388-
selectedItem = adapter.indexOf(as[j1]);
408+
int preSelectedItem = adapter.indexOf(visibles[counter]);
409+
if(preSelectedItem != -1){
410+
selectedItem = preSelectedItem;
411+
}
389412
} else {
390413
// 其他条目
391414
canvas.save();
@@ -396,7 +419,7 @@ protected void onDraw(Canvas canvas) {
396419
}
397420
canvas.restore();
398421
}
399-
j1++;
422+
counter++;
400423
}
401424
}
402425

0 commit comments

Comments
 (0)