怎样让它固定显示选中一条啊?
这个 SrollerNumberPicker.java 是从网上找的 控件类 ,代码可能有点多,我贴到下面,希望大神能帮忙看看。。。
自己解决掉了,原因是onMesure里根据父控件获取宽高,高度这样设置就不会再有这个问题: itemNumber * unitHeight
public class ScrollerNumberPicker extends View
{
/** 控件宽度 */
private float controlWidth;
/** 控件高度 */
private float controlHeight;
/** 是否滑动�? */
private boolean isScrolling = false;
/** 选择的内�? */
private ArrayList<ItemObject> itemList = new ArrayList<ScrollerNumberPicker.ItemObject>();
/** 设置数据 */
private ArrayList<String> dataList = new ArrayList<String>();
/** 按下的坐�? */
private int downY;
/** 按下的时�? */
private long downTime = 0;
/** 短促移动 */
private long goonTime = 200;
/** 短促移动距离 */
private int goonDistence = 100;
/** 画线画笔 */
private Paint linePaint;
/** 线的默认颜色 */
private int lineColor = 0xff000000;
/** 默认字体 */
private float normalFont = 14.0f;
/** 选中的时候字�? */
private float selectedFont = 22.0f;
/** 单元格高�? */
private int unitHeight = 50;
/** 单元格宽�? */
private int unitWidgh = 50;
/** 显示多少个内�? */
private int itemNumber = 5;
/** 默认字体颜色 */
private int normalColor = 0xff000000;
/** 选中时�?�的字体颜色 */
private int selectedColor = 0xffff0000;
/** 蒙板高度 */
private float maskHight = 48.0f;
/** 选择监听 */
private OnSelectListener onSelectListener;
/** 是否可用 */
private boolean isEnable = true;
/** 刷新界面 */
private static final int REFRESH_VIEW = 0x001;
/** 移动距离 */
private static final int MOVE_NUMBER = 5;
/** 是否允许选空 */
private boolean noEmpty = false;
/** 正在修改数据,避免ConcurrentModificationException异常 */
private boolean isClearing = false;
public ScrollerNumberPicker(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init(context, attrs);
initData();
}
public ScrollerNumberPicker(Context context, AttributeSet attrs)
{
super(context, attrs);
init(context, attrs);
initData();
}
public ScrollerNumberPicker(Context context)
{
super(context);
initData();
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event)
{
if (!isEnable) return true;
int y = (int) event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
isScrolling = true;
downY = (int) event.getY();
downTime = System.currentTimeMillis();
break;
case MotionEvent.ACTION_MOVE:
actionMove(y - downY);
onSelectListener();
break;
case MotionEvent.ACTION_UP:
// 移动距离的绝对�??
int move = (y - downY);
move = move > 0 ? move : move * (-1);
// 判断段时间移动的距离
if (System.currentTimeMillis() - downTime < goonTime && move > goonDistence)
{
goonMove(y - downY);
}
else
{
actionUp(y - downY);
}
noEmpty();
isScrolling = false;
break;
default:
break;
}
return true;
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
drawLine(canvas);
drawList(canvas);
drawMask(canvas);
}
private synchronized void drawList(Canvas canvas)
{
if (isClearing) return;
try
{
for (ItemObject itemObject : itemList)
{
itemObject.drawSelf(canvas);
}
}
catch (Exception e)
{
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
controlWidth = measureWidth(widthMeasureSpec);
if (controlWidth != 0)
{
controlHeight = measureHeight(heightMeasureSpec);
setMeasuredDimension((int) controlWidth, (int) controlHeight);
}
}
/** 获取控件宽度 */
private int measureWidth(int measureSpec)
{
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
int result = 500;
if (specMode == MeasureSpec.AT_MOST)
{
result = specSize;
}
else if (specMode == MeasureSpec.EXACTLY)
{
result = specSize;
}
return result;
}
/** 获取控件高度 */
private int measureHeight(int measureSpec)
{
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
int result = 500;
if (specMode == MeasureSpec.AT_MOST)
{
result = specSize;
}
else if (specMode == MeasureSpec.EXACTLY)
{
result = specSize;
}
return result;
}
/**
* 继续移动�?定距�?
*/
private synchronized void goonMove(final int move)
{
new Thread(new Runnable()
{
@Override
public void run()
{
int distence = 0;
while (distence < unitHeight * MOVE_NUMBER)
{
try
{
Thread.sleep(5);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
actionThreadMove(move > 0 ? distence : distence * (-1));
distence += 10;
}
actionUp(move > 0 ? distence - 10 : distence * (-1) + 10);
noEmpty();
}
}).start();
}
/**
* 不能为空,必须有选项
*/
private void noEmpty()
{
if (!noEmpty) return;
for (ItemObject item : itemList)
{
if (item.isSelected()) return;
}
int move = (int) itemList.get(0).moveToSelected();
if (move < 0)
{
defaultMove(move);
}
else
{
defaultMove((int) itemList.get(itemList.size() - 1).moveToSelected());
}
for (ItemObject item : itemList)
{
if (item.isSelected())
{
if (onSelectListener != null) onSelectListener.endSelect(item.id, item.itemText);
break;
}
}
}
// /**
// * 初始化数组数据
// */
// private void initData()
// {
// isClearing = true;
// itemList.clear();
// for (int i = 0; i < dataList.size(); i++)
// {
// ItemObject itmItemObject = new ItemObject();
// itmItemObject.id = i;
// itmItemObject.itemText = dataList.get(i);
// itmItemObject.x = 0;
// itmItemObject.y = i * unitHeight;
// itemList.add(itmItemObject);
// }
// isClearing = false;
// }
/**
* 初始化数组数据
*/
private void initData()
{
isClearing = true;
itemList.clear();
int Size = dataList.size(); // 假设24
if (Size != 0)
{
for (int i = Size * -10; i < 0; i++)
{
ItemObject itmItemObject = new ItemObject();
itmItemObject.id = i;
itmItemObject.itemText = dataList.get(i % Size == 0 ? 0 : Size + i % Size); // TODO 从0位置上下各添加10组
itmItemObject.x = 0;
itmItemObject.y = i * unitHeight;
itemList.add(itmItemObject);
}
for (int i = 0; i < Size * 10; i++)
{
ItemObject itmItemObject = new ItemObject();
itmItemObject.id = i;
itmItemObject.itemText = dataList.get(i % Size);
itmItemObject.x = 0;
itmItemObject.y = i * unitHeight;
itemList.add(itmItemObject);
}
}
isClearing = false;
}
/**
* 移动的时�?
*
* @param move
*/
private void actionMove(int move)
{
for (ItemObject item : itemList)
{
item.move(move);
}
invalidate();
}
/**
* 移动,线程中调用
*
* @param move
*/
private void actionThreadMove(int move)
{
for (ItemObject item : itemList)
{
item.move(move);
}
Message rMessage = new Message();
rMessage.what = REFRESH_VIEW;
handler.sendMessage(rMessage);
}
/**
* 松开的时�?
*
* @param move
*/
private void actionUp(int move)
{
int newMove = 0;
if (move > 0)
{
for (int i = 0; i < itemList.size(); i++)
{
if (itemList.get(i).isSelected())
{
newMove = (int) itemList.get(i).moveToSelected();
if (onSelectListener != null) onSelectListener.endSelect(itemList.get(i).id, itemList.get(i).itemText);
break;
}
}
}
else
{
for (int i = itemList.size() - 1; i >= 0; i--)
{
if (itemList.get(i).isSelected())
{
newMove = (int) itemList.get(i).moveToSelected();
if (onSelectListener != null) onSelectListener.endSelect(itemList.get(i).id, itemList.get(i).itemText);
break;
}
}
}
for (ItemObject item : itemList)
{
item.newY(move + 0);
}
slowMove(newMove);
Message rMessage = new Message();
rMessage.what = REFRESH_VIEW;
handler.sendMessage(rMessage);
}
/**
* 缓慢移动
*
* @param move
*/
private synchronized void slowMove(final int move)
{
new Thread(new Runnable()
{
@Override
public void run()
{
// 判断政府
int m = move > 0 ? move : move * (-1);
int i = move > 0 ? 1 : (-1);
// 移动速度
int speed = 1;
while (true)
{
m = m - speed;
if (m <= 0)
{
for (ItemObject item : itemList)
{
item.newY(m * i);
}
Message rMessage = new Message();
rMessage.what = REFRESH_VIEW;
handler.sendMessage(rMessage);
try
{
Thread.sleep(2);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
break;
}
for (ItemObject item : itemList)
{
item.newY(speed * i);
}
Message rMessage = new Message();
rMessage.what = REFRESH_VIEW;
handler.sendMessage(rMessage);
try
{
Thread.sleep(2);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for (ItemObject item : itemList)
{
if (item.isSelected())
{
if (onSelectListener != null) onSelectListener.endSelect(item.id, item.itemText);
break;
}
}
}
}).start();
}
/**
* 移动到默认位�?
*
* @param move
*/
private void defaultMove(int move)
{
for (ItemObject item : itemList)
{
item.newY(move);
}
Message rMessage = new Message();
rMessage.what = REFRESH_VIEW;
handler.sendMessage(rMessage);
}
/**
* 滑动监听
*/
private void onSelectListener()
{
if (onSelectListener == null) return;
for (ItemObject item : itemList)
{
if (item.isSelected())
{
onSelectListener.selecting(item.id, item.itemText);
}
}
}
/**
* 绘制线条
*
* @param canvas
*/
private void drawLine(Canvas canvas)
{
if (linePaint == null)
{
linePaint = new Paint();
linePaint.setColor(lineColor);
linePaint.setAntiAlias(true);
linePaint.setStrokeWidth(0.5f);
}
canvas.drawLine(0, controlHeight / 2 - unitHeight / 2 + 2, controlWidth, controlHeight / 2 - unitHeight / 2 + 2, linePaint);
canvas.drawLine(0, controlHeight / 2 + unitHeight / 2 - 2, controlWidth, controlHeight / 2 + unitHeight / 2 - 2, linePaint);
}
/**
* 绘制遮盖�?
*
* @param canvas
*/
private void drawMask(Canvas canvas)
{
LinearGradient lg = new LinearGradient(0, 0, 0, maskHight, 0x00f2f2f2, 0x00f2f2f2, TileMode.MIRROR);
Paint paint = new Paint();
paint.setShader(lg);
canvas.drawRect(0, 0, controlWidth, maskHight, paint);
LinearGradient lg2 = new LinearGradient(0, controlHeight - maskHight, 0, controlHeight, 0x00f2f2f2, 0x00f2f2f2, TileMode.MIRROR);
Paint paint2 = new Paint();
paint2.setShader(lg2);
canvas.drawRect(0, controlHeight - maskHight, controlWidth, controlHeight, paint2);
}
/**
* 初始化,获取设置的属�?
*
* @param context
* @param attrs
*/
private void init(Context context, AttributeSet attrs)
{
TypedArray attribute = context.obtainStyledAttributes(attrs, R.styleable.SuNumberPicker);
unitHeight = (int) attribute.getDimension(R.styleable.SuNumberPicker_unitHight, 32);
unitWidgh = (int) attribute.getDimension(R.styleable.SuNumberPicker_unitWidgh, 50);
normalFont = attribute.getDimension(R.styleable.SuNumberPicker_normalTextSize, 14.0f);
selectedFont = attribute.getDimension(R.styleable.SuNumberPicker_selecredTextSize, 22.0f);
itemNumber = attribute.getInt(R.styleable.SuNumberPicker_itemNumber, 7);
normalColor = attribute.getColor(R.styleable.SuNumberPicker_normalTextColor, 0xff000000);
selectedColor = attribute.getColor(R.styleable.SuNumberPicker_selecredTextColor, 0xffff0000);
lineColor = attribute.getColor(R.styleable.SuNumberPicker_lineColor, 0xff000000);
maskHight = attribute.getDimension(R.styleable.SuNumberPicker_maskHight, 48.0f);
noEmpty = attribute.getBoolean(R.styleable.SuNumberPicker_noEmpty, false);
isEnable = attribute.getBoolean(R.styleable.SuNumberPicker_isEnable, true);
attribute.recycle();
controlHeight = itemNumber * unitHeight;
controlWidth = unitWidgh;
}
/**
* 设置数据
*
* @param data
*/
public void setData(ArrayList<String> data)
{
this.dataList = data;
initData();
}
/**
* 获取返回�?
*
* @return
*/
public int getSelected()
{
for (ItemObject item : itemList)
{
if (item.isSelected()) return item.id;
}
return -1;
}
/**
* 获取返回的内�?
*
* @return
*/
public String getSelectedText()
{
for (ItemObject item : itemList)
{
if (item.isSelected()) return item.itemText;
}
return "";
}
/**
* 是否正在滑动
*
* @return
*/
public boolean isScrolling()
{
return isScrolling;
}
/**
* 是否可用
*
* @return
*/
public boolean isEnable()
{
return isEnable;
}
/**
* 设置是否可用
*
* @param isEnable
*/
public void setEnable(boolean isEnable)
{
this.isEnable = isEnable;
}
/**
* 设置默认选项
*
* @param index
*/
public void setDefault(int index, int trim)
{
float move = itemList.get(index + dataList.size() * 10).moveToSelected(); // TODO +*10是为了移动到中间0的位置
defaultMove((int) move + trim);
}
/**
* 获取列表大小
*
* @return
*/
public int getListSize()
{
if (itemList == null) return 0;
return itemList.size();
}
/**
* 获取某项的内�?
*
* @param index
* @return
*/
public String getItemText(int index)
{
if (itemList == null) return "";
return itemList.get(index).itemText;
}
/**
* 监听
*
* @param onSelectListener
*/
public void setOnSelectListener(OnSelectListener onSelectListener)
{
this.onSelectListener = onSelectListener;
}
@SuppressLint("HandlerLeak")
Handler handler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
switch (msg.what)
{
case REFRESH_VIEW:
invalidate();
break;
default:
break;
}
}
};
/**
* 单条内容
*
* @author suzhenpeng
*/
private class ItemObject
{
/** id */
public int id = 0;
/** 内容 */
public String itemText = "";
/** x坐标 */
public int x = 0;
/** y坐标 */
public int y = 0;
/** 移动距离 */
public int move = 0;
/** 字体画笔 */
private Paint textPaint;
/** 字体范围矩形 */
private Rect textRect;
public ItemObject()
{
super();
}
/**
* 绘制自身
*
* @param canvas
*/
public void drawSelf(Canvas canvas)
{
if (textPaint == null)
{
textPaint = new Paint();
textPaint.setAntiAlias(true);
}
if (textRect == null) textRect = new Rect();
// 获取距离标准位置的距�?
float moveToSelect = moveToSelected();
moveToSelect = moveToSelect > 0 ? moveToSelect : moveToSelect * (-1);
// 判断是否被�?�择
if (isSelected())
{
textPaint.setColor(selectedColor);
// 计算当前字体大小
float textSize = (float) normalFont + ((float) (selectedFont - normalFont) * (1.0f - (float) moveToSelect / (float) unitHeight));
textPaint.setTextSize(textSize);
}
else
{
textPaint.setColor(normalColor);
textPaint.setTextSize(normalFont);
}
// 返回包围整个字符串的�?小的�?个Rect区域
textPaint.getTextBounds(itemText, 0, itemText.length(), textRect);
// 判断是否可视
if (!isInView()) return;
// 绘制内容
canvas.drawText(itemText, x + controlWidth / 2 - textRect.width() / 2, y + move + unitHeight / 2 + textRect.height() / 2, textPaint);
}
/**
* 是否在可视界面内
*
* @param rect
* @return
*/
public boolean isInView()
{
if (y + move > controlHeight || (y + move + unitHeight / 2 + textRect.height() / 2) < 0) return false;
return true;
}
/**
* 移动距离
*
* @param _move
*/
public void move(int _move)
{
this.move = _move;
}
/**
* 设置新的坐标
*
* @param move
*/
public void newY(int _move)
{
this.move = 0;
this.y = y + _move;
}
/**
* 判断是否在�?�择区域�?
*
* @return
*/
public boolean isSelected()
{
if ((y + move) >= controlHeight / 2 - unitHeight / 2 + 5 && (y + move) <= controlHeight / 2 + unitHeight / 2 - 5) return true;
if ((y + move + unitHeight) >= controlHeight / 2 - unitHeight / 2 + 5 && (y + move + unitHeight) <= controlHeight / 2 + unitHeight / 2 - 5) return true;
if ((y + move) <= controlHeight / 2 - unitHeight / 2 + 5 && (y + move + unitHeight) >= controlHeight / 2 + unitHeight / 2 - 5) return true;
return false;
}
/**
* 获取移动到标准位置需要的距离
*/
public float moveToSelected()
{
return (controlHeight / 2 - unitHeight / 2) - (y + move);
}
}
/**
* 选择监听监听
*
* @author suzhenpeng
*
*/
public interface OnSelectListener
{
/**
* 结束选择
*
* @param id
* @param text
*/
public void endSelect(int id, String text);
/**
* 选中的内�?
*
* @param id
* @param text
*/
public void selecting(int id, String text);
}
}