<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android自定義TabLayout,神奇效果竟是如此簡單

          共 6206字,需瀏覽 13分鐘

           ·

          2021-08-27 19:34

          前言

          啥話不說,先亮出效果圖:


          最近公司UI設(shè)計(jì)了一個(gè)這樣的tab切換的樣式,剛一看到UI設(shè)計(jì)圖,感覺還是不錯(cuò)滴。但是幾秒鐘后下意識想到,這個(gè)效果,Android自帶的 tablayout 控件應(yīng)該實(shí)現(xiàn)不了這效果呢。頓時(shí)一臉茫然,我還要自定義一個(gè)不成!但是這個(gè)弧度怎么搞…

          此時(shí)有的小伙伴可能會想,自定義view太麻煩,不如讓UI直接把這個(gè)弧度切出來,不是一共就三個(gè)tab項(xiàng)嘛,Textview,ImageView… 這樣橫著排起來,然后做適當(dāng)?shù)娘@示和隱藏不就行啦。

          是的,確實(shí)是可以,但是作為一個(gè)優(yōu)秀的開發(fā)人員。我們還是要優(yōu)選自定義view滴。

          思路分析

          (1) 由效果圖,我們很容易分析出,不管tab項(xiàng)一共幾個(gè),無非就這三種情況。

          草圖如下:


          (2) 無論是哪種情況,首先我們需要畫出一個(gè)背景矩形,這個(gè)比較簡單。

          (3)下面就是曲線的畫法,草圖中也已經(jīng)標(biāo)注了,很明顯我需要2個(gè)控制點(diǎn),那就需要用到三階貝塞爾曲線啦!cubicTo

          (4)畫出圖形后,點(diǎn)擊事件如何響應(yīng)處理呢?我們在 onTouchEvent 是能獲取到點(diǎn)擊控件后x,y坐標(biāo)的,判斷x的坐標(biāo)是在哪個(gè)tab項(xiàng)的范圍內(nèi),我們就認(rèn)為點(diǎn)擊了那個(gè)tab項(xiàng),就可以了。

          (5)控件的圓角的如何實(shí)現(xiàn)呢?canvas的 范圍裁切 就可以啦。


          代碼實(shí)現(xiàn)

          思路梳理好了,那我們就寫代碼吧:

          情況一(關(guān)鍵代碼):
           //最左邊的圖形            Path pathLeft = new Path();

          pathLeft.lineTo(textWidth, 0);
          pathLeft.cubicTo(textWidth + arcControlX, arcControlY, textWidth + arcWidth - arcControlX, viewHeight - arcControlY, textWidth + arcWidth, viewHeight);
          pathLeft.lineTo(0, viewHeight);
          pathLeft.lineTo(0, 0);

          paint.setColor(selectColor); canvas.drawPath(pathLeft, paint);

          步驟說明:

          1. 首先我們的起始點(diǎn)坐標(biāo)是(0,0),到坐標(biāo)(textWidth, 0) 畫一條直線;


          2. 然后三階貝塞爾曲線,2個(gè)控制點(diǎn)的坐標(biāo)1(textWidth + arcControlX,arcControlY),坐標(biāo)2(textWidth + arcWidth - arcControlX,viewHeight - arcControlY),結(jié)束的坐標(biāo)(textWidth + arcWidth,viewHeight);


          3. 最后畫直線到坐標(biāo)點(diǎn)(0, viewHeight),再到最終的原點(diǎn)(0, 0)。


          到這里一個(gè)封閉的路徑,就畫好啦。情況二和情況三也是同樣的道理,我也不再廢話了。

          情況二(關(guān)鍵代碼):
           //中間的圖形            Path pathCenter = new Path();            pathCenter.moveTo(tabPosition * textWidth + tabPosition * arcWidth, 0);            pathCenter.cubicTo(tabPosition * textWidth + tabPosition * arcWidth - arcControlX, arcControlY, tabPosition * textWidth + tabPosition * arcWidth - arcWidth + arcControlX, viewHeight - arcControlY, tabPosition * textWidth + tabPosition * arcWidth - arcWidth, viewHeight);            pathCenter.lineTo(tabPosition * textWidth + tabPosition * arcWidth + textWidth + arcWidth, viewHeight);            pathCenter.cubicTo(tabPosition * textWidth + tabPosition * arcWidth + textWidth + arcWidth - arcControlX, viewHeight - arcControlY, tabPosition * textWidth + tabPosition * arcWidth + textWidth + arcControlX, arcControlY, tabPosition * textWidth + tabPosition * arcWidth + textWidth, 0);            pathCenter.lineTo(tabPosition * textWidth + tabPosition * arcWidth, 0);

          paint.setColor(selectColor); canvas.drawPath(pathCenter, paint);

          情況三(關(guān)鍵代碼):
            //最右邊的圖形            Path pathRight = new Path();            pathRight.moveTo(viewWidth, 0);
          pathRight.lineTo(viewWidth - textWidth, 0);

          pathRight.cubicTo(viewWidth - textWidth - arcControlX, arcControlY, viewWidth - textWidth - arcWidth + arcControlX, viewHeight - arcControlY, viewWidth - textWidth - arcWidth, viewHeight);
          pathRight.lineTo(viewWidth, viewHeight);
          pathRight.lineTo(viewWidth, 0);
          paint.setColor(selectColor); canvas.drawPath(pathRight, paint);

          tabtext的繪制(關(guān)鍵代碼):
          for (int i = 0; i < tabTextList.size(); i++) {            String strTabText = tabTextList.get(i);            Rect rectText = new Rect();            textPaint.getTextBounds(strTabText, 0, strTabText.length(), rectText);            int strWidth = rectText.width();            int strHeight = rectText.height();            if (i == 0) {                canvas.drawText(strTabText, (textWidth + arcWidth / 2) / 2 - strWidth / 2, viewHeight / 2 + strHeight / 2, textPaint);            } else if (i == tabTextList.size() - 1) {                canvas.drawText(strTabText, viewWidth - (textWidth + arcWidth / 2) / 2 - strWidth / 2, viewHeight / 2 + strHeight / 2, textPaint);
          } else { canvas.drawText(strTabText, textWidth * i + arcWidth * (i - 1) + (textWidth + 2 * arcWidth) / 2 - strWidth / 2, viewHeight / 2 + strHeight / 2, textPaint); }
          }


          tab點(diǎn)擊處理(關(guān)鍵代碼):
          @Override    public boolean onTouchEvent(MotionEvent event) {        boolean isHandleClick = false;//是否處理點(diǎn)擊事件
          switch (event.getAction()) { case MotionEvent.ACTION_DOWN: float x = event.getX(); float y = event.getY(); System.out.println("YPKTabLayoutView.onTouchEvent x=" + x + " y=" + y); for (int i = 0; i < tabNumber; i++) { if (x <= ((i + 1) * textWidth + i * arcWidth + arcWidth / 2)) {//點(diǎn)擊的第一個(gè)按鈕 tabPosition = i;
          if (onTabClickListener != null) { onTabClickListener.tabSelectedListener(tabPosition); }
          invalidate(); isHandleClick = true;
          break; } }
          return isHandleClick;

          case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: break; } return super.onTouchEvent(event); }


          步驟說明:

          我們在 onTouchEvent方法中, 首先獲取到點(diǎn)擊控件后x,y坐標(biāo),然后for循環(huán)判斷x的坐標(biāo)是在哪個(gè)tab項(xiàng)的范圍內(nèi),最后在哪個(gè)范圍內(nèi),我們就認(rèn)為點(diǎn)擊了那個(gè)tab項(xiàng),回調(diào)對應(yīng)的 tabPosition 就可以了。


          遠(yuǎn)程依賴使用

          一:添加依賴

          Add it in your root build.gradle at the end of repositories:

          allprojects {    repositories {        ...        maven { url 'https://jitpack.io' }    }}


          Add the dependency

          dependencies {      implementation 'com.github.dacaoyuan:YPKTabDemo:1.0.2'}


          二:在xml布局中添加

          <com.ypk.library.view.YPKTabLayoutView        android:id="@+id/mYPKTabLayoutView"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_margin="10dp"        app:view_bg_corners="0"        app:arcControlX="30" />


          三:代碼中

          val tabTextList: MutableList<String> = ArrayList<String>()
          tabTextList.add("推薦學(xué)習(xí)"); tabTextList.add("企業(yè)學(xué)院"); tabTextList.add("我的關(guān)注"); mYPKTabLayoutView.setTabTextList(tabTextList);
          mYPKTabLayoutView.addTabSelectedListener { tabPosition -> val makeText = Toast.makeText( this@MainActivity, "點(diǎn)擊了第" + tabPosition + "項(xiàng)", Toast.LENGTH_SHORT ) makeText.setGravity(Gravity.CENTER, 0, 0); makeText.show(); }


          屬性說明


          源碼地址:
          https://github.com/dacaoyuan/YPKTabDemo

          到這里就結(jié)束啦
          瀏覽 49
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  超碰乱伦 | 成人色色网| 深夜福利久久 | 久久国产精品久久久 | 性猛交XXXXX富婆免费视频 |