Добавить пользовательское представление как представление XML-макета - PullRequest
1 голос
/ 02 ноября 2011

Сценарий следующий:

У меня есть действие RunTrainingWorkoutsView , использующее макет XML _run_workout.xml_ с некоторыми метками, которые обновляются CountDownTimer . Работает нормально ...

Теперь, кроме меток, которые обновляются каждую секунду с помощью onTick () метода обратного вызова объекта CountDownTimer, я хочу добавить пользовательский вид поверхности в мой _run_workout.xml layout_, который бы рисовал некоторые дуги, обновленные тот же onTick () метод каждую секунду ...

my run_workout.xml:

<training.timer.CounterClockView 
    android:id="@+id/counter_clock_surface"
    android:layout_width="300dp" 
    android:layout_height="240dp">
</training.timer.CounterClockView>

Мой пользовательский вид расширяет SurfaceView

public class CounterClockView extends SurfaceView {

Paint paint = new Paint();
Paint paint2 = new Paint();

final RectF rect = new RectF();
final RectF rect2 = new RectF();

int counterArcAngle = 15;
//constructor
public CounterClockView(Context context, AttributeSet attributeSet) {
    super(context);

    //setting some paint properties...

    this.setBackgroundColor(Color.TRANSPARENT);

}

@Override
public void onDraw(Canvas canvas) {

    rect.set(50, 50, 150, 150);
    rect2.set(50, 50, 150, 150);

    this.layout(0, 0, 200, 200);

    canvas.drawArc(rect, -90, 360, false, paint);
    canvas.drawArc(rect2, -90, counterArcAngle, false, paint2);

}

Мой основной класс, который расширяет активность, получает ссылку на пользовательский surfaceView в макете со следующим кодом:

//counterClockView  is declared outside of onCreate() as CounterClockView counterClockView;  

//later in onCreate(){....
counterClockView  = (CounterClockView) findViewById(R.id.counter_clock_surface);

Проблема заключается в изменении значения переменных-членов объекта customView (counterClockView)

counterClockView.counterArcAngle = 10;

вылетит приложение ...

Кроме того, из моей основной деятельности я хотел бы вызвать метод invalidate () , чтобы повторить представление поверхности после изменения значения counterArcAngle , но это также приводит к сбою приложения. .

Почему нельзя создать counterClockView объект и связать его с элементом макета xml того же типа, изменить его внешний вид, сделать его недействительным и т. Д.?

РЕДАКТИРОВАТЬ LogCat :

threadid=1: thread exiting with uncaught exception (group=0x40015560)

ERROR/AndroidRuntime(487): FATAL EXCEPTION: main

ERROR/AndroidRuntime(487): java.lang.RuntimeException: Unable to start activity ComponentInfo{training.timer/training.timer.RunTrainingWorkoutsView}: java.lang.NullPointerException

ERROR/AndroidRuntime(487):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1647)
ERROR/AndroidRuntime(487):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663)
ERROR/AndroidRuntime(487):     at android.app.ActivityThread.access$1500(ActivityThread.java:117)
ERROR/AndroidRuntime(487):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:931)
ERROR/AndroidRuntime(487):     at android.os.Handler.dispatchMessage(Handler.java:99)
ERROR/AndroidRuntime(487):     at android.os.Looper.loop(Looper.java:123)

ERROR/AndroidRuntime(487):     at android.app.ActivityThread.main(ActivityThread.java:3683)
ERROR/AndroidRuntime(487):     at java.lang.reflect.Method.invokeNative(Native Method)
ERROR/AndroidRuntime(487):     at java.lang.reflect.Method.invoke(Method.java:507)
ERROR/AndroidRuntime(487):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
ERROR/AndroidRuntime(487):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
ERROR/AndroidRuntime(487):     at dalvik.system.NativeStart.main(Native Method)
ERROR/AndroidRuntime(487): Caused by: java.lang.NullPointerException
ERROR/AndroidRuntime(487):     at training.timer.RunTrainingWorkoutsView.onCreate(RunTrainingWorkoutsView.java:72)
ERROR/AndroidRuntime(487):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
ERROR/AndroidRuntime(487):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611)
ERROR/AndroidRuntime(487):     ... 11 more

Ответы [ 2 ]

6 голосов
/ 04 ноября 2011

Я получил его через 3 дня, когда бился головой об стену и гуглил, перебегал и т. Д.

На самом деле, это была эта глупая маленькая штука ...

Мой XML-файл, гдеЯ определил макет, содержащий некоторые обычные представления Android (а именно textView и кнопки) и мой собственный вид CounterClockView У меня было:

<training.timer.CounterClockView 
android:id="@+id/counter_clock_surface"
android:layout_width="300dp" 
android:layout_height="240dp">

, где я должен был добавитьеще одна строка!

<training.timer.CounterClockView 
    xmlns:android="http://schemas.android.com/apk/res/android"   !!!
    android:id="@+id/counter_clock_surface"
    android:layout_width="300dp" 
    android:layout_height="240dp">
</training.timer.CounterClockView>

Понятия не имею, почему эта строка пространства имен так сильно изменилась, но она прекрасно работает!

Теперь я могу обновить свой пользовательский вид из моей основной деятельностина каждый onTick () из CountDownTimer () ...

Следующий ответ был очень полезен: findViewById () возвращает значение NULL для пользовательского компонента в макетеXML, не для других компонентов

3 голосов
/ 14 октября 2015

У меня была та же проблема, поэтому я просто реализовал все три конструктора в классе Java моего пользовательского представления, все три конструктора плюс метод onDrow, и это сработало как прелесть. Попробуй.

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

public class CustomWorldWideView extends View {

    public CustomWorldWideView(Context context) {

        super(context);
    }

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

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

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //Some simple draw on the view...
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.parseColor("#FFA800"));


        Path path = new Path();

        path.moveTo(0, 0);
        path.lineTo(getWidth() / 2, 0);
        path.lineTo(getWidth(), getHeight()/2);
        path.lineTo(getWidth() / 2, getHeight());
        path.lineTo( 0, getHeight());
        path.lineTo( 0, 0);

        canvas.drawPath(path, paint);


    }
}

XML:

        <PackageName.CustomWorldWideView
            android:layout_width="56.00dp"
            android:layout_height="43dp"
            android:id="@+id/world_wide_grid_view_2"
            />
...