android 自定义控件pickview


运行截图:




PickerView控件类


public class PickerView 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<String> mDataList;    /**  * 选中的位置,这个位置是mDataList的中心位置,一直不变  */  private int mCurrentSelected;    private Paint mPaint;    private float mMaxTextSize = 80;    private float mMinTextSize = 40;    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 PickerView(Context context)    {        super(context);        init();    }    public PickerView(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<String> datas)    {        mDataList = datas;        mCurrentSelected = datas.size() / 2;        invalidate();    }    public void setSelected(int selected)    {        mCurrentSelected = selected;    }    private void moveHeadToTail()    {        String head = mDataList.get(0);        mDataList.remove(0);        mDataList.add(head);    }    private void moveTailToHead()    {        String 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 / 4.0f;        mMinTextSize = mMaxTextSize / 2f;        isInit = true;        invalidate();    }    private void init()    {        timer = new Timer();        mDataList = new ArrayList<String>();        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));        canvas.drawText(mDataList.get(mCurrentSelected), 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));        canvas.drawText(mDataList.get(mCurrentSelected + type * position),                (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(String text);    }}


使用实例


xml 文件


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center"    tools:context="com.chinawit.cwandroidbase.SamplePickerView.PickerViewActivity">    <com.chinawit.cwandroidbase.SamplePickerView.PickerView        android:id="@+id/pickerview"        android:layout_width="200dp"        android:layout_height="200dp" /></LinearLayout>


PickerViewActivity

public class PickerViewActivity extends Activity {    PickerView pickerView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_picker_view);        pickerView= (PickerView) findViewById(R.id.pickerview);        List<String> data = new ArrayList<String>();        for(int i=0;i<10;i++) {            data.add("***"+i);        }        pickerView.setData(data);        pickerView.setOnSelectListener(new PickerView.onSelectListener(){            @Override            public void onSelect(String text)            {                Toast.makeText(PickerViewActivity.this, " " + text,                        Toast.LENGTH_SHORT).show();            }        });    }}





更多相关文章

  1. Android之获取控件的坐标
  2. android EditText插入字符串到光标所在位置
  3. 【Android】手机地图功能——利用手机GPS获取用户地理坐标
  4. Android拖动控件改变其位置
  5. android坐标图解
  6. Android Debug keystore系统位置
  7. Android 的坐标系及矩阵变换

随机推荐

  1. Android两种数据库操作方式入门介绍
  2. Android中实现Broastcast接收短信
  3. Robotium入门
  4. Android取消EditText自动聚焦、自动弹出
  5. 采用busybox 代替android 自带的shell
  6. Android — 创建文件及文件夹
  7. Android Studio之工程中导入jni库方法
  8. Android2.2应用解析
  9. Android圆形进度条控件-CircleSeekBar
  10. Android采用KSOAP2访问webservice