安卓实现自定义滚动选择器
转载请标明出处:http://blog.****.net/u011546655/article/details/45921025
(3)主界面
背景:其实我们都知道,在我们做开发的过程中,会遇到Android 自身所带控件不够的情况,那么这个时候,就需要我们自定义控件,所以,也就造成了,在开发的过程中,我们一定要掌握好自定义控件,不然,当你去一家公司,产品萌妹子过来找你,这个效果很不错,问你能不能实现的时候,你难道能有理由说不行么,男人嘛,哪里能说不行了,直接用浑厚的声音告诉她,行,怎么不行,直接KO她。
一:多的不说,效果图,先走起
二:实例源码
(1)自定义控件
- package com.pickerscrollview.views;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Timer;
- import java.util.TimerTask;
- import android.annotation.SuppressLint;
- import android.content.Context;
- import android.graphics.Canvas;
- import android.graphics.Paint;
- import android.graphics.Paint.Align;
- import android.graphics.Paint.FontMetricsInt;
- import android.graphics.Paint.Style;
- import android.os.Handler;
- import android.os.Message;
- import android.util.AttributeSet;
- import android.view.MotionEvent;
- import android.view.View;
- import com.pickerscrollview.bean.Pickers;
- /**
- * 自定义滚动选择器
- *
- * @author zengtao 2015年5月20日 下午7:36:03
- *
- */
- @SuppressLint({ "HandlerLeak", "ClickableViewAccessibility" })
- public class PickerScrollView extends View {
- public static final String TAG = "PickerView";
- /**
- * text之间间距和minTextSize之比
- */
- public static final float MARGIN_ALPHA = 2.8f;
- /**
- * 自动回滚到中间的速度
- */
- public static final float SPEED = 2;
- private List<Pickers> mDataList;
- /**
- * 选中的位置,这个位置是mDataList的中心位置,一直不变
- */
- private int mCurrentSelected;
- private Paint mPaint;
- private float mMaxTextSize = 20;
- private float mMinTextSize = 10;
- private float mMaxTextAlpha = 255;
- private float mMinTextAlpha = 120;
- private int mColorText = 0x333333;
- private int mViewHeight;
- private int mViewWidth;
- private float mLastDownY;
- /**
- * 滑动的距离
- */
- private float mMoveLen = 0;
- private boolean isInit = false;
- private onSelectListener mSelectListener;
- private Timer timer;
- private MyTimerTask mTask;
- Handler updateHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (Math.abs(mMoveLen) < SPEED) {
- mMoveLen = 0;
- if (mTask != null) {
- mTask.cancel();
- mTask = null;
- performSelect();
- }
- } else
- // 这里mMoveLen / Math.abs(mMoveLen)是为了保有mMoveLen的正负号,以实现上滚或下滚
- mMoveLen = mMoveLen - mMoveLen / Math.abs(mMoveLen) * SPEED;
- invalidate();
- }
- };
- public PickerScrollView(Context context) {
- super(context);
- init();
- }
- public PickerScrollView(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
- public void setOnSelectListener(onSelectListener listener) {
- mSelectListener = listener;
- }
- private void performSelect() {
- if (mSelectListener != null)
- mSelectListener.onSelect(mDataList.get(mCurrentSelected));
- }
- public void setData(List<Pickers> datas) {
- mDataList = datas;
- mCurrentSelected = datas.size() / 2;
- invalidate();
- }
- /**
- * 选择选中的item的index
- *
- * @param selected
- */
- public void setSelected(int selected) {
- mCurrentSelected = selected;
- int distance = mDataList.size() / 2 - mCurrentSelected;
- if (distance < 0)
- for (int i = 0; i < -distance; i++) {
- moveHeadToTail();
- mCurrentSelected--;
- }
- else if (distance > 0)
- for (int i = 0; i < distance; i++) {
- moveTailToHead();
- mCurrentSelected++;
- }
- invalidate();
- }
- /**
- * 选择选中的内容
- *
- * @param mSelectItem
- */
- public void setSelected(String mSelectItem) {
- for (int i = 0; i < mDataList.size(); i++)
- if (mDataList.get(i).equals(mSelectItem)) {
- setSelected(i);
- break;
- }
- }
- private void moveHeadToTail() {
- Pickers head = mDataList.get(0);
- mDataList.remove(0);
- mDataList.add(head);
- }
- private void moveTailToHead() {
- Pickers tail = mDataList.get(mDataList.size() - 1);
- mDataList.remove(mDataList.size() - 1);
- mDataList.add(0, tail);
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- mViewHeight = getMeasuredHeight();
- mViewWidth = getMeasuredWidth();
- // 按照View的高度计算字体大小
- mMaxTextSize = mViewHeight / 8.0f;
- mMinTextSize = mMaxTextSize / 2f;
- isInit = true;
- invalidate();
- }
- private void init() {
- timer = new Timer();
- mDataList = new ArrayList<Pickers>();
- mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- mPaint.setStyle(Style.FILL);
- mPaint.setTextAlign(Align.CENTER);
- mPaint.setColor(mColorText);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
- // 根据index绘制view
- if (isInit)
- drawData(canvas);
- }
- private void drawData(Canvas canvas) {
- // 先绘制选中的text再往上往下绘制其余的text
- float scale = parabola(mViewHeight / 4.0f, mMoveLen);
- float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize;
- mPaint.setTextSize(size);
- mPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha));
- // text居中绘制,注意baseline的计算才能达到居中,y值是text中心坐标
- float x = (float) (mViewWidth / 2.0);
- float y = (float) (mViewHeight / 2.0 + mMoveLen);
- FontMetricsInt fmi = mPaint.getFontMetricsInt();
- float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));
- int indexs = mCurrentSelected;
- String textData = mDataList.get(indexs).getShowConetnt();
- canvas.drawText(textData, x, baseline, mPaint);
- // 绘制上方data
- for (int i = 1; (mCurrentSelected - i) >= 0; i++) {
- drawOtherText(canvas, i, -1);
- }
- // 绘制下方data
- for (int i = 1; (mCurrentSelected + i) < mDataList.size(); i++) {
- drawOtherText(canvas, i, 1);
- }
- }
- /**
- * @param canvas
- * @param position
- * 距离mCurrentSelected的差值
- * @param type
- * 1表示向下绘制,-1表示向上绘制
- */
- private void drawOtherText(Canvas canvas, int position, int type) {
- float d = (float) (MARGIN_ALPHA * mMinTextSize * position + type
- * mMoveLen);
- float scale = parabola(mViewHeight / 4.0f, d);
- float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize;
- mPaint.setTextSize(size);
- mPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha));
- float y = (float) (mViewHeight / 2.0 + type * d);
- FontMetricsInt fmi = mPaint.getFontMetricsInt();
- float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0));
- int indexs = mCurrentSelected + type * position;
- String textData = mDataList.get(indexs).getShowConetnt();
- canvas.drawText(textData, (float) (mViewWidth / 2.0), baseline, mPaint);
- }
- /**
- * 抛物线
- *
- * @param zero
- * 零点坐标
- * @param x
- * 偏移量
- * @return scale
- */
- private float parabola(float zero, float x) {
- float f = (float) (1 - Math.pow(x / zero, 2));
- return f < 0 ? 0 : f;
- }
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
- doDown(event);
- break;
- case MotionEvent.ACTION_MOVE:
- doMove(event);
- break;
- case MotionEvent.ACTION_UP:
- doUp(event);
- break;
- }
- return true;
- }
- private void doDown(MotionEvent event) {
- if (mTask != null) {
- mTask.cancel();
- mTask = null;
- }
- mLastDownY = event.getY();
- }
- private void doMove(MotionEvent event) {
- mMoveLen += (event.getY() - mLastDownY);
- if (mMoveLen > MARGIN_ALPHA * mMinTextSize / 2) {
- // 往下滑超过离开距离
- moveTailToHead();
- mMoveLen = mMoveLen - MARGIN_ALPHA * mMinTextSize;
- } else if (mMoveLen < -MARGIN_ALPHA * mMinTextSize / 2) {
- // 往上滑超过离开距离
- moveHeadToTail();
- mMoveLen = mMoveLen + MARGIN_ALPHA * mMinTextSize;
- }
- mLastDownY = event.getY();
- invalidate();
- }
- private void doUp(MotionEvent event) {
- // 抬起手后mCurrentSelected的位置由当前位置move到中间选中位置
- if (Math.abs(mMoveLen) < 0.0001) {
- mMoveLen = 0;
- return;
- }
- if (mTask != null) {
- mTask.cancel();
- mTask = null;
- }
- mTask = new MyTimerTask(updateHandler);
- timer.schedule(mTask, 0, 10);
- }
- class MyTimerTask extends TimerTask {
- Handler handler;
- public MyTimerTask(Handler handler) {
- this.handler = handler;
- }
- @Override
- public void run() {
- handler.sendMessage(handler.obtainMessage());
- }
- }
- public interface onSelectListener {
- void onSelect(Pickers pickers);
- }
- }
- package com.pickerscrollview.bean;
- import java.io.Serializable;
- /**
- *
- * @author zengtao 2015年5月20日下午7:18:14
- *
- */
- public class Pickers implements Serializable {
- private static final long serialVersionUID = 1L;
- private String showConetnt;
- private String showId;
- public String getShowConetnt() {
- return showConetnt;
- }
- public String getShowId() {
- return showId;
- }
- public Pickers(String showConetnt, String showId) {
- super();
- this.showConetnt = showConetnt;
- this.showId = showId;
- }
- public Pickers() {
- super();
- }
- }
(3)主界面
- package com.pickerscrollview.ui;
- import java.util.ArrayList;
- import java.util.List;
- import android.app.Activity;
- import android.os.Bundle;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.RelativeLayout;
- import com.pickerscrollview.bean.Pickers;
- import com.pickerscrollview.views.PickerScrollView;
- import com.pickerscrollview.views.PickerScrollView.onSelectListener;
- /**
- * 主界面
- *
- * @author zengtao 2015年5月20日 下午7:36:03
- *
- */
- public class MainActivity extends Activity {
- private Button bt_scrollchoose; // 滚动选择器按钮
- private PickerScrollView pickerscrlllview; // 滚动选择器
- private List<Pickers> list; // 滚动选择器数据
- private String[] id;
- private String[] name;
- private Button bt_yes; // 确定按钮
- private RelativeLayout picker_rel; // 选择器布局
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initView();
- initLinstener();
- initData();
- }
- /**
- * 初始化
- */
- private void initView() {
- bt_scrollchoose = (Button) findViewById(R.id.bt_scrollchoose);
- picker_rel = (RelativeLayout) findViewById(R.id.picker_rel);
- pickerscrlllview = (PickerScrollView) findViewById(R.id.pickerscrlllview);
- bt_yes = (Button) findViewById(R.id.picker_yes);
- }
- /**
- * 设置监听事件
- */
- private void initLinstener() {
- bt_scrollchoose.setOnClickListener(onClickListener);
- pickerscrlllview.setOnSelectListener(pickerListener);
- bt_yes.setOnClickListener(onClickListener);
- }
- /**
- * 初始化数据
- */
- private void initData() {
- list = new ArrayList<Pickers>();
- id = new String[] { "1", "2", "3", "4", "5", "6" };
- name = new String[] { "中国银行", "农业银行", "招商银行", "工商银行", "建设银行", "民生银行" };
- for (int i = 0; i < name.length; i++) {
- list.add(new Pickers(name[i], id[i]));
- }
- // 设置数据,默认选择第一条
- pickerscrlllview.setData(list);
- pickerscrlllview.setSelected(0);
- }
- // 滚动选择器选中事件
- onSelectListener pickerListener = new onSelectListener() {
- @Override
- public void onSelect(Pickers pickers) {
- System.out.println("选择:" + pickers.getShowId() + "--银行:"
- + pickers.getShowConetnt());
- }
- };
- // 点击监听事件
- OnClickListener onClickListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (v == bt_scrollchoose) {
- picker_rel.setVisibility(View.VISIBLE);
- } else if (v == bt_yes) {
- picker_rel.setVisibility(View.GONE);
- }
- }
- };
- }