【安卓深度控件开发(2.1)】LCDView - 基本绘图

<p>好了,今天我们来真正自己动手制作控件了,在本章中我们会从最简单开始。虽然是简单,但你必须已经能自己做 Activity 等最基本的东西。</p> <p>注意,我不会:</p> <ol> <li>控件中不会使用任何 res/ 下的文件支持,因为这对于为自己建立一个控件库来说不是必须的,相反它让设计变的复杂,做一个简单的控件在多个文件中跳来跳去可不是什么好玩的事,特别是未来你需要把控件复制到你的项目中使用时,如果只需要复制一个 .java 文件是多么简单,你不用为了复制相关副属资源文件找来找去了,不是吗。当然,如果你的确需要设计时能设定一大堆自己的属性什么的,你完全可以按第一章提到的方式去实现。 </li> <li>不会使用太多 Android 框架下的帮助类与方法,因为我也在看呢 :)。如果一定要找个理由来说的话,我相信专为控件而定制的帮助方法一定比通用版本的简单,从而更有效率。 </li> <li>从第一章到最后一章,几乎不会找到有一个函数始终是一样的。因为我们是从简单开始,但最后,我们希望的是实用好用,而不是个 TEST 而已。 </li> <li>我不会写大堆的文字说明来解析每一行代码,因为大部分东西我已经以注释的样式写在代码里了。我不需要你忘记了什么之后再来的点击量 :) </li> </ol> <p>&#160;</p> <h2>目标</h2> <p>来说说我们这次是目标 – LCDView。</p> <p>从名字可以看出,它是一个模拟 LCD 效果的视图或直白说成是模拟点阵屏幕好了。</p> <p>&#160;</p> <h2>版本一</h2> <p>首先按您喜欢的名称创建一个新的 Android 项目,然后新建一个类 LCDView,实现如下:</p> <div> <pre><span style="color: #0000ff">public</span> <span style="color: #0000ff">class</span> LCDView <span style="color: #0000ff">extends</span> View {

<span style="color: #0000ff">private</span> String text = &quot;<span style="color: #8b0000">LCD 自定义视图</span>&quot;;
<span style="color: #0000ff">private</span> Paint mTextPaint = <span style="color: #0000ff">new</span> Paint();
<span style="color: #0000ff">private</span> Paint mLinePaint = <span style="color: #0000ff">new</span> Paint();
<span style="color: #0000ff">private</span> Rect mBounds = <span style="color: #0000ff">new</span> Rect();
<span style="color: #0000ff">private</span> Point mTextPos = <span style="color: #0000ff">new</span> Point();
<span style="color: #0000ff">private</span> Rect mTextBounds = <span style="color: #0000ff">new</span> Rect();

<span style="color: #0000ff">public</span> LCDView(Context context, AttributeSet attrs) {
	<span style="color: #0000ff">super</span>(context, attrs);		
	init();
}

<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> init() {
	<span style="color: #008000">// 默认背景为黑色</span>
	setBackgroundColor(Color.BLACK);
	mLinePaint.setColor(0xcc000000);
	mLinePaint.setStyle(Style.STROKE);
	mLinePaint.setStrokeWidth(1);
	
	<span style="color: #008000">// 默认文本为白色</span>
	mTextPaint.setColor(Color.WHITE);
	mTextPaint.setTextSize(36);
	mTextPaint.setTextAlign(Align.CENTER);
}

@Override
<span style="color: #0000ff">protected</span> <span style="color: #0000ff">void</span> onSizeChanged(<span style="color: #0000ff">int</span> w, <span style="color: #0000ff">int</span> h, <span style="color: #0000ff">int</span> oldw, <span style="color: #0000ff">int</span> oldh) {
	<span style="color: #0000ff">super</span>.onSizeChanged(w, h, oldw, oldh);
	<span style="color: #008000">// 计算我们可能用于绘制内容的区域</span>
	mBounds.set(getPaddingLeft(), getPaddingTop(), w - getPaddingLeft() - getPaddingRight(), h - getPaddingTop() - getPaddingBottom());		
	recalcTextPoint();
}

<span style="color: #0000ff">private</span> <span style="color: #0000ff">void</span> recalcTextPoint() {
	<span style="color: #008000">// 我们将在视图的正中间绘制文本,这里计算文本需要绘制的位置</span>
	<span style="color: #0000ff">int</span> textHeight = 0;
	<span style="color: #0000ff">if</span>(text != <span style="color: #0000ff">null</span> &amp;&amp; !text.isEmpty()) {
		mTextPaint.getTextBounds(text, 0, 1, mTextBounds);
		textHeight = mTextBounds.height();
	}
	mTextPos.x = mBounds.centerX();
	mTextPos.y = mBounds.centerY() + (textHeight / 2);		
}

@Override
<span style="color: #0000ff">protected</span> <span style="color: #0000ff">void</span> onDraw(Canvas canvas) {
	<span style="color: #0000ff">super</span>.onDraw(canvas);
	<span style="color: #0000ff">if</span>(text == <span style="color: #0000ff">null</span> &amp;&amp; text.isEmpty()) {
		<span style="color: #0000ff">return</span>;
	}		
	canvas.drawText(text, mTextPos.x, mTextPos.y, mTextPaint);
	
	<span style="color: #008000">// 相当直接的做法,后面将变很多次</span>
	<span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> y=mBounds.top; y&lt;mBounds.bottom; y+=2) {
		canvas.drawLine(mBounds.left, y, mBounds.right, y, mLinePaint);
	}
}

