ক্যানভাসে অ্যান্ড্রয়েড সেন্টার পাঠ্য


191

আমি নীচের কোডটি ব্যবহার করে একটি পাঠ্য প্রদর্শন করার চেষ্টা করছি। সমস্যাটি হচ্ছে পাঠ্যটি অনুভূমিকভাবে কেন্দ্রিক নয়। আমি যখন স্থানাঙ্কগুলি সেট করি তখন drawTextএটি এই অবস্থানে পাঠ্যের নীচে সেট করে। আমি পাঠ্যটি আঁকতে চাই যাতে পাঠ্যটি অনুভূমিকভাবে কেন্দ্রীভূত হয়।

আমার সমস্যাটি আরও প্রদর্শন করার জন্য এটি একটি ছবি:

স্ক্রিনশট

@Override
protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    super.onDraw(canvas);
    //canvas.drawRGB(2, 2, 200);
    Paint textPaint = new Paint();
    textPaint.setARGB(200, 254, 0, 0);
    textPaint.setTextAlign(Align.CENTER);
    textPaint.setTypeface(font);
    textPaint.setTextSize(300);
    canvas.drawText("Hello", canvas.getWidth()/2, canvas.getHeight()/2  , textPaint);
}

20
আমি আপনার অনড্র ইভেন্টে আপনার রঙের বিষয়টিকে ঘোষণা করব না declare প্রতিবার এটি পুনরায় চিত্রিত করা হলে এটি পুনরায় তৈরি করা হয়। এটিকে একটি বেসরকারী শ্রেণীর পরিবর্তনশীল করার কথা বিবেচনা করুন।
ক্রিস্টোফার রাথজেব

8
Mate! আপনার চিত্রের লিঙ্কটি এনএসএফডাব্লু উল্লেখ করুন! আমি বুদ্ধিমান হতে চাইছি না, তবে অফিসে আমার পর্দায় টপলেস মহিলার সাথে উপস্থিত হওয়ার দরকার নেই need
মাইকেল শ্যাপার

5
@ মিশেলশেপার দুঃখিত, আমি লিঙ্কটি আপডেট করেছি!
সেবাস্তিয়ান

23
@ সেবাস্তিয়ান আপনি এই লিঙ্কটি এখনও পেয়েছেন?
এস। লুকাস

@ এস.লুকাস হাহাহাহা
বিওটিজেআর।

উত্তর:


376

নিম্নলিখিত চেষ্টা করুন:

 int xPos = (canvas.getWidth() / 2);
 int yPos = (int) ((canvas.getHeight() / 2) - ((textPaint.descent() + textPaint.ascent()) / 2)) ; 
 //((textPaint.descent() + textPaint.ascent()) / 2) is the distance from the baseline to the center.

 canvas.drawText("Hello", xPos, yPos, textPaint);

10
দুর্দান্ত উত্তর। আমার জন্য আমি নীচের অবস্থানটি কেন্দ্রের অবস্থানের থেকে শুরু করার চেয়ে পাঠ্যটিকে অনুভূমিকভাবে পুরোপুরি কেন্দ্র করার জন্য প্রয়োজন হিসাবে ব্যবহার করেছি: int xPos = (প্রস্থ - টেক্সটপেইন্ট.টেক্সটসাইজ * ম্যাথ.এবস (_টেক্সট.লেন্থ / 2)) / 2; এটি সম্পাদন করার আরও ভাল উপায় আছে কিনা তা নিশ্চিত নন।
paj7777

এবং সম্ভবত সর্বোত্তম কাস্টিং _ টেক্সট L একটি ফ্লোটে দৈর্ঘ্য কারণ এটি স্পষ্টতই বিজোড় পাঠ্যের দৈর্ঘ্যের জন্য কাজ করবে না।
paj7777

61
paj7777, যদি আপনি টেক্সটপেইন্ট.সেটটেক্সটএলাইন (Align.CENTER) সেট করেন তবে এটি প্রয়োজনীয় নয়;
কোস্তি মুরারু

@ paj7777 এটি কেবল স্থির-প্রস্থের ফন্টগুলির জন্যই কাজ করতে পারে। এছাড়াও, আপনার একটি ভাসমান কাস্ট করার প্রয়োজন নেই ; যদি আপনি একটি ভাসা দিয়ে বিভক্ত করেন, ফলাফলটি ভাসমান হবে। যেমন float halfLength = text.length() / 2f;এটিকে প্রকার প্রচার বলে
মাইকেল শ্যাপার

