[解決済み] Androidの縦長(回転)ラベルについて
2022-05-18 01:56:02
質問
Androidで縦書きラベルを表示する方法を2つ教えてください。
- 水平ラベルを反時計回りに90度回転させたもの(文字が横にあるもの)
- 横長のラベルで、1つの文字がもう1つの文字の下にある(店の看板のようなもの)。
両方のケース(1つのケース)に対してカスタムウィジェットを開発する必要があるのか、TextViewをそのようにレンダリングさせることができるのか、完全にカスタムで行う必要がある場合、そのようなことをする良い方法は何でしょうか?
どのように解決するのですか?
TextViewを拡張した、エレガントでシンプルな縦書きテキストの実装を紹介します。TextViewを拡張しているので、TextViewの標準的なスタイルがすべて使用できます。
public class VerticalTextView extends TextView{
final boolean topDown;
public VerticalTextView(Context context, AttributeSet attrs){
super(context, attrs);
final int gravity = getGravity();
if(Gravity.isVertical(gravity) && (gravity&Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity((gravity&Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
topDown = false;
}else
topDown = true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
@Override
protected boolean setFrame(int l, int t, int r, int b){
return super.setFrame(l, t, l+(b-t), t+(r-l));
}
@Override
public void draw(Canvas canvas){
if(topDown){
canvas.translate(getHeight(), 0);
canvas.rotate(90);
}else {
canvas.translate(0, getWidth());
canvas.rotate(-90);
}
canvas.clipRect(0, 0, getWidth(), getHeight(), android.graphics.Region.Op.REPLACE);
super.draw(canvas);
}
}
デフォルトでは、回転したテキストは上から下へ描画されます。android:gravity="bottom" を設定すると、下から上へ描画されます。
技術的には、回転して描画する一方で、通常の回転(数カ所で幅と高さを入れ替える)であると考えるように、基礎となるTextViewをだますことになります。 これはxmlレイアウトで使用されたときにもうまく機能します。
EDITです。 は、別のバージョンを投稿し、上記のアニメーションに問題がある。この新しいバージョンはよりよく動作しますが、マーキーや同様の特殊機能など、いくつかのTextView機能を失います。
public class VerticalTextView extends TextView{
final boolean topDown;
public VerticalTextView(Context context, AttributeSet attrs){
super(context, attrs);
final int gravity = getGravity();
if(Gravity.isVertical(gravity) && (gravity&Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
setGravity((gravity&Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
topDown = false;
}else
topDown = true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
@Override
protected void onDraw(Canvas canvas){
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();
canvas.save();
if(topDown){
canvas.translate(getWidth(), 0);
canvas.rotate(90);
}else {
canvas.translate(0, getHeight());
canvas.rotate(-90);
}
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
getLayout().draw(canvas);
canvas.restore();
}
}
EDIT Kotlin版です。
import android.content.Context
import android.graphics.Canvas
import android.text.BoringLayout
import android.text.Layout
import android.text.TextUtils.TruncateAt
import android.util.AttributeSet
import android.view.Gravity
import androidx.appcompat.widget.AppCompatTextView
import androidx.core.graphics.withSave
class VerticalTextView(context: Context, attrs: AttributeSet) : AppCompatTextView(context, attrs) {
private val topDown = gravity.let { g ->
!(Gravity.isVertical(g) && g.and(Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM)
}
private val metrics = BoringLayout.Metrics()
private var padLeft = 0
private var padTop = 0
private var layout1: Layout? = null
override fun setText(text: CharSequence, type: BufferType) {
super.setText(text, type)
layout1 = null
}
private fun makeLayout(): Layout {
if (layout1 == null) {
metrics.width = height
paint.color = currentTextColor
paint.drawableState = drawableState
layout1 = BoringLayout.make(text, paint, metrics.width, Layout.Alignment.ALIGN_NORMAL, 2f, 0f, metrics, false, TruncateAt.END, height - compoundPaddingLeft - compoundPaddingRight)
padLeft = compoundPaddingLeft
padTop = extendedPaddingTop
}
return layout1!!
}
override fun onDraw(c: Canvas) {
// c.drawColor(0xffffff80); // TEST
if (layout == null)
return
c.withSave {
if (topDown) {
val fm = paint.fontMetrics
translate(textSize - (fm.bottom + fm.descent), 0f)
rotate(90f)
} else {
translate(textSize, height.toFloat())
rotate(-90f)
}
translate(padLeft.toFloat(), padTop.toFloat())
makeLayout().draw(this)
}
}
}
関連
-
[解決済み] Androidのソフトキーボードをプログラムで閉じる/隠すにはどうすればよいですか?
-
[解決済み] Androidでアクティビティ起動時にEditTextにフォーカスが当たらないようにする方法
-
[解決済み] Androidの「コンテキスト」とは何ですか?
-
[解決済み] AndroidでPythonを実行する方法はありますか?
-
[解決済み] AndroidのListViewで画像を遅延ロードする方法
-
[解決済み] EclipseのAndroidプラグインで "Debug certificate expired "エラーが発生する。
-
[解決済み] クリック可能なラベルを持つチェックボックスを作成するには?
-
[解決済み】Android UserManager.isUserAGoat()の正しい使用例?)
-
[解決済み] 純正CPU使用率データの読み方
-
[解決済み] Android Studio - Lollipop, ADB, & Genymotionの問題。デバイスが表示されない "adb server is out of date... 殺し合い..." 重複] [重複
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] アプリ内課金テスト:android.test.purchased already owned
-
[解決済み] アンドロイドのスプラッシュスクリーンのサイズは、ldpi、mdpi、hdpi、xhdpiのディスプレイのためのものですか?- 例:1024X768ピクセル(ldpi)。
-
[解決済み] Receiver not registered exception error?
-
[解決済み] AndroidのimageviewがmaxWidthを無視する?
-
[解決済み] Android Studioで複数のデバイスでアプリを自動実行する
-
[解決済み] RelativeLayout は LinearLayout よりも高価ですか?
-
[解決済み] Genymotion、Mavericksで「Unable to load VirtualBox engine. VBoxは正しくセットアップされています。
-
[解決済み] Androidの縦長(回転)ラベルについて
-
[解決済み] android:fontFamily="sans-serif-light "と同等の機能をJavaコードで実現するには?
-
[解決済み] Android - logcat メッセージの最大長を設定する