如何将动态自定义视图嵌入到xml布局中?

时间:2013-06-11 14:47:01

标签: android android-layout android-canvas android-view

我有一个纯粹用java代码创建的自定义视图。当我创建视图的实例并将内容视图设置为视图对象时,它工作正常。然而;当我将视图作为xml嵌入时,我的应用程序停止处理超时错误。

查看代码:

package com.example.dcubebluetooth;

import android.view.View;
import android.view.MotionEvent;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.Toast;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;

public class LEDView extends View{

    Paint background = new Paint();
    Paint white = new Paint();
    Paint red = new Paint();

    Bitmap grid;
    Canvas ledDrawer = new Canvas();

    boolean[][][] states = new boolean[4][4][4];

    int currentLayer = 0;

    Button l1;
    Button l2;
    Button l3;
    Button l4;

    public LEDView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initialize();
    }

    public void initialize(){
        /*
        l1 = (Button) findViewById(R.id.layer1);
        l1.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Toast.makeText(getContext(), "Test", Toast.LENGTH_LONG).show();
            }
        });
        l2 = (Button) findViewById(R.id.layer2);
        l3 = (Button) findViewById(R.id.layer3);
        l4 = (Button) findViewById(R.id.layer4);
        */
        setLayoutParams(new LayoutParams(400, 400));

        background.setARGB(255, 0, 0, 0);
        white.setARGB(255, 255, 255, 255);
        red.setARGB(255, 255, 0, 0);

        grid = Bitmap.createBitmap(400, 400, Config.RGB_565);
        ledDrawer.setBitmap(grid);
        //ledDrawer.drawPaint(background);

        for(int i=0; i<states.length; i++){
            for(int j=0; j<states[0].length; j++){
                for(int k=0; k<states[0][0].length; k++){
                    states[i][j][k] = false;
                }
            }
        }

        drawGrid(currentLayer);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(grid, 0, 0, null);
    }

    private void drawGrid(int layer) {
        //ledDrawer.drawPaint(background);

        for(int y=0; y<4; y++){
            for(int x=0; x<4; x++){
                Paint p = (states[layer][x][y] == true) ? red : white;
                ledDrawer.drawCircle((100*x)+50, (100*y)+50, 40, p);
            }
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) (event.getX())/100;
        int y = (int) (event.getY())/100;

        states[currentLayer][x][y] = !states[currentLayer][x][y];

        drawGrid(currentLayer);

        invalidate();

        return super.onTouchEvent(event);
    }

}

XML代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <com.example.dcubebluetooth.LEDView
        android:id="@+id/lEDView1"
        android:layout_width="400px"
        android:layout_height="400px"
        android:layout_alignParentTop="true" 
        android:layout_alignParentLeft="true"/>

<Button
        android:id="@+id/layer1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/lEDView1"
        android:layout_marginTop="50px"
        android:text="Layer1"
        android:textSize="12dp" />

    <Button
        android:id="@+id/layer2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/layer1"
        android:layout_toRightOf="@id/layer1"
        android:text="Layer2"
        android:textSize="12dp" />

    <Button
        android:id="@+id/layer3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/layer2"
        android:layout_toRightOf="@id/layer2"
        android:text="Layer3"
        android:textSize="12dp" />

    <Button
        android:id="@+id/layer4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@id/layer3"
        android:layout_toRightOf="@id/layer3"
        android:text="Layer4"
        android:textSize="12dp" />

</RelativeLayout>

我不能做logcat的正面或反面。创建实例或其他东西的一些问题。:

06-11 10:50:29.079: E/AndroidRuntime(19143): FATAL EXCEPTION: main
06-11 10:50:29.079: E/AndroidRuntime(19143): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.dcubebluetooth/com.example.dcubebluetooth.MainActivity}: android.view.InflateException: Binary XML file line #11: Error inflating class com.example.dcubebluetooth.LEDView
06-11 10:50:29.079: E/AndroidRuntime(19143):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1967)

最后,你会看到我试图评论除了基本部分之外的所有内容。我无法确定问题所在。

我必须在xml中使用它的原因是我可以轻松添加按钮。

1 个答案:

答案 0 :(得分:2)

Android正在调用您未定义的自定义视图的构造函数之一。 因此,您需要为自定义视图创建所有构造函数:

public LEDView(Context context) {
   super(context);
   initialize();
}
public LEDView(Context context, AttributeSet attrs) {
   super(context, attrs);
   initialize();
}
public LEDView(Context context, AttributeSet attrs, int defStyle) {
   super(context, attrs, defStyle);
   initialize();
}