2
আমি নীচের আমার উত্তরের সাথে কেন্দ্রের পাঠ্যের সাথে এই পদ্ধতির (= কেন্দ্রের সাথে Paint.descent()এবং Paint.ascent()) তুলনা Paint.getTextBounds()করেছি। Paint.descent()এবং Paint.ascent()প্রকৃত পাঠ্যটি আমলে নেবেন না। (আপনি নীচের আমার পোস্টের স্ক্রিনশটটিতে এই অপূর্ণতাটি চিনতে পারেন)) এজন্য আমি এই পদ্ধতির বিরুদ্ধে সুপারিশ করব। সাথে Paint.getTextBounds()যোগাযোগটি আরও সঠিকভাবে কাজ করছে বলে মনে হচ্ছে।
andreas1724

215

পেইন্ট.টেক্সটবাউন্ডস () সহ কেন্দ্র :

এখানে চিত্র বর্ণনা লিখুন

private Rect r = new Rect();

private void drawCenter(Canvas canvas, Paint paint, String text) {
    canvas.getClipBounds(r);
    int cHeight = r.height();
    int cWidth = r.width();
    paint.setTextAlign(Paint.Align.LEFT);
    paint.getTextBounds(text, 0, text.length(), r);
    float x = cWidth / 2f - r.width() / 2f - r.left;
    float y = cHeight / 2f + r.height() / 2f - r.bottom;
    canvas.drawText(text, x, y, paint);
}
  • পেইন্ট.এলাইন.সেন্টার মানে এই নয় যে পাঠ্যের রেফারেন্স পয়েন্টটি উল্লম্বভাবে কেন্দ্রিক। রেফারেন্স পয়েন্টটি সর্বদা বেসলাইনে থাকে। সুতরাং, কেন পেইন্ট.আলাইন.এলএফটি ব্যবহার করবেন না ? আপনাকে যাইহোক রেফারেন্স পয়েন্ট গণনা করতে হবে।

  • পেইন্ট.ডেসেন্ট () এর অসুবিধা রয়েছে, এটি আসল পাঠটিকে বিবেচনা করে না। পেইন্ট.ডেসেন্ট () পাঠ্যের উত্থানের সাথে অক্ষর রয়েছে কিনা তা নির্বিশেষে একই মানটি পুনরুদ্ধার করে। এজন্য আমি পরিবর্তে আর.বটম ব্যবহার করি

  • ক্যানভাস.জেটহাইট () এপিআই <16 এর সাথে আমার কিছু সমস্যা হয়েছে That's এজন্য আমি এর পরিবর্তে ক্যানভাস.সেটলিপবাউন্ডস (রেক্ট) ব্যবহার করি। (না ব্যবহার করবেন Canvas.getClipBounds ()। GetHeight () যেমন একটি জন্য মেমরি বরাদ্দ আয়তক্ষেত্র ।)

  • পারফরম্যান্সের কারণে, ওনড্র () ব্যবহার করার আগে আপনাকে অবজেক্টগুলি বরাদ্দ করা উচিত । হিসাবে drawCenter () মধ্যে বলা হবে onDraw () বস্তুর আয়তক্ষেত্র R এখানে একটি ক্ষেত্র হিসেবে preallocated করা হয়।


আমি দুটি শীর্ষ উত্তরের কোডটি আমার নিজস্ব কোডে (আগস্ট 2015) রাখার চেষ্টা করেছি এবং ফলাফলগুলির তুলনা করার জন্য একটি স্ক্রিনশট তৈরি করেছি:

পাঠ্য তিনটি সংস্করণ কেন্দ্রিক

পাঠ্যটি লাল ভরাট আয়তক্ষেত্রের মাঝখানে হওয়া উচিত। আমার কোডটি সাদা পাঠ্য উত্পাদন করে, অন্য দুটি কোড সম্পূর্ণ ধূসর পাঠ্য উত্পাদন করে (সেগুলি আসলে একই, ওভারল্যাপিং)) ধূসর পাঠ্যটি কিছুটা কম এবং ডানদিকে দুটি বেশি।

এইভাবে আমি পরীক্ষাটি করেছিলাম:

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

class MyView extends View {

