【问题标题】:Android: Draw Custom TextView on CanvasAndroid:在 Canvas 上绘制自定义 TextView
【发布时间】:2015-09-10 17:58:54
【问题描述】:

我有以下 TextView

public class Cube extends TextView {

Context mContext;

Drawable background;//Hintergrund des Blocks
char mLetter;//Buchstabe des Blocks
int x, y;//Koordinaten des Blocks

@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
public Cube(Context context, char letter, int _x, int _y) {
    super(context);
    mContext = context;
    mLetter = letter;
    background = ContextCompat.getDrawable(getContext(), R.drawable.cube);
    x = _x;
    y = _y;
    this.setText("" + letter);
    if(android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN)
        this.setBackgroundDrawable(background);
    else
        this.setBackground(background);
}

public void drawCube(Canvas canvas){//how to draw now!? This is called from a separate thread in SurfaceView
}

}

如果我在 drawCube() 中调用以下函数:

    background.setBounds(x, y, x + 20, y + 20);
    background.draw(canvas);

它只是绘制 backgroundDrawable。但是我怎样才能用里面的文字/字母来画呢?它看起来像这样:(背景是画布,橙色和白色的是背景,“A”是字母/文本)

编辑:21.09 的代码 这是我的(缩短的)线程:

public class CanvasThread extends Thread {

private SurfaceHolder mSh;

private ArrayList<Cube> mCubes;

private Canvas mCanvas;
private Context mContext;
private boolean mRun = false;
private boolean mDown = false;
private boolean newCube = false;
public CanvasThread(SurfaceHolder sh, Context context){
    mSh = sh;
    mCubes = new ArrayList<>();
    mContext = context;
}

public void run(){
    while(mRun){
        mCanvas = null;

        try{
            mCanvas = mSh.lockCanvas(null);
            synchronized (mSh){
                mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
                newCube = true;
                for(int i = 0; i < mCubes.size(); i++){
                    if(mCubes.get(i).getSpeed() > 0)
                        newCube = false;
                    if(mDown) {
                        if (mCubes.get(i).moveDown(feld)) {
                            mDown = false;
                        }
                    }
                    //mCubes.get(i).invalidate();
                    //mCubes.get(i).requestLayout();
                    mCubes.get(i).draw(mCanvas);
                }
                if(newCube)
                    addCube();
            }
        } finally {
            if(mCanvas != null){
                mSh.unlockCanvasAndPost(mCanvas);
            }
        }
    }
}

public void addCube(){
    Random r = new Random();
    Cube cube = new Cube(mContext, mBuchstaben[r.nextInt(29)], r.nextInt(10), 0, mCanvas);
    mCubes.add(cube);
}

}

这是我使用画布/表面视图的(缩短的)片段:

public class KlassischFragment extends Fragment implements SurfaceHolder.Callback {

SurfaceHolder sh;
SurfaceView sv;

private CanvasThread thread;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_klassisch, container, false);
    sv = (SurfaceView) view.findViewById(R.id.surfaceView);
    sh = sv.getHolder();
    sh.addCallback(this);
    sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    return view;
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    thread = new CanvasThread(sh, getContext());
    thread.setRunnable(true);
    thread.start();
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    boolean retry = true;
    //thread.setRunnable(false);

    while(retry){
        try{
            thread.join();
            retry = false;
        } catch(InterruptedException ie){
            //Immer wieder versuchen
        }
        break;
    }
    thread = null;
}

}

【问题讨论】:

  • 你试过canvas.drawText()吗? developer.android.com/reference/android/graphics/…,浮动,浮动,android.graphics.Paint)
  • 为什么需要文本在drawable中?不知道有没有其他办法。
  • 你能上传一份关于你希望立方体看起来如何的信息吗?很难想象你想要它的样子
  • 那么为什么你需要它在一个drawable中呢?您可以在立方体顶部绘制文本(它是一个正方形)。
  • 然后在绘制文本时添加onDraw 调用。

标签: android textview android-canvas drawable


【解决方案1】:

这是一个关于如何在正方形顶部绘制文本的示例。一些值是硬编码的,但您应该能够使它们动态化。

public class Cube extends View {

    private final static String TEST_STRING = "ABC";
    private Paint mBackgroundPaint;
    private Paint mTextPaint;

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public Cube(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    public Cube(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    public Cube(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public Cube(Context context) {
        this(context, null, -1);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Just for demo purposes this should be calculated properly
        int desiredWidth = 100;
        int desiredHeight = 100;

        setMeasuredDimension(desiredWidth, desiredHeight);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int savedCount = canvas.save();
        drawRectangle(canvas);
        drawText(canvas);
        canvas.restoreToCount(savedCount);
    }

    private void init() {
        mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBackgroundPaint.setColor(Color.BLUE);
        mBackgroundPaint.setStyle(Paint.Style.FILL);

        mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        // This need to be adjusted based on the requirements that you have
        mTextPaint.setTextSize(20.0f);

    }

    private void drawRectangle(Canvas canvas) {
        canvas.drawRect(0, 0, getWidth(), getHeight(), mBackgroundPaint);
    }

    private void drawText(Canvas canvas) {
        Rect rect = new Rect();
        // For simplicity I am using a hardcoded string
        mTextPaint.getTextBounds(TEST_STRING, 0, 1, rect);
        int w = getWidth(), h = getHeight();
        float x = (w - rect.width()) / 2, y = ((h - rect.height()) / 2) + rect.height();
        canvas.drawText(TEST_STRING, 0, 1, x, y, mTextPaint);


    }
}

【讨论】:

  • 谢谢你这个作品(有一些变化)完美!唯一仍然存在的是,我必须通过调用 cube.draw(canvas); 手动调用 onDraw;
  • 你不应该那样做。 invalidate()requestLayout() 应该会自动为您执行此操作。
  • 这不起作用。它只是什么都没有显示。还是我必须先以任何方式将“立方体”添加到画布上?
  • 嗯,好的。您没有以将其添加到根布局(或通过 xml)的传统方式使用它。如果你不这样做,那么你必须自己画。
  • 好的,那我可以按照我现在的方式来做吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-02
  • 1970-01-01
相关资源
最近更新 更多