<p>好了,今天咱們來真正本身動手製做控件了,在本章中咱們會從最簡單開始。雖然是簡單,但你必須已經能本身作 Activity 等最基本的東西。</p> <p>注意,我不會:</p> <ol> <li>控件中不會使用任何 res/ 下的文件支持,由於這對於爲本身創建一個控件庫來講不是必須的,相反它讓設計變的複雜,作一個簡單的控件在多個文件中跳來跳去可不是什麼好玩的事,特別是將來你須要把控件複製到你的項目中使用時,若是隻須要複製一個 .java 文件是多麼簡單,你不用爲了複製相關副屬資源文件找來找去了,不是嗎。固然,若是你的確須要設計時能設定一大堆本身的屬性什麼的,你徹底能夠按第一章提到的方式去實現。 </li> <li>不會使用太多 Android 框架下的幫助類與方法,由於我也在看呢 :)。若是必定要找個理由來講的話,我相信專爲控件而定製的幫助方法必定比通用版本的簡單,從而更有效率。 </li> <li>從第一章到最後一章,幾乎不會找到有一個函數始終是同樣的。由於咱們是從簡單開始,但最後,咱們但願的是實用好用,而不是個 TEST 而已。 </li> <li>我不會寫大堆的文字說明來解析每一行代碼,由於大部分東西我已經以註釋的樣式寫在代碼裏了。我不須要你忘記了什麼以後再來的點擊量 :) </li> </ol> <p> </p> <h2>目標</h2> <p>來講說咱們此次是目標 – LCDView。</p> <p>從名字能夠看出,它是一個模擬 LCD 效果的視圖或直白說成是模擬點陣屏幕好了。</p> <p> </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 {java
<span style="color: #0000ff">private</span> String text = "<span style="color: #8b0000">LCD 自定義視圖</span>"; <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> && !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> && 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<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>canvas
</div>框架
<br />ide
<p>完成了,它就是一個可用的視圖了,打開 activity_main.xml 點左邊的 「Custom & Library Views」而後點面板底部的 「Refresh」,看到它了吧,像通常自帶控件同樣,拖到設計界面裏去,而後運行看看效果。</p>函數
<p>在主要的繪圖代碼裏,咱們經過繪製間隔爲一個像素的半透明黑色橫向線條,讓它看起來像 LCD 同樣了。</p>字體
<p>能夠看到在幾個給用戶操做的 setter 中,有些調用了 recalcTextPoint() 與 invalidate(),而有些只調用了 invalidate() ,原則是隻幹你須要乾的事,多的事咱不幹~~~</p>this
<p>如今讓咱們在添加一個按鈕看看 setter 有木有效果:</p>spa
<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 };code
<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>