2

以下のコードはカスタム ビューです。円を描画し、スケールに従ってノッチを追加し、スケール テキストを追加します。これは、ビンテージ温度計の作成に関する Mind The Robot の優れたチュートリアルから派生したものです。http://mindtherobot.com/blog/272/android-custom-ui-making-a-vintage-thermometer/

このコードは、Jelly Bean 4.1.2 までのデバイスでは問題なく動作しますが、4.2 では機能しません。4.2 では、数字が円の周りに描かれなくなりましたが、画面全体に広がっているように見えます。Nexus 7 では 4.2 のアップデートが適用されるまでコードは正常に機能していたため、デバイスの問題ではありません。4.1.2 を実行している Nexus S と 4.2 を実行している Nexus 4 でテストしましたが、Nexus S では正常に動作しますが、Nexus 4 では動作しません。

残念ながら、新しいユーザーとしてスクリーンショットを投稿することはできません.

4.2 の変更ログを見ましたが、これが発生する原因は見当たりません。同様の問題をオンラインで探しましたが、これらはすべてハードウェア アクセラレーションに関係しているようです。マニフェストでハードウェア アクセラレーションを設定するさまざまな組み合わせを試しましたが、何も影響はありません。

これが発生する原因についての情報をいただければ幸いです。

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;

public class AneroidView extends View {


    // drawing tools
    private RectF rimRect;

    private RectF faceRect;

    private Paint scalePaint;
    private RectF scaleRect;

    private Paint backgroundPaint; 
    // end drawing tools

    private Bitmap background; // holds the cached static part

    private int totalNotches = 130;
    private int incrementPerLargeNotch = 10;
    private int incrementPerSmallNotch = 1;
    private float degreesPerNotch = 360.0f / totalNotches;  

    private int scaleCenterValue = 1000; // the one in the top center (12 o'clock)
    private int scaleMinValue = 935;
    private int scaleMaxValue = 1065;


    public AneroidView(Context context) {
        super(context);
        init(context, null);
    }

    public AneroidView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    public AneroidView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {

        rimRect = new RectF(0.1f, 0.1f, 0.9f, 0.9f);

        float rimSize = 0.02f;
        faceRect = new RectF();
        faceRect.set(rimRect.left + rimSize, rimRect.top + rimSize, 
                 rimRect.right - rimSize, rimRect.bottom - rimSize);        


        scalePaint = new Paint();
        scalePaint.setStyle(Paint.Style.STROKE);
        scalePaint.setColor(Color.rgb(49, 79, 79));
        scalePaint.setStrokeWidth(0.005f);
        scalePaint.setAntiAlias(true);

        scalePaint.setTextSize(0.045f);
        scalePaint.setTypeface(Typeface.SANS_SERIF);
        scalePaint.setTextScaleX(0.8f);
        scalePaint.setTextAlign(Paint.Align.CENTER);        

        // The scale rectangular is located .10 from the outer rim.
        float scalePosition = 0.10f;

        scaleRect = new RectF();
        scaleRect.set(faceRect.left + scalePosition, faceRect.top + scalePosition,
                      faceRect.right - scalePosition, faceRect.bottom - scalePosition);

            }

    private void drawScale(Canvas canvas) {
        // Draw a large notch every large increment, and a small
        // notch every small increment.

        canvas.drawOval(scaleRect, scalePaint);

        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        for (int i = 0; i < totalNotches; ++i) {
            float y1 = scaleRect.top;
            float y2 = y1 - 0.015f;
            float y3 = y1 - 0.025f;

            int value = notchToValue(i);

            if (i % (incrementPerLargeNotch/incrementPerSmallNotch) == 0) {
                if (value >= scaleMinValue && value <= scaleMaxValue) {
                    // draw a nick
                    canvas.drawLine(0.5f, y1, 0.5f, y3, scalePaint);

                    String valueString = Integer.toString(value);
                    // Draw the text 0.15 away from y3 which is the long nick.
                    canvas.drawText(valueString, 0.5f, y3 - 0.015f, scalePaint);
                }
            }
            else{
                if (value >= scaleMinValue && value <= scaleMaxValue) {
                    // draw a nick
                    canvas.drawLine(0.5f, y1, 0.5f, y2, scalePaint);
                }
            }

            canvas.rotate(degreesPerNotch, 0.5f, 0.5f);
        }
        canvas.restore();       
    }

    private int notchToValue(int value) {
        int rawValue = ((value < totalNotches / 2) ? value : (value - totalNotches)) * incrementPerSmallNotch;
        int shiftedValue = rawValue + scaleCenterValue;
        return shiftedValue;
    }


    private void drawBackground(Canvas canvas) {
        if (background != null)         
            canvas.drawBitmap(background, 0, 0, backgroundPaint);
    }

    @Override
    protected void onDraw(Canvas canvas) {      

        drawBackground(canvas);

        float scale = (float) getWidth();       
        canvas.save(Canvas.MATRIX_SAVE_FLAG);
        canvas.scale(scale, scale); 

        canvas.restore();

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        regenerateBackground();
    }

    private void regenerateBackground() {
        // free the old bitmap
        if (background != null) {
            background.recycle();
        }

        background = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
        Canvas backgroundCanvas = new Canvas(background);
        float scale = (float) getWidth();       
        backgroundCanvas.scale(scale, scale);

        drawScale(backgroundCanvas);
    }
}
4

3 に答える 3

4

追加scalePaint.setLinearText(true);

うまく機能しますが、テキストの間隔が悪く見える場合があります。

以下のスレッドを参照してください。

Nexus7上のAndroid4.2:canvas.drawText()が正しく機能しない

Android 4.2.1の間違った文字のカーニング(間隔)

于 2013-01-29T20:01:31.737 に答える
1

scalePaint.setLinearText(true)を使用してテキスト文字を1か所に描画し、textSize> 1.0fを設定してカーニングの問題を回避し、canvas.scale(float、float)を使用して問題を回避しました。フォントを適切なサイズにします。それは醜くて苦痛ですが、それは私にとってはうまくいきます。

于 2013-01-31T21:50:12.633 に答える
1

の別の回避策を次に示しkerning issueます。drawTextOnPath動作するので...

これを置き換えます:
//canvas.drawText("Smushed text.", 0.5f, 0.7F, myTextPaint);

これとともに:

private Path strightPath; <br>
strightPath = new Path(); <br>
strightPath.moveTo(0.1f, 0.5f);<br>
strightPath.lineTo(0.9f, 0.5f); <br>
canvas.drawTextOnPath("This text is not smushed together.", strightPath, 0.0f, 0.2f, myTextPaint);
于 2013-02-12T04:03:22.417 に答える