    private static String LABEL = "long";
    private static float TEXT_HEIGHT_RATIO = 0.82f;

    private FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(0, 0);
    private Rect r = new Rect();
    private Paint paint = new Paint();
    private Paint rectPaint = new Paint();

    public MyView(Context context) {
        super(context);
    }

    private void drawTextBounds(Canvas canvas, Rect rect, int x, int y) {
        rectPaint.setColor(Color.rgb(0, 0, 0));
        rectPaint.setStyle(Paint.Style.STROKE);
        rectPaint.setStrokeWidth(3f);
        rect.offset(x, y);
        canvas.drawRect(rect, rectPaint);
    }

    // andreas1724 (white color):
    private void draw1(Canvas canvas, Paint paint, String text) {
        paint.setTextAlign(Paint.Align.LEFT);
        paint.setColor(Color.rgb(255, 255, 255));
        canvas.getClipBounds(r);
        int cHeight = r.height();
        int cWidth = r.width();
        paint.getTextBounds(text, 0, text.length(), r);
        float x = cWidth / 2f - r.width() / 2f - r.left;
        float y = cHeight / 2f + r.height() / 2f - r.bottom;
        canvas.drawText(text, x, y, paint);
        drawTextBounds(canvas, r, (int) x, (int) y);
    }

    // Arun George (light green color):
    private void draw2(Canvas canvas, Paint textPaint, String text) {
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setColor(Color.argb(100, 0, 255, 0));
        int xPos = (canvas.getWidth() / 2);
        int yPos = (int) ((canvas.getHeight() / 2) - ((textPaint.descent() + textPaint.ascent()) / 2));
        canvas.drawText(text, xPos, yPos, textPaint);
    }

    // VinceStyling (light blue color):
    private void draw3(Canvas yourCanvas, Paint mPaint, String pageTitle) {
        mPaint.setTextAlign(Paint.Align.LEFT);
        mPaint.setColor(Color.argb(100, 0, 0, 255));
        r = yourCanvas.getClipBounds();
        RectF bounds = new RectF(r);
        bounds.right = mPaint.measureText(pageTitle, 0, pageTitle.length());
        bounds.bottom = mPaint.descent() - mPaint.ascent();
        bounds.left += (r.width() - bounds.right) / 2.0f;
        bounds.top += (r.height() - bounds.bottom) / 2.0f;
        yourCanvas.drawText(pageTitle, bounds.left, bounds.top - mPaint.ascent(), mPaint);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        int margin = 10;
        int width = w - 2 * margin;
        int height = h - 2 * margin;
        params.width = width;
        params.height = height;
        params.leftMargin = margin;
        params.topMargin = margin;
        setLayoutParams(params);
        paint.setTextSize(height * TEXT_HEIGHT_RATIO);
        paint.setAntiAlias(true);
        paint.setTypeface(Typeface.create(Typeface.SERIF, Typeface.BOLD_ITALIC));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.rgb(255, 0, 0));
        draw1(canvas, paint, LABEL);
        draw2(canvas, paint, LABEL);
        draw3(canvas, paint, LABEL);
    }
}

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        FrameLayout container = new FrameLayout(this);
        container.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT));
        container.addView(new MyView(this));
        setContentView(container);
    }
}

1
আপনাকে অনেক ধন্যবাদ .. আপনার যুক্তি আমাকে সত্যই অনেক সাহায্য করেছে।
সুজয় ইউএন

আপনাকে অনেক ধন্যবাদ .. আপনার যুক্তি আমাকে সত্যই অনেক সাহায্য করেছে!
লিউয়েনবিন_না

এটিই কেবলমাত্র উত্তর যা পাঠ্যটিকে সত্যই কেন্দ্র করে।
জোয়ারি

63

উল্লম্বভাবে সারিবদ্ধ করা কঠিন কারণ পাঠ্য উত্থান এবং উত্থান ঘটেছিল, প্রচুর লোকেরা টেক্সটউইথ এবং টেক্সটহাইটটি পুনরুদ্ধার করতে পেইন্ট.সেজটেক্সটবাউন্ডস () ব্যবহার করেছেন, তবে এটি পাঠ্য কেন্দ্রটি খুব বেশি তৈরি করে না। এখানে আমরা টেক্সটউইথ গণনা করার জন্য পেইন্ট.মিজারটেক্সট () ব্যবহার করতে পারি, আমরা যে টেক্সটহাইটটি কেবল উত্সাহ এবং উত্থানের সাহায্যে বিয়োগফল করি, তারপরে আমরা সর্বাধিক পদ্ধতির টেক্সট সাইজ পেয়েছি, নিম্নলিখিত কাজ একে অপরের পক্ষে মোটামুটি সহজ।

