如何正确地将自定义视图添加到 activity

How do I properly add a custom view to an activity

我正在尝试构建自定义视图,但由于某种原因它根本没有显示。

为了避免您阅读这两个构造函数,我在调用 View 构造函数时不带 attr 参数,因为它们应该从布局文件中获取。未从此处获取的任何值都在视图 class 本身中设置。

我的观点class:

package mrl233.campustour.AugmentedReality;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.hardware.SensorManager;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;

import org.w3c.dom.Text;

import java.util.ArrayList;
import java.util.List;

import mrl233.campustour.R;

/**
 * TODO: document your custom view class.
 */
public class CameraOverlay extends View {

    private float mAzimuth;
    private float mPitch;
    private float mRoll;
    private String mTextString;
    private int mTextColor = Color.RED;
    private float mTextDimension = 80;
    private Drawable mTextDrawable;
    private float mTextSize = 29;
    private TextPaint mTextPaint;
    private float mTextHeight = 0;
    private float mTextWidth;


    public CameraOverlay(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.CameraOverlay,
                0, 0);

        try {
            mTextString = a.getString(R.styleable.CameraOverlay_exampleString);
            mAzimuth = a.getFloat(R.styleable.CameraOverlay_exampleFloat_X, 0);
            mPitch = a.getFloat(R.styleable.CameraOverlay_exampleFloat_Y, 0);
            mRoll = a.getFloat(R.styleable.CameraOverlay_exampleFloat_Z, 0);
        } finally {
            a.recycle();
        }
        init();
    }
    public CameraOverlay(Context con, float azimuth, float pitch, float roll) {
        this(con,null);
        this.mAzimuth = azimuth;
        this.mPitch = pitch;
        this.mRoll = roll;
        TypedArray a = con.getTheme().obtainStyledAttributes(
                null,
                R.styleable.CameraOverlay,
                0, 0);

        try {
            mTextString = a.getString(R.styleable.CameraOverlay_exampleString);
            mAzimuth = a.getFloat(R.styleable.CameraOverlay_exampleFloat_X, 0);
            mPitch = a.getFloat(R.styleable.CameraOverlay_exampleFloat_Y, 0);
            mRoll = a.getFloat(R.styleable.CameraOverlay_exampleFloat_Z, 0);

        } finally {
            a.recycle();
        }
        init();

    }
        @Override
    public void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            invalidate();
            int paddingLeft = getPaddingLeft();
            int paddingTop = getPaddingTop();
            int paddingRight = getPaddingRight();
            int paddingBottom = getPaddingBottom();

            int contentWidth = getWidth() - paddingLeft - paddingRight;
            int contentHeight = getHeight() - paddingTop - paddingBottom;

            canvas.drawText("wsfsefseefsfsef",
                    paddingLeft + (contentWidth - mTextWidth),
                    paddingTop + (contentHeight + mTextHeight)
                    ,mTextPaint);


    }

}

这是我的视图布局:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    android:id="@+id/overlay"  >

    <mrl233.campustour.AugmentedReality.CameraOverlay
        android:background="#ccc"
        android:layout_width="300dp" android:layout_height="300dp" android:paddingLeft="20dp"
        android:paddingBottom="40dp" custom:exampleDimension="24sp" custom:exampleColor="#33b5e5"
        custom:exampleString="Hello, CameraOverlay"
        custom:exampleFloat_X="0.1"
        custom:exampleFloat_Y="0.5"
        custom:exampleFloat_Z="1"/>

</FrameLayout>

我正在将此视图添加到具有自己视图的 activity。这是 Activity class 的 onCreate 方法,这是我尝试添加视图的地方。

 @Override
    @SuppressWarnings("deprecation")
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_augment);

        preview = (FrameLayout) findViewById(R.id.camera_preview);
        mPreview = new CameraPreview(this, camera);
        mCameraOverlay = new CameraOverlay(this, 0, 0, 0);

        preview.addView(mPreview);
        preview.addView(mCameraOverlay);
        preview.bringChildToFront(mCameraOverlay);

    }

这个activityclass的布局:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout      xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:showIn="@layout/augment"
        tools:context="mrl233.campustour.Activities.Augment">

        <FrameLayout
            android:id="@+id/camera_preview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="1">

        <!--<SurfaceView-->
            <!--android:layout_width="match_parent"-->
            <!--android:layout_height="match_parent"-->
            <!--android:id="@+id/surfaceView"/>-->

            <mrl233.campustour.AugmentedReality.CameraOverlay
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                />
        </FrameLayout>

    </RelativeLayout>

我在这里看到两个问题。您不应该在 onDraw 方法中调用 invalidate() ,因为它会导致视图重绘自身(无限循环)。其次 getWidth() 可能在那里为 0。您可能想从 onSizeChanged 方法

获得 canvas 宽度
private int width;
private int height;

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    width = w;
    height = h;
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    ...
    int contentWidth = width - paddingLeft - paddingRight;
    ...
}

尝试使用硬编码大小,因为目前您可能会在屏幕外绘制该文本或给它太小 space(这可能会帮助您找到问题所在)。 我能想到的最小的 customView 是:

public class CustomView extends View {
    private TextPaint paint;

    public CustomView(Context context) {
        super(context);
        paint = new TextPaint(Paint.LINEAR_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.RED);
        paint.setTextSize(20);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText("Hello", 20, 20, paint);
    }
}

并初始化它:

preview.addView(new CustomView(this));

还有一些更小的问题,但它可能会让你前进