序文
何も言わないで、最初にレンダリングを表示します。
最近、会社の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);
ステップの説明:
- まず、開始点の座標は(0、0)であり、座標(textWidth、0)に直線を描きます。
- 次に、3次ベジェ曲線、2つの制御点の座標は1(textWidth + arcControlX、arcControlY)、座標2(textWidth + arcWidth-arcControlX、viewHeight-arcControlY)、および終了座標(textWidth + arcWidth、viewHeight)です。 ;
- 最後に、座標点(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開発のインタビューの特別な資料、複数の大物によって収集および整理された高度な高度なアーキテクチャの資料も共有します。
これらは私が暇なときに何度も何度も読む素晴らしい資料です。誰もが知識を習得し、原則を理解するのを効果的に助けることができます。もちろん、脱落をチェックして競争力を高めるためにも使用できます。
あなたがそれを必要とするならば、あなたはそれをここで手に入れることができ ます
この記事が気に入ったら、ちょっといいねを言ったり、コメント欄にメッセージを残したり、転送してサポートしたりしてください〜