// the Paint instance(should be assign as a field of class).
Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setTextSize(getResources().getDimension(R.dimen.btn_textsize));

// the display area.
Rect areaRect = new Rect(0, 0, 240, 60);

// draw the background style (pure color or image)
mPaint.setColor(Color.BLACK);
yourCanvas.drawRect(areaRect, mPaint);

String pageTitle = "文字小说";

RectF bounds = new RectF(areaRect);
// measure text width
bounds.right = mPaint.measureText(pageTitle, 0, pageTitle.length());
// measure text height
bounds.bottom = mPaint.descent() - mPaint.ascent();

bounds.left += (areaRect.width() - bounds.right) / 2.0f;
bounds.top += (areaRect.height() - bounds.bottom) / 2.0f;

mPaint.setColor(Color.WHITE);
yourCanvas.drawText(pageTitle, bounds.left, bounds.top - mPaint.ascent(), mPaint);

কোড দ্বারা স্ক্রিন শট

উপায় দ্বারা, আমরা অত্যন্ত ব্যবহার সুপারিশ RectF বদলে আয়তক্ষেত্র , কারণ অবস্থানের আরো সঠিক মান প্রয়োজন আমার অভিজ্ঞতা, RectF শীর্ষ & নীচে বিচ্যুতি xhdpi ডিভাইসে মাত্র এক পিক্সেল সম্পন্ন হলে, আয়তক্ষেত্র আরো দুটি হবে।


যেমনটি লেখা হয়েছে, var "পেইন্ট" বিভ্রান্তিকর। এটি কীভাবে বরাদ্দ করা হয়? এটি কীভাবে বাউন্ডস.বটমের জন্য পাঠ্যের উত্থান এবং উত্থানটি জানতে পারে?
রাউন্ডস্প্যারো হিলিটেক্স

1
হ্যাঁ, আমি এর জন্য আমার উত্তরটি অনুকূলিত করেছি, দয়া করে একবার দেখুন।
ভিন্স স্টাইলিং

আমার মূল্যবান সময় বাঁচানোর জন্য ধন্যবাদ))
অ্যান্ড্রে

16

আপনার কোডটি পাঠ্যটির বেসলাইনটির কেন্দ্রবিন্দুতে, ভিউটির কেন্দ্রস্থলে আঁকছে। অর্ডার কিছু পয়েন্ট x, y এ টেক্সট কেন্দ্রে গেলে আপনি পাঠ্য কেন্দ্রে গণনা করে এবং রাখতে হবে যে সময়ে।

এই পদ্ধতিটি x, y পয়েন্টকে কেন্দ্র করে পাঠ্য আঁকবে। আপনি যদি এটিকে আপনার দর্শনের কেন্দ্রে পাস করেন তবে এটি কেন্দ্রিক পাঠ্যটি আঁকবে।

private void drawTextCentered(String text, int x, int y, Paint paint, Canvas canvas) {
    int xPos = x - (int)(paint.measureText(text)/2);
    int yPos = (int) (y - ((textPaint.descent() + textPaint.ascent()) / 2)) ;

    canvas.drawText(text, xPos, yPos, textPaint);
}

@ মার্সিও গ্রানজোটো এর android.graphics.Paintপাঠ্যটি আঁকতে ব্যবহৃত হচ্ছে
উইলিয়াম রিড

4

আমি দেখতে পেয়েছি যে পাঠ্যকে কেন্দ্র করে রাখার সর্বোত্তম সমাধানটি নিম্নরূপ:

