<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                上一篇做了一個水波紋view ?不知道大家有沒有動手試試呢[點擊打開鏈接](http://blog.csdn.net/wingichoy/article/details/50523713) 這個效果做起來好像沒什么意義,如果不加監聽回調 圖片就能直接替代。寫這篇博客的目的是鍛煉一下思維能力,以更好的面多各種自定義view需求。 轉載請注明出處:http://blog.csdn.net/wingichoy/article/details/50554058 本文是和代碼同步寫的。也就是說在寫文章的時候才敲的代碼。這樣會顯得文章有些許混亂。但是我想這樣記錄下來,一個自定義view的真正的制作過程,是一點一點,一步步跟著思路的改變,完善的。不可能一下子就做出一個完整的view。。技術也是這樣,不可能一步登天。都是一步一步的積累。 另外,每一篇博客都是建立在之前博客的基礎知識上的,如果你剛接觸自定義view。可以來[說說自定義view簡單學習的方式](http://blog.csdn.net/wingichoy/article/details/50483101)這里看我以前的文章。記錄了我學習自定義view的過程,而且前幾篇博客或多或少犯了一些錯誤。這里我并不想改正博文中的錯誤,因為些錯誤是大家經常會犯的,后來的博客都有指出這些錯誤,以及不再犯,這是一個學習的過程。所以我想把錯誤的經歷記錄下來。等成為高手 回頭看看當年的自己是多么菜。。也會有成就感。。 老規矩效果圖如下: ![](https://box.kancloud.cn/2016-03-21_56efaea8addcc.jpg) 首先畫一個六邊形,畫之前來計算一下六邊形的相關知識: ![](https://box.kancloud.cn/2016-03-21_56efaea8c26ef.jpg) 假設一個正六邊形的邊長為a ?,因為每個角都是120° ?所以可得高為根號三a ?,如圖所示。 有了這些信息我們就可以繪制一個六邊形出來,如下: ~~~ float height = (float) (Math.sqrt(3)*mLength); mPath.moveTo(mLength/2,0); mPath.lineTo(0,height/2); mPath.lineTo(mLength/2,height); mPath.lineTo((float) (mLength*1.5),height); mPath.lineTo(2*mLength,height/2); mPath.lineTo((float) (mLength*1.5),0); mPath.lineTo(mLength/2,0); mPath.close(); ~~~ 繪制效果: ![](https://box.kancloud.cn/2016-03-21_56efaea8d39f8.jpg) 然后將其根據一個偏移量進行平移,就可以用循環繪制出多個六邊形 這里offset是偏移量,緊挨著的話應該是偏移一個六邊形的寬,寬由上圖可知為 a/2+a+a/2 即 2a;? ~~~ for(int i = 0 ; i < 3;i++) { int offset = mLength * 2 * i; mPath.moveTo(mLength / 2 + offset, 0); mPath.lineTo(0 + offset, height / 2); mPath.lineTo(mLength / 2 + offset, height); mPath.lineTo((float) (mLength * 1.5) + offset, height); mPath.lineTo(2 * mLength + offset, height / 2); mPath.lineTo((float) (mLength * 1.5)+offset, 0); mPath.lineTo(mLength / 2+offset, 0); mPath.close(); } ~~~ 發現效果如下 ![](https://box.kancloud.cn/2016-03-21_56efaea8e10bd.jpg) 這不對啊,很奇怪啊。。 底下空出來的一個三角形放不下我們的第二行啊。。 那么怎么辦呢。。 加大offset! ?加大多少呢。。 應該多增加一個邊長。。這樣就正好留空了。 來試試 ![](https://box.kancloud.cn/2016-03-21_56efaea8f1d7f.jpg) 現在來準備畫第二行.... 發現我們之前path的坐標都是相對寫死的。。 所以要回過頭改一下,改成給定一個起點,就可以繪制出一個六邊形,經過計算,得出下圖 ![](https://box.kancloud.cn/2016-03-21_56efaea91087d.jpg) 這里a代表邊長。 改完之后的代碼是: ~~~ float height = (float) (Math.sqrt(3)*mLength); for(int i = 0 ; i < 3;i++) { //橫坐標偏移量 int offset = mLength * 3 * i ; //左上角的x int x = mLength/2 + offset; int y = 0; //根據左上角一點 繪制整個正六邊形 mPath.moveTo(x, y); mPath.lineTo(x -mLength/2, height / 2 + y); mPath.lineTo(x, height+y); mPath.lineTo(x + mLength, height +y); mPath.lineTo((float) (x + 1.5*mLength), height / 2+y); mPath.lineTo(x + mLength, y); mPath.lineTo(x, y); mPath.close(); } ~~~ 繪制出來的效果是一樣的。但是方法以及變了。 然后來畫第二行,第二行起點的path應該在這里 ![](https://box.kancloud.cn/2016-03-21_56efaea9226ad.jpg) 坐標是: 2a , height/2 ?這里的偏移量不變。 首先將畫path的方法提取出來(as快捷鍵ctrl + alt + m) ~~~ //根據左上角一點 繪制整個正六邊形 private void getPath(float height, float x, float y) { mPath.moveTo(x, y); mPath.lineTo(x -mLength/2, height / 2 + y); mPath.lineTo(x, height+y); mPath.lineTo(x + mLength, height +y); mPath.lineTo((float) (x + 1.5*mLength), height / 2+y); mPath.lineTo(x + mLength, y); mPath.lineTo(x, y); mPath.close(); } ~~~ 然后再給個循環,來繪制第二行的六邊形 ~~~ for(int i = 0;i<2;i++){ float offset = mLength * 3 * i ; float x = mLength*2 + offset; float y = height/2; getPath(height,x,y); } canvas.drawPath(mPath,mPaint); ~~~ 得到如下的效果。 ![](https://box.kancloud.cn/2016-03-21_56efaea932df1.jpg) 現在ondraw的全部代碼如下: ~~~ @Override protected void onDraw(Canvas canvas) { mPaint.setColor(Color.parseColor("#FFBB33")); //正六邊形的高 float height = (float) (Math.sqrt(3)*mLength); for(int i = 0 ; i < 3;i++) { //橫坐標偏移量 float offset = mLength * 3 * i ; //左上角的x float x = mLength/2 + offset; float y = 0; getPath(height, x, y); } canvas.drawPath(mPath,mPaint); mPath.reset(); mPaint.setColor(Color.parseColor("#AA66CC")); for(int i = 0;i<2;i++){ float offset = mLength * 3 * i ; float x = mLength*2 + offset; float y = height/2; getPath(height,x,y); } canvas.drawPath(mPath,mPaint); } ~~~ 接下來對每行的個數進行一下控制。 ~~~ //每行的個數 private int mColumnsCount = 3; //行數 private int mLineCount = 3; ~~~ 對應的循環也改變,最外面套一個大循環,來控制多行繪制 ~~~ for (int j = 0; j < mLineCount; j++) { if(j%2 == 0) 繪制奇數行 else 繪制偶數行 } ~~~ 現在整個ondraw如下。 ~~~ @Override protected void onDraw(Canvas canvas) { //正六邊形的高 float height = (float) (Math.sqrt(3) * mLength); for (int j = 0; j < mLineCount; j++) { if (j % 2 == 0) { mPaint.setColor(Color.parseColor("#FFBB33")); for (int i = 0; i < mColumnsCount; i++) { //橫坐標偏移量 float offset = mLength * 3 * i; //左上角的x float x = mLength / 2 + offset; float y = j * height / 2; getPath(height, x, y); } canvas.drawPath(mPath, mPaint); mPath.reset(); } else { mPaint.setColor(Color.parseColor("#AA66CC")); for (int i = 0; i < mColumnsCount; i++) { float offset = mLength * 3 * i; float x = mLength * 2 + offset; float y = (height / 2) * j; getPath(height, x, y); } canvas.drawPath(mPath, mPaint); mPath.reset(); } } } ~~~ ![](https://box.kancloud.cn/2016-03-21_56efaea94394c.jpg) 好像顏色一樣就不好看了。。那我們來動態改變一下顏色.. 添加一個屬性list來存放color ~~~ private ArrayList<Integer> mColorList; ~~~ ~~~ mColorList = new ArrayList<>(); mColorList.add(Color.parseColor("#33B5E5")); mColorList.add(Color.parseColor("#AA66CC")); mColorList.add(Color.parseColor("#99CC00")); mColorList.add(Color.parseColor("#FFBB33")); mColorList.add(Color.parseColor("#FF4444")); ~~~ 在循環中,取出顏色值 ~~~ for (int j = 0; j < mLineCount; j++) { mPaint.setColor(mColorList.get(j)); ~~~ 效果如下: ![](https://box.kancloud.cn/2016-03-21_56efaea95307f.jpg) 嗯。。看起來像一點樣子了。。。 給中間加點文字吧。。 先給每個蜂窩編號 ![](https://box.kancloud.cn/2016-03-21_56efaea962af3.jpg) 按上面的循環 ? j為行數 ?i為列數 ? **研究規律發現 ? 編號等于 j*3 + i?** 我們有六邊形左上角的坐標xy 可以輕易的計算出中心坐標 ![](https://box.kancloud.cn/2016-03-21_56efaea974574.jpg) 這些都有了。開一個list存放中間的文字: ~~~ //存放文字的list private ArrayList<String> mTextList ; ~~~ 在初始化的時候給添加點數據 ~~~ mTextList = new ArrayList<>(); for(int i =0;i<mLineCount*mColumnsCount;i++){ mTextList.add("wing "+i); } mTextPaint = new Paint(); mTextPaint.setTextSize(20); ~~~ 繪制文字: 這里要注意他和path的繪制順序,如果path后繪制則會覆蓋掉文字 ~~~ float txtLength = mTextPaint.measureText(mTextList.get(txtId)); canvas.drawText(mTextList.get(txtId),x+mLength/2-txtLength/2,y+height/2+5, mTextPaint); ~~~ 下面是全部的ondraw ~~~ @Override protected void onDraw(Canvas canvas) { //正六邊形的高 float height = (float) (Math.sqrt(3) * mLength); for (int j = 0; j < mLineCount; j++) { mPaint.setColor(mColorList.get(j)); if (j % 2 == 0) { // mPaint.setColor(Color.parseColor("#FFBB33")); for (int i = 0; i < mColumnsCount; i++) { int txtId = j*3 +i; //橫坐標偏移量 float offset = mLength * 3 * i; //左上角的x float x = mLength / 2 + offset; float y = j * height / 2; mPath.reset(); getPath(height, x, y); canvas.drawPath(mPath, mPaint); float txtLength = mTextPaint.measureText(mTextList.get(txtId)); canvas.drawText(mTextList.get(txtId),x+mLength/2-txtLength/2,y+height/2+5, mTextPaint); } } else { // mPaint.setColor(Color.parseColor("#AA66CC")); for (int i = 0; i < mColumnsCount; i++) { int txtId = j*3 +i; float offset = mLength * 3 * i; float x = mLength * 2 + offset; float y = (height / 2) * j; mPath.reset(); getPath(height, x, y); canvas.drawPath(mPath, mPaint); float txtLength = mTextPaint.measureText(mTextList.get(txtId)); canvas.drawText(mTextList.get(txtId),x+mLength/2-txtLength/2,y+height/2+5, mTextPaint); } } } } ~~~ 現在的效果圖如下: ![](https://box.kancloud.cn/2016-03-21_56efaea8addcc.jpg) 好,那現在讓他靈活一點。添加各種set方法,比如行數啊 列數啊 ?邊長啊 文字內容啊 顏色啊之類的。 ~~~ /** * 設置列數 * @param mColumnsCount */ public void setColumnsCount(int mColumnsCount) { this.mColumnsCount = mColumnsCount; invalidate(); } /** * 設置行數 * @param mLineCount */ public void setLineCount(int mLineCount) { this.mLineCount = mLineCount; invalidate(); } /** * 設置文本數據 */ public void setTextList(ArrayList<String> textList) { mTextList.clear(); mTextList.addAll(textList); invalidate(); } /** * 設置顏色數據 * @param colorList */ public void setColorList(ArrayList<Integer> colorList) { mColorList.clear(); mColorList.addAll(colorList); invalidate(); } ~~~ 然后 你有沒有忘記測量呢? 只要把最外面的矩形大小給他就行 ~~~ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); if(widthMode == MeasureSpec.AT_MOST){ widthSize = (int) ((3f*mColumnsCount+0.5f) *mLength); }else{ // throw new IllegalStateException("only support wrap_content"); } if(heightMode == MeasureSpec.AT_MOST){ heightSize = (int) ((mLineCount/2f +0.5f) * (Math.sqrt(3) * mLength)); }else{ // throw new IllegalStateException("only support wrap_content"); } setMeasuredDimension(widthSize,heightSize); } ~~~ 這下使用wrap_content 來看看view的大小: ![](https://box.kancloud.cn/2016-03-21_56efaea9897c7.jpg) 嗯。。測量也對著。。。 ? 這里我只實現了wrap_content ?大家可以以及擴展 讓他支持EXACTLY 這樣 一個蜂窩煤的view 就完成了。。。但是好像沒鳥用的樣子。。因為沒有交互的話。。圖片完全可以代替。所以這次就先遺留一個問題,事件的處理。其實邏輯也不是很復雜,就是判斷觸摸點 是否在Path內,如果action_up的時候在,分開編號,按照編號進行回調即可,這個問題,準備下篇博客解決,請大家繼續關注我的博客 蟹蟹!。 本項目地址:[點擊打開鏈接](https://github.com/githubwing/HoneycombView) 如果你覺得我寫的還不錯,請點擊一下頂,繼續關注我。謝謝!!
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看