自定义尺子
2016-01-05 15:17
239 查看
为了进一步学习Canvas,弄了个简单的可以左右滑动的尺子,没有进一步优化,希望以后做到可以想加多少就加多少。现在说下基本思路:
在画线跟画文字的时候用到了Canvas.translate、Canvas.save、Canvas.restore,这几个函数有利于尺寸计算。
/**
* 初始化属性
*/
private void initAttrs (AttributeSet
attrs) {
TypedArray a = mContext .obtainStyledAttributes(attrs ,
R.styleable. RulerView );
lineColor =
a.getColor(R.styleable. RulerView_lineColor, Color. BLACK );
mLineHeight =
a.getDimensionPixelOffset(R.styleable. RulerView_lineHeight, LINE_HEIGHT );
a.recycle() ;
}
在这里主要用到了自定义属性,可以修改线的高度跟线的颜色。
/**
* 初始化画笔
*/
private void initPaint ()
{
mLinePaint = new Paint() ; // 初始绘制线的画笔
mLinePaint .setAntiAlias( true) ; // 去除画笔锯齿
mLinePaint .setStyle(Paint.Style. FILL ); // 设置风格为实线
mLinePaint .setColor( lineColor) ; // 设置画笔颜色
mOuterPaint = new Paint(Paint. ANTI_ALIAS_FLAG ) ;
mOuterPaint .setColor(Color. BLACK) ;
mOuterPaint .setStyle(Paint.Style. STROKE );
mOuterPaint .setStrokeWidth( 1) ;
mTextPaint = new Paint(Paint. ANTI_ALIAS_FLAG ) ;// 初始绘制线的画笔
mTextPaint .setAntiAlias( true) ; // 去除画笔锯齿
mTextPaint .setStyle(Paint.Style. STROKE ); // 设置风格为实线
mTextPaint .setTextSize( 10) ;
mTextPaint .setColor(Color. BLACK) ; // 设置画笔颜色
mBitmapPaint = new Paint() ;
mBitmapPaint .setAntiAlias( true) ;
mBitmapPaint .setDither( true) ;
mBitmapPaint .setFilterBitmap( true) ;
}
/**
* 将 dp 转化为 px, 为了适配
*/
private void initData ()
{
touchSlop =
ViewConfiguration.get( mContext ).getScaledTouchSlop() ;
this. mScroller = new Scroller( mContext) ;
mHalfLineHeight = mLineHeight / 2 ;
mMiddleLineHeight = mLineHeight / 3 ;
mRulerLeftRightMargin =
UiUtils.dipToPx( mContext , RULER_MARGIN_LEFT_RIGHT) ;
mRulerTopBottomMargin =
UiUtils.dipToPx( mContext , RULER_MARGIN_TOP_BOTTOM) ;
mFirstLineMargin =
UiUtils. dipToPx( mContext, FIRST_LINE_MARGIN ) ;
rulerBitmap =
((BitmapDrawable)mContext .getResources().getDrawable(R.mipmap. ruler )).getBitmap();
mRulerWidth =
UiUtils. dipToPx( mContext, mRulerWidth ) ;
mRulerHeight =
UiUtils. dipToPx( mContext, mRulerHeight ) ;
}
/**
* 绘制处边框
* @param canvas
*/
private void drawOuter (Canvas
canvas) {
canvas.drawRect(mOutRect , mOuterPaint) ;
}
/**
* 绘制线
* @param canvas
*/
private void drawLine (Canvas
canvas) {
canvas.save();
// 第一条线间隔
canvas.translate(( float )
(mFirstLineMargin * 1.5 + mRulerLeftRightMargin ) , 0 ) ;
int top = 0 ;
for( int i
= 1 ; i
<= DEFAULT_LINE_COUNT * DEFAULT_LINE_COUNT ; i++)
{
// 绘制最长线
if (i
% 10 == 0 ||
i == 1 )
{
top = mTotalHeight - mLineHeight ;
}
// 绘制中间线
else if (i
% 5 == 0 )
{
top = mTotalHeight - mHalfLineHeight ;
}
// 绘制短线
else {
top = mTotalHeight - mMiddleLineHeight ;
}
canvas.drawLine(0 , top, 0 , mTotalHeight - mRulerTopBottomMargin , mLinePaint) ;
// 增加相应的间隔
canvas.translate( mLineDivider , 0 ) ;
}
canvas.restore();
}
/**
* 绘制文本
* @param canvas
*/
private void drawText (Canvas
canvas) {
canvas.save();
// 第一条线间隔
canvas.translate(( float )
(mFirstLineMargin * 1.5 + mRulerLeftRightMargin )
- 2, 0 );
for( int i
= 1 ; i
<= DEFAULT_LINE_COUNT * DEFAULT_LINE_COUNT ; i++)
{
canvas.drawText(i + "" , 0, mTotalHeight , mTextPaint ) ;
// 增加相应的间隔
canvas.translate( mLineDivider , 0 ) ;
}
canvas.restore();
}
这样就完成了基本的绘制,但为了可以左右滑动,增加了一个scroller,scoroller滑动的只是内容,位置不变。
/**
* 画标志
* @param canvas
*/
private void drawSymbol (Canvas
canvas) {
canvas.save();
// 第一条线间隔
canvas.translate(( float )
(mFirstLineMargin * 1.5 + mRulerLeftRightMargin )
- 5, mRulerTopBottomMargin ) ;
canvas.drawBitmap( rulerBitmap , mRulerSrcRect , mRulerDestRect , mBitmapPaint) ;
canvas.restore() ;
}
@Override
protected void onSizeChanged (int w ,
int h ,
int oldw,
int oldh) {
super .onSizeChanged(w , h , oldw, oldh) ;
// 记录下 view 的宽高
mTotalWidth =
w ;
mTotalHeight =
h ;
mLineDivider =
( int)
Math. round(( mTotalWidth - mRulerLeftRightMargin * 2 - mFirstLineMargin * 2 )
/ (DEFAULT_LINE_COUNT * DEFAULT_LINE_MIDDLE_COUNT - 1.0 ));
mRulerSrcRect = new Rect( 0 , 0 , mRulerWidth, mRulerHeight ) ;
mRulerDestRect = new Rect( 0 , 0 , mRulerWidth, mRulerHeight ) ;
mWholeRulerWidth =
( DEFAULT_LINE_COUNT *
(DEFAULT_LINE_COUNT - DEFAULT_LINE_MIDDLE_COUNT ))
* mLineDivider ;
mOutRect = new Rect( mRulerLeftRightMargin , mRulerTopBottomMargin , mWholeRulerWidth + mTotalWidth ,mTotalHeight - mRulerTopBottomMargin ) ;
}
@Override
public boolean onTouchEvent (MotionEvent
event) {
int action
= event.getAction() ;
int x = ( int )
event.getX();
int y = ( int )
event.getY();
switch (action) {
case MotionEvent. ACTION_DOWN:
break;
case MotionEvent. ACTION_MOVE :
if (
(x > mRulerLeftRightMargin + mFirstLineMargin )
&& (x < mTotalWidth - mRulerLeftRightMargin -mFirstLineMargin ))
{
int temp
= ( int )
(x - (mRulerLeftRightMargin + mFirstLineMargin * 1.5 ))
- 5 ;
temp = temp > 0 ?
temp : 0;
mRulerDestRect = new Rect(temp, 0 , temp
+ mRulerWidth , mRulerHeight ) ;
postInvalidate();
scrollerSmoothScrollBy( lastX -
x , 0 );
}
break;
case MotionEvent. ACTION_UP :
break;
}
lastX =
x ;
return true;
}
@Override
public void computeScroll ()
{
// 先判断 mScroller 滚动是否完成
if ( mScroller.computeScrollOffset())
{
// 这里调用 View 的scrollTo() 完成实际的滚动
scrollTo( mScroller .getCurrX(), mScroller .getCurrY()) ;
// 必须调用该方法,否则不一定能看到滚动效果
postInvalidate() ;
}
}
// 调用此方法滚动到目标位置
public void scrollerSmoothScrollTo ( int fx ,
int fy) {
int dx
= fx - mScroller.getFinalX() ;
int dy = fy - mScroller .getFinalY();
scrollerSmoothScrollBy(dx , dy);
}
// 调用此方法设置滚动的相对偏移
public void scrollerSmoothScrollBy ( int dx ,
int dy) {
// 设置 mScroller的滚动偏移量
mScroller .startScroll( mScroller.getFinalX() , mScroller .getFinalY() , dx , dy);
invalidate() ; //这里必须调用 invalidate() 才能保证 computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果
}
在画线跟画文字的时候用到了Canvas.translate、Canvas.save、Canvas.restore,这几个函数有利于尺寸计算。
/**
* 初始化属性
*/
private void initAttrs (AttributeSet
attrs) {
TypedArray a = mContext .obtainStyledAttributes(attrs ,
R.styleable. RulerView );
lineColor =
a.getColor(R.styleable. RulerView_lineColor, Color. BLACK );
mLineHeight =
a.getDimensionPixelOffset(R.styleable. RulerView_lineHeight, LINE_HEIGHT );
a.recycle() ;
}
在这里主要用到了自定义属性,可以修改线的高度跟线的颜色。
/**
* 初始化画笔
*/
private void initPaint ()
{
mLinePaint = new Paint() ; // 初始绘制线的画笔
mLinePaint .setAntiAlias( true) ; // 去除画笔锯齿
mLinePaint .setStyle(Paint.Style. FILL ); // 设置风格为实线
mLinePaint .setColor( lineColor) ; // 设置画笔颜色
mOuterPaint = new Paint(Paint. ANTI_ALIAS_FLAG ) ;
mOuterPaint .setColor(Color. BLACK) ;
mOuterPaint .setStyle(Paint.Style. STROKE );
mOuterPaint .setStrokeWidth( 1) ;
mTextPaint = new Paint(Paint. ANTI_ALIAS_FLAG ) ;// 初始绘制线的画笔
mTextPaint .setAntiAlias( true) ; // 去除画笔锯齿
mTextPaint .setStyle(Paint.Style. STROKE ); // 设置风格为实线
mTextPaint .setTextSize( 10) ;
mTextPaint .setColor(Color. BLACK) ; // 设置画笔颜色
mBitmapPaint = new Paint() ;
mBitmapPaint .setAntiAlias( true) ;
mBitmapPaint .setDither( true) ;
mBitmapPaint .setFilterBitmap( true) ;
}
/**
* 将 dp 转化为 px, 为了适配
*/
private void initData ()
{
touchSlop =
ViewConfiguration.get( mContext ).getScaledTouchSlop() ;
this. mScroller = new Scroller( mContext) ;
mHalfLineHeight = mLineHeight / 2 ;
mMiddleLineHeight = mLineHeight / 3 ;
mRulerLeftRightMargin =
UiUtils.dipToPx( mContext , RULER_MARGIN_LEFT_RIGHT) ;
mRulerTopBottomMargin =
UiUtils.dipToPx( mContext , RULER_MARGIN_TOP_BOTTOM) ;
mFirstLineMargin =
UiUtils. dipToPx( mContext, FIRST_LINE_MARGIN ) ;
rulerBitmap =
((BitmapDrawable)mContext .getResources().getDrawable(R.mipmap. ruler )).getBitmap();
mRulerWidth =
UiUtils. dipToPx( mContext, mRulerWidth ) ;
mRulerHeight =
UiUtils. dipToPx( mContext, mRulerHeight ) ;
}
/**
* 绘制处边框
* @param canvas
*/
private void drawOuter (Canvas
canvas) {
canvas.drawRect(mOutRect , mOuterPaint) ;
}
/**
* 绘制线
* @param canvas
*/
private void drawLine (Canvas
canvas) {
canvas.save();
// 第一条线间隔
canvas.translate(( float )
(mFirstLineMargin * 1.5 + mRulerLeftRightMargin ) , 0 ) ;
int top = 0 ;
for( int i
= 1 ; i
<= DEFAULT_LINE_COUNT * DEFAULT_LINE_COUNT ; i++)
{
// 绘制最长线
if (i
% 10 == 0 ||
i == 1 )
{
top = mTotalHeight - mLineHeight ;
}
// 绘制中间线
else if (i
% 5 == 0 )
{
top = mTotalHeight - mHalfLineHeight ;
}
// 绘制短线
else {
top = mTotalHeight - mMiddleLineHeight ;
}
canvas.drawLine(0 , top, 0 , mTotalHeight - mRulerTopBottomMargin , mLinePaint) ;
// 增加相应的间隔
canvas.translate( mLineDivider , 0 ) ;
}
canvas.restore();
}
/**
* 绘制文本
* @param canvas
*/
private void drawText (Canvas
canvas) {
canvas.save();
// 第一条线间隔
canvas.translate(( float )
(mFirstLineMargin * 1.5 + mRulerLeftRightMargin )
- 2, 0 );
for( int i
= 1 ; i
<= DEFAULT_LINE_COUNT * DEFAULT_LINE_COUNT ; i++)
{
canvas.drawText(i + "" , 0, mTotalHeight , mTextPaint ) ;
// 增加相应的间隔
canvas.translate( mLineDivider , 0 ) ;
}
canvas.restore();
}
这样就完成了基本的绘制,但为了可以左右滑动,增加了一个scroller,scoroller滑动的只是内容,位置不变。
/**
* 画标志
* @param canvas
*/
private void drawSymbol (Canvas
canvas) {
canvas.save();
// 第一条线间隔
canvas.translate(( float )
(mFirstLineMargin * 1.5 + mRulerLeftRightMargin )
- 5, mRulerTopBottomMargin ) ;
canvas.drawBitmap( rulerBitmap , mRulerSrcRect , mRulerDestRect , mBitmapPaint) ;
canvas.restore() ;
}
@Override
protected void onSizeChanged (int w ,
int h ,
int oldw,
int oldh) {
super .onSizeChanged(w , h , oldw, oldh) ;
// 记录下 view 的宽高
mTotalWidth =
w ;
mTotalHeight =
h ;
mLineDivider =
( int)
Math. round(( mTotalWidth - mRulerLeftRightMargin * 2 - mFirstLineMargin * 2 )
/ (DEFAULT_LINE_COUNT * DEFAULT_LINE_MIDDLE_COUNT - 1.0 ));
mRulerSrcRect = new Rect( 0 , 0 , mRulerWidth, mRulerHeight ) ;
mRulerDestRect = new Rect( 0 , 0 , mRulerWidth, mRulerHeight ) ;
mWholeRulerWidth =
( DEFAULT_LINE_COUNT *
(DEFAULT_LINE_COUNT - DEFAULT_LINE_MIDDLE_COUNT ))
* mLineDivider ;
mOutRect = new Rect( mRulerLeftRightMargin , mRulerTopBottomMargin , mWholeRulerWidth + mTotalWidth ,mTotalHeight - mRulerTopBottomMargin ) ;
}
@Override
public boolean onTouchEvent (MotionEvent
event) {
int action
= event.getAction() ;
int x = ( int )
event.getX();
int y = ( int )
event.getY();
switch (action) {
case MotionEvent. ACTION_DOWN:
break;
case MotionEvent. ACTION_MOVE :
if (
(x > mRulerLeftRightMargin + mFirstLineMargin )
&& (x < mTotalWidth - mRulerLeftRightMargin -mFirstLineMargin ))
{
int temp
= ( int )
(x - (mRulerLeftRightMargin + mFirstLineMargin * 1.5 ))
- 5 ;
temp = temp > 0 ?
temp : 0;
mRulerDestRect = new Rect(temp, 0 , temp
+ mRulerWidth , mRulerHeight ) ;
postInvalidate();
scrollerSmoothScrollBy( lastX -
x , 0 );
}
break;
case MotionEvent. ACTION_UP :
break;
}
lastX =
x ;
return true;
}
@Override
public void computeScroll ()
{
// 先判断 mScroller 滚动是否完成
if ( mScroller.computeScrollOffset())
{
// 这里调用 View 的scrollTo() 完成实际的滚动
scrollTo( mScroller .getCurrX(), mScroller .getCurrY()) ;
// 必须调用该方法,否则不一定能看到滚动效果
postInvalidate() ;
}
}
// 调用此方法滚动到目标位置
public void scrollerSmoothScrollTo ( int fx ,
int fy) {
int dx
= fx - mScroller.getFinalX() ;
int dy = fy - mScroller .getFinalY();
scrollerSmoothScrollBy(dx , dy);
}
// 调用此方法设置滚动的相对偏移
public void scrollerSmoothScrollBy ( int dx ,
int dy) {
// 设置 mScroller的滚动偏移量
mScroller .startScroll( mScroller.getFinalX() , mScroller .getFinalY() , dx , dy);
invalidate() ; //这里必须调用 invalidate() 才能保证 computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果
}
相关文章推荐
- NotePad++增加java编译选项和查看字节码选项
- css压缩网址
- magento2创建主题
- “App.exe 以附加有调试器,但没有将该调试器配置为调试此未经处理的异常。”
- Linux下查看/管理当前登录用户及用户操作历史记录
- ardupilot在Linux上的启动过程
- 代理模式
- JSONP和ajax的跨域调用
- CC2538之TinyOS例程实验:9-Ppprouter边界路由实验
- 第五章 简单的数据查询
- 聚合函数
- Java——Java方法
- PHP5.4安装xhprof扩展[不要去pecl下载]
- 使用cordova/phonegap 开发应用前请阅读,环境搭建,UI选择,低端机性能问题解决
- Uboot中start.S源码的指令级的详尽解析
- vim配置文件自定义
- Day2 一个月过去了。
- JAVA 对象拷贝
- Maven手工安装jar包到本地仓库
- eclipse汉化