textPaint.setTextAlign(Paint.Align.CENTER);
//textPaint is the Paint object being used to draw the text (it must be initialized beforehand)
float textY=center.y;
float textX=center.x; 
// in this case, center.x and center.y represent the coordinates of the center of the rectangle in which the text is being placed
canvas.drawText(text,textX,textY,textPaint);    `

এটিকে দেখতে হুবহু দেখায়, প্রশ্নকারী পাঠ্যটিকে কেন্দ্র করে দেখার চেষ্টা করেছিল। পাঠ্যটি উল্লম্বভাবে কেন্দ্রীভূত হবে না কারণ পেইন্ট.এলাইন.সেন্টার অর্থ এই নয় যে, পাঠ্যের রেফারেন্স পয়েন্টটি উল্লম্বভাবে কেন্দ্রিক।
andreas1724

3

: ব্যবহার করার জন্য আমার জন্য কাজ করে textPaint.textAlign = Paint.Align.CENTER সঙ্গে textPaint.getTextBounds

private fun drawNumber(i: Int, canvas: Canvas, translate: Float) {
            val text = "$i"
            textPaint.textAlign = Paint.Align.CENTER
            textPaint.getTextBounds(text, 0, text.length, textBound)

            canvas.drawText(
                    "$i",
                    translate + circleRadius,
                    (height / 2 + textBound.height() / 2).toFloat(),
                    textPaint
            )
        }

ফলাফল:

এখানে চিত্র বর্ণনা লিখুন


1

আমি এটি সহজ করার জন্য একটি পদ্ধতি তৈরি করেছি:

    public static void drawCenterText(String text, RectF rectF, Canvas canvas, Paint paint) {
    Paint.Align align = paint.getTextAlign();
    float x;
    float y;
    //x
    if (align == Paint.Align.LEFT) {
        x = rectF.centerX() - paint.measureText(text) / 2;
    } else if (align == Paint.Align.CENTER) {
        x = rectF.centerX();
    } else {
        x = rectF.centerX() + paint.measureText(text) / 2;
    }
    //y
    metrics = paint.getFontMetrics();
    float acent = Math.abs(metrics.ascent);
    float descent = Math.abs(metrics.descent);
    y = rectF.centerY() + (acent - descent) / 2f;
    canvas.drawText(text, x, y, paint);

    Log.e("ghui", "top:" + metrics.top + ",ascent:" + metrics.ascent
            + ",dscent:" + metrics.descent + ",leading:" + metrics.leading + ",bottom" + metrics.bottom);
}

রেকটিএফ হল এমন অঞ্চল যা আপনি পাঠ্যটি আঁকতে চান, এটি। বিস্তারিত


1

যদি আমরা স্ট্যাটিক লেআউটটি ব্যবহার করি

mStaticLayout = new StaticLayout(mText, mTextPaint, mTextWidth,
                Layout.Alignment.ALIGN_CENTER, 1.0f, 0, true);

লেআউট.এলাইনমেন্ট.এলআইজিএন_সেন্টার এটি কৌশলটি করবে। স্ট্যাটিক লেআউট এছাড়াও অন্যান্য অনেক সুবিধা পেয়েছে।

তথ্যসূত্র: অ্যান্ড্রয়েড ডকুমেন্টেশন


1

এটি আমার পক্ষে কাজ করেছে:

 paint.setTextAlign(Paint.Align.CENTER);
        int xPos = (newWidth / 2);
        int yPos = (newHeight / 2);
        canvas.drawText("Hello", xPos, yPos, paint);

কারও যদি কোনও সমস্যা মনে হয় তবে দয়া করে আমাকে জানান


এটি কেন্দ্র বিন্দু থেকে পাঠ্য লেখা শুরু করবে তবে পুরো পাঠ্যটি কেন্দ্রে থাকবে না
এম শাবান আলী

0

আমার ক্ষেত্রে, আমাকে পাঠ্যটি ক্যানভাসের মাঝখানে রাখতে হয়নি, তবে একটি চাকাতে যা ঘুরছে। যদিও আমাকে সফল করতে এই কোডটি ব্যবহার করতে হয়েছিল:

fun getTextRect(textSize: Float, textPaint: TextPaint, string: String) : PointF {
    val rect = RectF(left, top, right, bottom)
    val rectHeight = Rect()
    val cx = rect.centerX()
    val cy = rect.centerY()

    textPaint.getTextBounds(string, 0, string.length, rectHeight)
    val y = cy + rectHeight.height()/2
    val x = cx - textPaint.measureText(string)/2

    return PointF(x, y)
}

তারপরে আমি ভিউ ক্লাস থেকে এই পদ্ধতিটি কল করি:

private fun drawText(canvas: Canvas, paint: TextPaint, text: String, string: String) {
    val pointF = getTextRect(paint.textSize, textPaint, string)
    canvas.drawText(text, pointF!!.x, pointF.y, paint)
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.