Add custom view as a view of XML layout

23,531

Solution 1

I got it after 3 days of banging my head against the wall and by googling, stacOverflowing etc.

Actually, it was this stupid little thing...

My XML file where I defined the layout containing some usual android views (textView and buttons namely) and my custom view CounterClockView I had:

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

where I had to have added one more line!

<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>

I have no idea why this namespace line made such a huge difference, but it works great!

Now, I can update my custom view from my main activity on every onTick() of CountDownTimer()...

The following answer was very helpful: findViewById() returns null for custom component in layout XML, not for other components

Solution 2

Had the same issue, so I just implemented all the three constructors in the Java class of my custom view all the three constructors plus onDrow method and it worked like a charm. Try it.

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);


    }
}

The XML :

        <PackageName.CustomWorldWideView
            android:layout_width="56.00dp"
            android:layout_height="43dp"
            android:id="@+id/world_wide_grid_view_2"
            />
Share:
23,531
luigi7up
Author by

luigi7up

Shremos.com Co-founder &amp; CEO

Updated on October 15, 2020

Comments

  • luigi7up
    luigi7up over 3 years

    The scenario is the following:

    I have an activity RunTrainingWorkoutsView that uses XML layout _run_workout.xml_ with some labels that are updated by CountDownTimer. Works fine...

    Now, apart from labels that are updated every sec by onTick() callback method of CountDownTimer object I want to add a custom surface view to my _run_workout.xml layout_ that would draw some arcs updated by the same onTick() method every second...

    my run_workout.xml:

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

    My custom View extends 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);
    
    }
    

    My main class that extends activity is getting the reference to a custom surfaceView in the layout with the following code:

    //counterClockView  is declared outside of onCreate() as CounterClockView counterClockView;  
    
    //later in onCreate(){....
    counterClockView  = (CounterClockView) findViewById(R.id.counter_clock_surface);
    

    The problem is changing the value of member variables of customView object (counterClockView)

    counterClockView.counterArcAngle = 10;
    

    will crash the app...

    Also, from my main activity I would like to call invalidate() method to redo the surface view after changing the counterArcAngle value, but this causes app to crash too...

    Why can't create counterClockView object and reference it to a xml layout element of the same type and the change its appereance, invalidate it etc. ?

    EDIT 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