Coova
Coova

Reputation: 1858

Removing a view from within its own view class

Here is the view class that I have created.

public class WorkoutView extends LinearLayout implements View.OnClickListener {


    public Spinner spinnerDifficulty, spinnerTime, spinnerMuscleGroup, spinnerSets, spinnerReps;
    public EditText etWorkoutName;
    public Button btnRemoveWorkout;

    String workoutName, muscleGroup, sets, reps;
    LayoutInflater inflater;
    Context mContext;
    ButtonPressInterface buttonPressCallback;

    public WorkoutView(Context context) {
        super(context);
        Log.e("WORKOUTVIEW", "1");
        mContext = context;

    }

    public WorkoutView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        Log.e("WORKOUTVIEW", "2");
    }

    public WorkoutView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        Log.e("WORKOUTVIEW", "3");
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        init();
    }

    public interface ButtonPressInterface {
        void buttonWasPressed();

    }

    public void init() {
        spinnerDifficulty = (Spinner) findViewById(R.id.spinnerDifficulty);
        spinnerReps = (Spinner) findViewById(R.id.spinnerReps);
        spinnerSets = (Spinner) findViewById(R.id.spinnerSets);
        spinnerMuscleGroup = (Spinner) findViewById(R.id.spinnerWorkoutGroup);
        spinnerTime = (Spinner) findViewById(R.id.spinnerTime);
        etWorkoutName = (EditText) findViewById(R.id.etWorkoutName);
        btnRemoveWorkout = (Button) findViewById(R.id.btnRemoveWorkout);
        btnRemoveWorkout.setOnClickListener(this);

        buttonPressCallback = (ButtonPressInterface) getContext();
    }

    public String getReps() {
        reps = spinnerReps.getSelectedItem().toString();
        return reps;
    }

    public String getWorkoutName() {
        workoutName = etWorkoutName.getText().toString().trim();
        return workoutName;
    }

    public String getMuscleGroup() {
        muscleGroup = spinnerMuscleGroup.getSelectedItem().toString();
        return muscleGroup;
    }

    public String getSets() {
        sets = spinnerSets.getSelectedItem().toString();
        return sets;
    }

    public SingleWorkout getAll() {
        //to be designed
        return null;
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btnRemoveWorkout:
                buttonPressCallback.buttonWasPressed();
                Log.e("DID THIS WORK?", "BUTTON PRESSED");
                break;
        }

    }
}

How can I remove this view when pressing the btnRemoveWorkout? Is there a way to implement an interface? This view is being added correctly and all the other methods work perfectly.

Here is the error I am receiving when trying to add the view programmatically, this was possible before I attempted to implement an interface for a callback to the Activity.

03-06 23:30:30.352    6986-6986/com.modup.app E/WORKOUTVIEW﹕ 2
03-06 23:30:30.372    6986-6986/com.modup.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.modup.app, PID: 6986
    java.lang.ClassCastException: com.modup.view.WorkoutView cannot be cast to com.modup.view.WorkoutView$ButtonPressInterface
            at com.modup.view.WorkoutView.init(WorkoutView.java:70)
            at com.modup.view.WorkoutView.onFinishInflate(WorkoutView.java:52)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:763)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
            at com.modup.fragment.CreateFragment.onClick(CreateFragment.java:197)
            at android.view.View.performClick(View.java:4442)
            at android.view.View$PerformClick.run(View.java:18473)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5105)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
            at dalvik.system.NativeStart.main(Native Method)
03-06 23:31:21.972    7620-7620/com.modup.app E/WORKOUTVIEW﹕ 2
03-06 23:31:21.982    7620-7620/com.modup.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.modup.app, PID: 7620
    java.lang.ClassCastException: com.modup.app.LeftMenusActivity cannot be cast to com.modup.view.WorkoutView$ButtonPressInterface
            at com.modup.view.WorkoutView.init(WorkoutView.java:70)
            at com.modup.view.WorkoutView.onFinishInflate(WorkoutView.java:52)
            at android.view.LayoutInflater.rInflate(LayoutInflater.java:763)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
            at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
            at com.modup.fragment.CreateFragment.onClick(CreateFragment.java:197)
            at android.view.View.performClick(View.java:4442)
            at android.view.View$PerformClick.run(View.java:18473)
            at android.os.Handler.handleCallback(Handler.java:733)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5105)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:792)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:608)
            at dalvik.system.NativeStart.main(Native Method)

Inside the Fragment which I am expecting to respond to a callback

@Override
public void buttonWasPressed() {
     workoutLayout.removeView(workoutView);
}

UPDATE:

I implemented

   public void registerButtonPressInterface(ButtonPressInterface listener){
        buttonPressCallback = listener;
    }

this does not result in a crash when adding a view, but my button does not work still and leads to a NullPointerException.

    @Override
public void onClick(View v) {
    switch (v.getId()){
        case R.id.btnRemoveWorkout:
            buttonPressCallback.buttonWasPressed();
            Log.e("DID THIS WORK?", "BUTTON PRESSED");
            break;
    }

}

This is how I am attempting to listen for the callback

        workoutView.registerButtonPressInterface(new WorkoutView.ButtonPressInterface() {
        @Override
        public void buttonWasPressed() {
            Log.e("BUTTON WAS PRESSED", "INTERFACE WORKED!");
        }
    });
    workoutLayout.addView(workoutView);

Upvotes: 0

Views: 56

Answers (1)

kris larson
kris larson

Reputation: 30985

According to your stack trace, this is the line that's causing the heartburn:

buttonPressCallback = (ButtonPressInterface) getContext();

You don't have the relevant code posted, but I'd bet that you think your activity is implementing this interface when it actually isn't. In fact, you say your last code snippet (which is the interface implementation) is from a Fragment.

Here is what I would recommend: Rather than casting the context to your interface, create a method

public void registerButtonPressListener(ButtonPressInterface listener)

on your view class and store a reference to the ButtonPressInterface implementation. This will make your view class more flexible since your context won't be required to implement ButtonPressInterface in order to use your view. Now the compiler will be able to tell you if what you are passing in does in fact implement the interface, and it will be easier for you to figure out what's wrong.

Upvotes: 1

Related Questions