سؤال

أي طريقة مباشرة إلى الأمام لقياس ارتفاع النص؟ الطريقة التي أفعلها الآن هي استخدام الطلاء measureText() للحصول على العرض ، ثم عن طريق التجربة والخطأ إيجاد قيمة للحصول على ارتفاع تقريبي. لقد كنت أيضًا أتعامل مع FontMetrics, ، ولكن كل هذه تبدو مثل الأساليب التقريبية التي تمتص.

أحاول توسيع نطاق الأشياء لقرارات مختلفة. يمكنني القيام بذلك ، لكنني انتهى بي الأمر برمز مطوّل بشكل لا يصدق مع الكثير من الحسابات لتحديد الأحجام النسبية. أنا أكره ذلك! حتما توجد طريقة افضل.

هل كانت مفيدة؟

المحلول

ماذا عن paint.getTextBounds () (طريقة الكائن)

نصائح أخرى

هناك طرق مختلفة لقياس الارتفاع اعتمادًا على ما تحتاجه.

getTextBounds

إذا كنت تفعل شيئًا مثل توسيط كمية صغيرة من النص الثابت ، فربما تريد getTextBounds. يمكنك الحصول على المستطيل المحيط مثل هذا

Rect bounds = new Rect();
mTextPaint.getTextBounds(mText, 0, mText.length(), bounds);
int height = bounds.height();

كما ترون للصور التالية ، ستعطي سلاسل مختلفة ارتفاعات مختلفة (كما هو موضح باللون الأحمر).

enter image description here

يمكن أن تكون هذه المرتفعات المختلفة عيبًا في بعض المواقف عندما تحتاج فقط إلى ارتفاع ثابت بغض النظر عن النص. انظر القسم التالي.

Paint.FontMetrics

يمكنك حساب قضاء خط الخط من مقاييس الخط. الارتفاع هو نفسه دائمًا لأنه يتم الحصول عليه من الخط ، وليس أي سلسلة نصية معينة.

Paint.FontMetrics fm = mTextPaint.getFontMetrics();
float height = fm.descent - fm.ascent;

خط الأساس هو الخط الذي يجلس فيه النص. يكون النسب عمومًا هو الأبعد الذي ستذهب إليه حرف تحت الخط والصعود عمومًا هو الأبعد الذي سيذهب إليه حرف فوق الخط. للحصول على الارتفاع ، يجب عليك طرح الصعود لأنها قيمة سالبة. (خط الأساس هو y=0 و y descreases فوق الشاشة.)

انظر إلى الصورة التالية. مرتفعات كل من السلاسل 234.375.

enter image description here

إذا كنت تريد ارتفاع الخط بدلاً من ارتفاع النص ، فيمكنك القيام بما يلي:

float height = fm.bottom - fm.top + fm.leading; // 265.4297

هذه هي bottom و top من الخط. عادة ما يكون الصفر (التباعد المتداخل) صفرًا ، ولكن يجب عليك إضافته على أي حال.

الصور أعلاه تأتي من هذا المشروع. يمكنك اللعب معها لترى كيف تعمل مقاييس الخط.

StaticLayout

لقياس ارتفاع النص متعدد الخطوط ، يجب عليك استخدام أ StaticLayout. تحدثت عن ذلك ببعض التفصيل في هذا الجواب, ، لكن الطريقة الأساسية للحصول على هذا الارتفاع مثل هذا:

String text = "This is some text. This is some text. This is some text. This is some text. This is some text. This is some text.";

TextPaint myTextPaint = new TextPaint();
myTextPaint.setAntiAlias(true);
myTextPaint.setTextSize(16 * getResources().getDisplayMetrics().density);
myTextPaint.setColor(0xFF000000);

int width = 200;
Layout.Alignment alignment = Layout.Alignment.ALIGN_NORMAL;
float spacingMultiplier = 1;
float spacingAddition = 0;
boolean includePadding = false;

StaticLayout myStaticLayout = new StaticLayout(text, myTextPaint, width, alignment, spacingMultiplier, spacingAddition, includePadding);

float height = myStaticLayout.getHeight(); 

إجابة @Bramp صحيحة - جزئيًا ، من حيث أنه لا يذكر أن الحدود المحسوبة ستكون الحد الأدنى للمستطيل الذي يحتوي على النص بالكامل مع إحداثيات البدء الضمنية من 0 ، 0.

هذا يعني أن ارتفاع ، على سبيل المثال "PY" سيكون مختلفًا عن ارتفاع "PY" أو "Hi" أو "Oi" أو "AW" لأن البكسل يتطلب ارتفاعات مختلفة.

هذا بأي حال من الأحوال يعادل FontMetrics في Java الكلاسيكية.

