Android開発:カスタムTabLayout、魔法の効果はとても簡単です

序文

何も言わないで、最初にレンダリングを表示します。

最近、会社のUIがそのようなタブ切り替えスタイルをデザインしました。UIデザインの図面を見るとすぐに、かなり気分が良くなりました。しかし、数秒後、私は無意識のうちにこの効果、Android独自のタブレイアウトコントロールがこの効果を達成できないはずだと思いました。突然損失を見て、私はまだそれをカスタマイズする必要があります!しかし、この弧はどうですか...

現時点では、ビューのカスタマイズが面倒だと思う方もいらっしゃるかもしれません。UIで直接この弧を切り取った方がいいです。Textview、ImageViewの合計3つのタブ項目があります。このように、水平に配置します。次に、適切な表示を行い、非表示にします。

はい、それは確かに可能ですが、優れた開発者として。私たちはまだカスタムビュードロップを好む必要があります。

思考分析

(1)効果図から、タブ項目がいくつあっても、この3つの状況しかないことが簡単にわかります。
スケッチは次のとおりです。

(2)どちらの場合も、最初に背景の長方形を描く必要がありますが、これは比較的簡単です。

(3)スケッチでマークされている曲線の描画方法は、明らかに2つの制御点が必要なので、3次ベジェ曲線を使用する必要があります。cubeTo

(4)グラフを描いた後、クリックイベントにどのように対応しますか?onTouchEventのコントロールをクリックすると、x座標とy座標を取得でき、x座標がどのタブ項目内にあるかを判断でき、タブ項目がクリックされたと考えられます。

(5)コントロールの丸みを帯びた角を実現するにはどうすればよいですか?キャンバスはトリミングできます。

コード

アイデアを整理した後、コードを書いてみましょう。

状況1(キーコード):

 //最左边的图形
            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. まず、開始点の座標は(0、0)であり、座標(textWidth、0)に直線を描きます。
  2. 次に、3次ベジェ曲線、2つの制御点の座標は1(textWidth + arcControlX、arcControlY)、座標2(textWidth + arcWidth-arcControlX、viewHeight-arcControlY)、および終了座標(textWidth + arcWidth、viewHeight)です。 ;
  3. 最後に、座標点(0、viewHeight)に直線を描き、次に最終的な原点(0、0)に直線を描きます。

ここの閉じた道、ただそれを描いてください。ケース2とケース3でも同じことが言え、ナンセンスな話はもうしません。

状況2(キーコード):

 //中间的图形
            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);

状況3(キーコード):

  //最右边的图形
            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);

タブテキスト(キーコード)の描画:

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);
            }

        }

タブクリック処理(キーコード):

@Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean isHandleClick = false;//是否处理点击事件

        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)) {//点击的第一个按钮
                        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メソッドでは、コントロールをクリックした後に最初にx座標とy座標を取得し、次にforループがx座標がどのタブ項目にあるかを決定し、最後にどの範囲にあるかを判断し、タブ項目がクリックされたと見なします。コールバックは対応しますtabPositionが行います。

リモート依存使用

1つ:依存関係を追加する

リポジトリの最後にあるルートbuild.gradleに追加します。

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

依存関係を追加する

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

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" />

3:コード内

val tabTextList: MutableList<String> = ArrayList<String>()

        tabTextList.add("推荐学习");
        tabTextList.add("企业学院");
        tabTextList.add("我的关注");
        mYPKTabLayoutView.setTabTextList(tabTextList);

        mYPKTabLayoutView.addTabSelectedListener { tabPosition ->
            val makeText =
                Toast.makeText(
                    this@MainActivity,
                    "点击了第" + tabPosition + "项",
                    Toast.LENGTH_SHORT
                )
            makeText.setGravity(Gravity.CENTER, 0, 0);
            makeText.show();
        }

プロパティの説明

記事はこちらです。アイデアを実現するためのより良い提案があれば、メッセージを残して私を訂正してください。

送信元アドレス:

https://github.com/dacaoyuan/YPKTabDemo

やっと

ここでは、Android学習PDF +アーキテクチャビデオ+インタビュードキュメント+ソースノート高度なアーキテクチャテクノロジーの高度なマインドマップ、Android開発のインタビューの特別な資料、複数の大物によって収集および整理された高度な高度なアーキテクチャの資料も共有します。

これらは私が暇なときに何度も何度も読む素晴らしい資料です。誰もが知識を習得し、原則を理解するのを効果的に助けることができます。もちろん、脱落をチェックして競争力を高めるためにも使用できます。

あなたがそれを必要とするならば、あなたはそれをここで手に入れることができ ます

この記事が気に入ったら、ちょっといいねを言ったり、コメント欄にメッセージを残したり、転送してサポートしたりしてください〜

おすすめ

転載: blog.csdn.net/River_ly/article/details/107228575