Ошибки при создании представления для пользовательского представления

Я создал класс Custom View, который берет путь, затем заполняет его белым цветом и окрашивает его край в красный цвет:

StrokeFill.java:

package com.kf.pathshape;
...

public class StrokeFill extends View{
private Path shapePath;

public StrokeFill(Context context, Path path) {
    super(context);
    this.shapePath = path;

    // TODO Auto-generated constructor stub
}

public StrokeFill(Context context, AttributeSet attrs, Path shapePath) {
    super(context, attrs);
    this.shapePath = shapePath;
}

protected void onDraw(Canvas canvas) {
    // TODO Auto-generated method stub
    //canvas.drawColor(Color.BLACK);
    super.onDraw(canvas);

    //Sets paints and draws the shapes
    Paint fillPaint = new Paint();
    fillPaint.setColor(android.graphics.Color.WHITE);
    fillPaint.setStyle(Paint.Style.FILL);
    fillPaint.setStrokeWidth(0);
    Paint strokePaint = new Paint();
    strokePaint.setColor(android.graphics.Color.RED);
    strokePaint.setStyle(Paint.Style.STROKE);
    strokePaint.setStrokeWidth(2);

    canvas.drawPath(shapePath, fillPaint);
    canvas.drawPath(shapePath, strokePaint);
}
}

Мой макет XML (main.xml) очень прост:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.kf.pathshape.StrokeFill
    android:id="@+id/pathshape"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />
</LinearLayout>

Мероприятия:

setContentView(R.layout.main);
shapeView = (StrokeFill) findViewById(R.id.pathshape);
shapeView = new StrokeFill(this, testpath);

testpath является допустимым путем. Это дает мне ошибки, даже если я закомментирую строки, определяющие «shapeView». Логкат:

07-11 01:50:17.150: E/AndroidRuntime(24321): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.kf.pathshape/com.kf.pathshape.PathshapeActivity}: android.view.InflateException: Binary XML file line #6: Error inflating class com.kf.pathshape.StrokeFill
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1651)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.app.ActivityThread.access$1500(ActivityThread.java:117)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.os.Handler.dispatchMessage(Handler.java:99)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.os.Looper.loop(Looper.java:130)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.app.ActivityThread.main(ActivityThread.java:3691)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at java.lang.reflect.Method.invokeNative(Native Method)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at java.lang.reflect.Method.invoke(Method.java:507)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:670)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at dalvik.system.NativeStart.main(Native Method)
07-11 01:50:17.150: E/AndroidRuntime(24321): Caused by: android.view.InflateException: Binary XML file line #6: Error inflating class com.kf.pathshape.StrokeFill
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.view.LayoutInflater.createView(LayoutInflater.java:508)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:570)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:623)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.view.LayoutInflater.inflate(LayoutInflater.java:408)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:234)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.app.Activity.setContentView(Activity.java:1679)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at com.kf.pathshape.PathshapeActivity.onCreate(PathshapeActivity.java:73)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1050)
07-11 01:50:17.150: E/AndroidRuntime(24321):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
07-11 01:50:17.150: E/AndroidRuntime(24321):    ... 11 more
07-11 01:50:17.150: E/AndroidRuntime(24321): Caused by: java.lang.NoSuchMethodException: StrokeFill(Context,AttributeSet)

Искал по форуму, но не нашел того, что мне нужно. Я уже определил конструктор, принимающий контекст и атрибуты. Что мне здесь не хватает?


person tangfucius    schedule 10.07.2012    source источник


Ответы (3)


Поскольку вы расширяете представление, вам необходимо реализовать 3 конструктора:

public class StrokeFill extends View{
    private Path mShapePath;

    public StrokeFill(Context context) {
        super(context);
        init();
    }

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

    public StrokeFill(Context context, AttributeSet attrs, int defstyle) {
        super(context, attrs, defstyle);
        init();
    }

    private void init(){
        //some code... or not =)
    }

    public void setPath(Path path){
        mShapePath = path;
    }
    /* rest of your code */
}

Затем в вашей деятельности:

shapeView = (StrokeFill) findViewById(R.id.pathshape);
shapeView.setPath(yourPath);

Надеюсь, это поможет вам

person AMerle    schedule 10.07.2012
comment
Должен ли я реализовать это в Activity? У меня нет ничего для AttributeSet. - person tangfucius; 10.07.2012
comment
@tangfucius, вам нужно реализовать эти конструкторы в своем пользовательском представлении. Отредактирую свой пост выше. - person AMerle; 10.07.2012
comment
Это делает это! Так что конструктор должен быть совершенно правильным... спасибо! - person tangfucius; 10.07.2012

нет необходимости создавать его снова

shapeView = new StrokeFill(this, testpath);

изменить вот так

setContentView(R.layout.main);
shapeView = (StrokeFill) findViewById(R.id.pathshape);
person RajaReddy PolamReddy    schedule 10.07.2012
comment
Но и shapeView, и testpath исходят из Activity, поэтому мне нужно как-то создать экземпляр shapeView. Кроме того, даже если я не определяю shapeView, setContentView уже выдает мне ошибку. Если у меня есть StrokeFill в XML, значит ли это, что его нужно создавать в onCreate? - person tangfucius; 10.07.2012

Когда вы создаете свое собственное представление из xml, Android вызывает конструктор StrokeFill(Context,AttributeSet). Вы должны создать этот конструктор, если хотите раздуть свое представление из xml. Вы также можете создать свое представление в коде, а затем удалить его из xml, в этом случае вам не нужен конструктор StrokeFill(Context,AttributeSet).

Например:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/myLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
</LinearLayout>

Мероприятия:

setContentView(R.layout.main);
LinearLayout v = (LinearLayout)findViewById(R.id.myLayout);
shapeView = new StrokeFill(this, testpath);
v.addView(shapeView);
person Leszek    schedule 10.07.2012
comment
Это работает, спасибо. Мне интересно, есть ли способ, с помощью которого я могу напрямую использовать StrokeFill в XML напрямую вместо LinearLayout, поскольку это больше похоже на обходной путь. - person tangfucius; 10.07.2012