<span style="color: #008000">/***** 公共用户属性 *****/</span>

<span style="color: #008000">/**
 * 获取当前显示文本
 * @return
 */</span>
<span style="color: #0000ff">public</span> String getText() {
	<span style="color: #0000ff">return</span> text;
}

<span style="color: #008000">/**
 * 设置要显示的文本
 * @param text
 */</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setText(String text) {
	<span style="color: #0000ff">this</span>.text = text;
	recalcTextPoint();
	invalidate();
}

<span style="color: #008000">/**
 * 获取当前文本颜色
 * @return
 */</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">int</span> getTextColor() {
	<span style="color: #0000ff">return</span> mTextPaint.getColor();
}

<span style="color: #008000">/**
 * 设置当前文本颜色
 * @param color
 */</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setTextColor(<span style="color: #0000ff">int</span> color) {
	mTextPaint.setColor(color);
	invalidate();
}

<span style="color: #008000">/**
 * 获取当前文本字体大小
 * @return
 */</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">float</span> getTextSize() {
	<span style="color: #0000ff">return</span> mTextPaint.getTextSize();
}

<span style="color: #008000">/**
 * 设置当前文本字体大小
 * @param textSize
 */</span>
<span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> setTextSize(<span style="color: #0000ff">float</span> textSize) {
	mTextPaint.setTextSize(textSize);
	recalcTextPoint();
	invalidate();
}

}</pre>

</div>

<br />

<p>完成了,它就是一个可用的视图了,打开 activity_main.xml 点左边的 “Custom &amp; Library Views”然后点面板底部的 “Refresh”,看到它了吧,像一般自带控件一样,拖到设计界面里去,然后运行看看效果。</p>

<p>在主要的绘图代码里,我们通过绘制间隔为一个像素的半透明黑色横向线条,让它看起来像 LCD 一样了。</p>

<p>可以看到在几个给用户操作的 setter 中,有些调用了 recalcTextPoint() 与 invalidate(),而有些只调用了 invalidate() ,原则是只干你需要干的事,多的事咱不干~~~</p>

<p>现在让我们在添加一个按钮看看 setter 有木有效果:</p>

<ol> <li>再拖一个按钮到设计界面,修改 id 为 “buttonChangeColor” </li>

<li>切换到 MainActivity.java ,在 onCreate 之前加入如下代码: <div style="border-bottom: #ddd 1px solid; border-left: #ddd 1px solid; padding-bottom: 1em; margin: 0px 0px 1em; padding-left: 1em; padding-right: 1em; background: #f7f7f7; overflow: auto; border-top: #ddd 1px solid; border-right: #ddd 1px solid; padding-top: 1em"> <pre> <span style="color: #0000ff">private</span> <span style="color: #0000ff">static</span> <span style="color: #0000ff">final</span> <span style="color: #0000ff">int</span>[] colors = <span style="color: #0000ff">new</span> <span style="color: #0000ff">int</span>[]{ Color.WHITE, Color.BLUE, Color.GREEN, Color.RED, Color.YELLOW };

<span style="color: #0000ff">private</span> <span style="color: #0000ff">int</span> colorIndex = 0;

<span style="color: #0000ff">private</span> LCDView lcd;</pre>
</div>

</li>

<li>在 onCreate 内部的尾部加入加入代码: <div style="border-bottom: #ddd 1px solid; border-left: #ddd 1px solid; padding-bottom: 1em; margin: 0px 0px 1em; padding-left: 1em; padding-right: 1em; background: #f7f7f7; overflow: auto; border-top: #ddd 1px solid; border-right: #ddd 1px solid; padding-top: 1em"> <pre> lcd = (LCDView)findViewById(R.id.lCDView1); findViewById(R.id.buttonChangeColor).setOnClickListener(<span style="color: #0000ff">this</span>);</pre> </div> </li>

<li>为 MainActivity 类实现 OnClickListener 接口,添加实现函数: <div style="border-bottom: #ddd 1px solid; border-left: #ddd 1px solid; padding-bottom: 1em; margin: 0px 0px 1em; padding-left: 1em; padding-right: 1em; background: #f7f7f7; overflow: auto; border-top: #ddd 1px solid; border-right: #ddd 1px solid; padding-top: 1em"> <pre> @Override <span style="color: #0000ff">public</span> <span style="color: #0000ff">void</span> onClick(View v) { colorIndex++; colorIndex%=colors.length; lcd.setTextColor(colors[colorIndex]); }</pre> </div> </li>

<li>运行。 </li> </ol>

<p>好了,点击按钮试试,每一次点击文本颜色在白,蓝,绿,红,黄中转换,看起来还不错。</p>

<p>目前这个代码有两个问题,一个是如果用户调用 setBackgroundColor 修改了背景色,你的线条就曝光了;另一个问题,用 for 循环去画直线条这太低层次了,我们将在下一节中完善。 </p>

转载于:https://my.oschina.net/jock/blog/118808

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值