في حين أن عرض النص ليس الكثير من الألم ، إلا أن الارتفاع.

على وجه الخصوص ، إذا كنت بحاجة إلى محاذاة النص الرأسي ، فحاول الحصول على حدود النص "A" (بدون عروض أسعار) ، بدلاً من استخدام النص الذي تنوي رسمه. يعمل لدي...

هذا ما أعنيه:

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG);

paint.setStyle(Paint.Style.FILL);
paint.setColor(color);
paint.setTextAlign(Paint.Align.CENTER);
paint.setTextSize(textSize);

Rect bounds = new Rect();
paint.getTextBounds("a", 0, 1, bounds);

buffer.drawText(this.myText, canvasWidth >> 1, (canvasHeight + bounds.height()) >> 1, paint);
// remember x >> 1 is equivalent to x / 2, but works much much faster

يعني المركز الرأسي المحاذاة النص رأسياً محاذاة المستطيل المحيط - وهو مختلف للنصوص المختلفة (CAPS ، الحروف الطويلة وما إلى ذلك). لكن ما نريد فعله بالفعل هو محاذاة خطوط الأساس من النصوص المقدمة ، بحيث لم تظهر مرتفعة أو مخطوة. لذلك ، طالما أننا نعرف مركز أصغر حرف ("A" على سبيل المثال) يمكننا بعد ذلك إعادة استخدام محاذاة لبقية النصوص. سيؤدي هذا إلى محاذاة جميع النصوص بالإضافة إلى محاذاة خط الأساس.

الارتفاع هو حجم النص الذي حددته على متغير الطلاء.

طريقة أخرى لمعرفة الارتفاع

mPaint.getTextSize();

يمكنك استخدام android.text.StaticLayout الفصل لتحديد الحدود المطلوبة ثم الاتصال getHeight(). يمكنك رسم النص (الموجود في التصميم) عن طريق الاتصال به draw(Canvas) طريقة.

يمكنك ببساطة الحصول على حجم النص لكائن الطلاء باستخدام طريقة getTextsize (). فمثلا:

Paint mTextPaint = new Paint (Paint.ANTI_ALIAS_FLAG);
//use densityMultiplier to take into account different pixel densities
final float densityMultiplier = getContext().getResources()
            .getDisplayMetrics().density;  
mTextPaint.setTextSize(24.0f*densityMultiplier);

//...

float size = mTextPaint.getTextSize();

عليك أن تستعمل Rect.width() و Rect.Height() التي عادت من getTextBounds() في حين أن. هذا يناسبني.

إذا كان أي شخص لا يزال لديه مشكلة ، فهذا هو الكود الخاص بي.

لدي طريقة عرض مخصصة مربعة (العرض = الارتفاع) وأريد تعيين حرف لها. onDraw() يوضح كيفية الحصول على ارتفاع الشخصية ، على الرغم من أنني لا أستخدمه. سيتم عرض الشخصية في منتصف الرؤية.

public class SideBarPointer extends View {

    private static final String TAG = "SideBarPointer";

    private Context context;
    private String label = "";
    private int width;
    private int height;

    public SideBarPointer(Context context) {
        super(context);
        this.context = context;
        init();
    }

    public SideBarPointer(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    public SideBarPointer(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
        init();
    }

    private void init() {
//        setBackgroundColor(0x64FF0000);
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        height = this.getMeasuredHeight();
        width = this.getMeasuredWidth();

        setMeasuredDimension(width, width);
    }

    protected void onDraw(Canvas canvas) {
        float mDensity = context.getResources().getDisplayMetrics().density;
        float mScaledDensity = context.getResources().getDisplayMetrics().scaledDensity;

        Paint previewPaint = new Paint();
        previewPaint.setColor(0x0C2727);
        previewPaint.setAlpha(200);
        previewPaint.setAntiAlias(true);

        Paint previewTextPaint = new Paint();
        previewTextPaint.setColor(Color.WHITE);
        previewTextPaint.setAntiAlias(true);
        previewTextPaint.setTextSize(90 * mScaledDensity);
        previewTextPaint.setShadowLayer(5, 1, 2, Color.argb(255, 87, 87, 87));

        float previewTextWidth = previewTextPaint.measureText(label);
//        float previewTextHeight = previewTextPaint.descent() - previewTextPaint.ascent();
        RectF previewRect = new RectF(0, 0, width, width);

        canvas.drawRoundRect(previewRect, 5 * mDensity, 5 * mDensity, previewPaint);
        canvas.drawText(label, (width - previewTextWidth)/2, previewRect.top - previewTextPaint.ascent(), previewTextPaint);

        super.onDraw(canvas);
    }

    public void setLabel(String label) {
        this.label = label;
        Log.e(TAG, "Label: " + label);

        this.invalidate();
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top