0

I wanted to take the code from an activity, both the xml and the java and use it to create a fragment that is the exact same as the activities design and functionality. I have checked the docs (https://developer.android.com/guide/components/fragments.html) several times about Fragments and also watched tons of youtube videos about it. I literally copy and pasted the code from my activity.java file and pasted it directly into my fragment.java file then I made changes to the code that was there. But, I believe I have a misconception about Fragments.

Just to give a better scope of what error I have been getting I have been getting NullPointerExceptions like crazy.

My original java file for my original activity works perfectly, as does the xml.

package com.example.me.inserttitlename;


import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.view.InflateException;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;


/**
 * A simple {@link Fragment} subclass.
 */
public class LevelOneFragment extends Fragment {

    //creating variables
    private ImageView img;
    private ViewGroup viewer;
    TextView textCount;
    Button failButton;
    Button beginButton;
    TextView countDownBeginText;
    private TextView countDownMain;
    public int scoreCounter;

    public LevelOneFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment



        super.onActivityCreated(savedInstanceState);
        //setCont(R.layout.fragment_level_one);
       // return inflater.inflate(R.layout.fragment_level_one,container, false);

        View view = inflater.inflate(R.layout.fragment_level_one, container, true);
        //creating viewables and such
        viewer = (ViewGroup) view.findViewById(R.id.view_level);
        img = (ImageView) view.findViewById(R.id.imageView);
        failButton = (Button) view.findViewById(R.id.failureButton);
        countDownMain = (TextView) view.findViewById(R.id.countDownMain);
        countDownBeginText = (TextView) view.findViewById(R.id.countDownBeginText);
        beginButton = (Button) view.findViewById(R.id.beginButton);

        if (view != null) {
            ViewGroup parent = (ViewGroup) view.getParent();
            if (parent != null) {
                parent.removeView(view);
            }
        }
        try {
            view = inflater.inflate(R.layout.fragment_level_one, container, false);
        } catch (InflateException e) {

        }

        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(150, 150);
        img.setLayoutParams(layoutParams);
        img.setOnTouchListener(new LevelOneFragment.ChoiceTouchListener());

        //begin random movement
        startRandomButton(img);

        //setting up button for failure CORRECT TO TAKE YOU TO THE MAIN MENU
        failButton.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                startActivity(new Intent(getActivity(), MainMenu.class));
            }
        });

        //setting countdown text to 3
        countDownBeginText.setText(":3");

        //begin countdown from three
        beginButton.setOnClickListener(new View.OnClickListener(){
            public void onClick(View beginT) {
                CountDownTimer countDownTimer = new CountDownTimer(3*1000, 3) {
                    @Override
                    public void onTick(long millisUntilFinished) {

                        countDownBeginText.setText(":" + millisUntilFinished/1000);
                        //add possible sound here every tick
                    }

                    @Override
                    public void onFinish() {
                        beginButton.setVisibility(View.INVISIBLE);
                        countDownBeginText.setVisibility(View.INVISIBLE);

                        //countdown from 60------- change parameters in count down timer to the time desired
                        CountDownTimer countDownTimer = new CountDownTimer(60*1000, 3) {
                            @Override
                            public void onTick(long millisUntilFinishedMain) {

                                countDownMain.setText(":" + millisUntilFinishedMain/1000);
                                //add possible sound here every tick
                            }

                            @Override
                            public void onFinish() {
                                Toast.makeText(getActivity(),"You lose", Toast.LENGTH_LONG).show();
                                //rest of text in method is trial

                                startActivity(new Intent(getActivity(), MainMenu.class ));

                            }
                        }.start();

                    }
                }.start();
            }
        });
        return view; //inflater.inflate(R.layout.fragment_level_one,container, false);
    }
    //getting screen size
    public static Point getDisplaySize(@NonNull Context context){

        Point point = new Point();
        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        manager.getDefaultDisplay().getSize(point);
        return point;
    }

    //randomly move
    public void randomMovement(ImageView img){
        int   x = new Random().nextInt(getDisplaySize(getActivity()).x);
        int   y = new Random().nextInt(getDisplaySize(getActivity()).y);

        img.setY(y);
        img.setX(x);

    }

    //creating timer
    public void startRandomButton(final ImageView img){
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                getActivity().runOnUiThread(new Runnable() { //best method in the entire world-- use when trying to update ui in the background
                    @Override
                    public void run() {
                        randomMovement(img);
                    }
                });
            }
        }, 0, 5000);
    }


    //listener for the moving ball
    private final class ChoiceTouchListener implements View.OnTouchListener {
        public boolean onTouch(View view, MotionEvent event){

            //Calling Counter
            textCount = (TextView) getView().findViewById(R.id.textViewCount);



            //switch statement for different events
            switch (event.getAction() & MotionEvent.ACTION_MASK){

                case MotionEvent.ACTION_DOWN:
                    break;

                case MotionEvent.ACTION_UP:
                    //this is where youre going to generate randmom location with id.setX(randomX) and id.setY(randomY)
                    randomMovement(img);

                    //Setting Counter to count when img is clicked
                    String countValue = textCount.getText().toString();
                    scoreCounter = Integer.parseInt(countValue);
                    scoreCounter++;
                    textCount.setText(String.valueOf(scoreCounter));
                    break;


                case MotionEvent.ACTION_POINTER_DOWN:
                    break;

                case MotionEvent.ACTION_POINTER_UP:
                    break;


            }



            //checking score
            if(scoreCounter == 10 )
            {
                Toast.makeText(getActivity(),"You win", Toast.LENGTH_LONG).show();

            }

            viewer.invalidate();
            return true;
        }
    }
}

As you can see the code posted above is my java code for my fragment. Below is the xml for the fragment.

<?xml version="1.0" encoding="utf-8"?>


    <!-- TODO: Update blank fragment layout -->

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/view_level"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/levelbackgroundoptiontwo"
    tools:context="com.example.name.inserttitlename.LevelOneFragment"
    tools:layout_editor_absoluteX="0dp"
    tools:layout_editor_absoluteY="81dp">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/failureButton"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentTop="true"
            android:background="@drawable/levelbackgroundoptiontwo"
            android:visibility="visible" />
    </RelativeLayout>

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"
        android:text="Version: 0.0.12"
        android:textColor="#Ef9A9A"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        tools:layout_constraintBottom_creator="1"
        tools:layout_constraintLeft_creator="1" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="61dp"
        android:layout_height="80dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentStart="true"
        android:layout_marginBottom="66dp"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/clickerobject"
        tools:layout_constraintLeft_creator="1"
        tools:layout_constraintRight_creator="1"
        tools:layout_constraintTop_creator="1" />

    <TextView
        android:id="@+id/textViewCount"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentTop="true"
        android:fontFamily="casual"
        android:text="0"
        android:textColor="@android:color/white"
        android:textSize="30sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/levelCounter"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/textViewCount"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:fontFamily="casual"
        android:text="Level: 1"
        android:textColor="@android:color/white"
        android:textSize="30sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/countDownMain"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/levelCounter"
        android:layout_centerHorizontal="true"
        android:fontFamily="casual"
        android:text="60"
        android:textColor="@android:color/white"
        android:textSize="30sp"
        android:textStyle="bold" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <Button
            android:id="@+id/beginButton"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true"
            android:background="#80363636"
            android:fontFamily="casual"
            android:text="Tap anywhere to begin"
            android:textColor="@android:color/white"
            android:textSize="30sp"
            android:textStyle="bold"
            android:visibility="visible" />

    </RelativeLayout>

    <TextView
        android:id="@+id/countDownBeginText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="213dp"
        android:text="TextView"
        android:textColor="@android:color/white"
        android:textSize="35sp"
        android:textStyle="bold"
        android:visibility="visible"
        tools:text="3" />


</RelativeLayout>

Also here is where I am calling the fragment.

package com.example.name.insertitlename;

import android.app.Activity;

import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.widget.Button;
import android.widget.Toast;

/**
 * Created by Marcus
 */

public class LevelsMenu extends FragmentActivity {

    Button levelOne;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.levels_menu);

        //creating the buttons
         //Button levelOne;

        //setting the button equal to buttons found on levels_menu.xml
        levelOne = (Button) findViewById(R.id.levelone);


        //button listener surrounding fragment call
        levelOne.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                LevelOneFragment fragment = new LevelOneFragment();
                FragmentManager manager = getSupportFragmentManager();
                manager.beginTransaction().replace(R.id.levelsMainLayout, fragment, fragment.getTag()).commit();
            }
        });


    }


}

Here is my logcat:

10-22 01:02:03.174 3165-3341/com.example.jon.tapmeifyoucan E/AndroidRuntime: FATAL EXCEPTION: Timer-0
                                                                             Process: com.example.jon.tapmeifyoucan, PID: 3165
                                                                             java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.FragmentActivity.runOnUiThread(java.lang.Runnable)' on a null object reference
                                                                                 at com.example.jon.tapmeifyoucan.LevelOneFragment$3.run(LevelOneFragment.java:162)
                                                                                 at java.util.TimerThread.mainLoop(Timer.java:555)
                                                                                 at java.util.TimerThread.run(Timer.java:505)
10-22 01:02:03.290 3165-3183/com.example.jon.tapmeifyoucan D/EGL_emulation: eglMakeCurrent: 0xa77050c0: ver 3 0 (tinfo 0xa7703210)
10-22 01:02:03.374 3165-3183/com.example.jon.tapmeifyoucan D/EGL_emulation: eglMakeCurrent: 0xa77050c0: ver 3 0 (tinfo 0xa7703210)

I am not sure where I am going wrong. I could really use some help and maybe even some more clarification on fragments. For those who wanted to reference the original java code on the original activity it is posted below

//this consists of all the game logic
package com.example.name.insertitlename;


import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.os.CountDownTimer;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;


import org.w3c.dom.Text;

import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;


public class MainActivity extends AppCompatActivity {

    //creating variables
    private ImageView img;
    private ImageView lava;
    private ViewGroup rootLayout;
    TextView textCount;
    Button failButton;
    Button beginButton;
    TextView countDownBeginText;
    private TextView countDownMain;
    public int scoreCounter;



    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //creating viewables
        rootLayout = (ViewGroup) findViewById(R.id.view_root);
        img = (ImageView) rootLayout.findViewById(R.id.imageView);
        failButton = (Button) rootLayout.findViewById(R.id.failureButton);
        countDownMain = (TextView) findViewById(R.id.countDownMain);
        countDownBeginText = (TextView) findViewById(R.id.countDownBeginText);
        beginButton = (Button) findViewById(R.id.beginButton);

        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(150, 150);
        img.setLayoutParams(layoutParams);
        img.setOnTouchListener(new ChoiceTouchListener());

        //begin random movement
        startRandomButton(img);

        //setting up button for failure CORRECT TO TAKE YOU TO THE MAIN MENU
        failButton.setOnClickListener(new View.OnClickListener(){
            public void onClick(View v){
                startActivity(new Intent(MainActivity.this, MainMenu.class));
            }
        });
        //setting countdown text to 3
        countDownBeginText.setText(":3");

        //begin countdown from three
        beginButton.setOnClickListener(new View.OnClickListener(){
            public void onClick(View beginT) {
                CountDownTimer countDownTimer = new CountDownTimer(3*1000, 3) {
                    @Override
                    public void onTick(long millisUntilFinished) {

                        countDownBeginText.setText(":" + millisUntilFinished/1000);
                        //add possible sound here every tick
                    }

                    @Override
                    public void onFinish() {
                        beginButton.setVisibility(View.INVISIBLE);
                        countDownBeginText.setVisibility(View.INVISIBLE);

                        //countdown from 60------- change parameters in count down timer to the time desired
                        CountDownTimer countDownTimer = new CountDownTimer(60*1000, 3) {
                            @Override
                            public void onTick(long millisUntilFinishedMain) {

                                countDownMain.setText(":" + millisUntilFinishedMain/1000);
                                //add possible sound here every tick
                            }

                            @Override
                            public void onFinish() {
                                Toast.makeText(MainActivity.this,"You lose", Toast.LENGTH_LONG).show();
                                //rest of text in method is trial

                                startActivity(new Intent(MainActivity.this, MainMenu.class ));

                            }
                        }.start();

                    }
                }.start();
            }
        });


    }

    //getting screen size
    public static Point getDisplaySize(@NonNull Context context){

        Point point = new Point();
        WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        manager.getDefaultDisplay().getSize(point);
        return point;
    }

    //randomly move
     public void randomMovement(ImageView img){
         int   x = new Random().nextInt(getDisplaySize(this).x);
         int   y = new Random().nextInt(getDisplaySize(this).y);

        img.setY(y);
        img.setX(x);

    }

    //creating timer
    public void startRandomButton(final ImageView img){
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() { //best method in the entire world-- use when trying to update ui in the background
                    @Override
                    public void run() {
                        randomMovement(img);
                    }
                });
            }
        }, 0, 5000);
    }


    //listener for the moving ball
    private final class ChoiceTouchListener implements OnTouchListener{
        public boolean onTouch(View view, MotionEvent event){

            //Calling Counter
            textCount = (TextView) findViewById(R.id.textViewCount);



            //switch statement for different events
            switch (event.getAction() & MotionEvent.ACTION_MASK){

                case MotionEvent.ACTION_DOWN:
                    break;

               case MotionEvent.ACTION_UP:
                   //this is where youre going to generate randmom location with id.setX(randomX) and id.setY(randomY)
                   randomMovement(img);

                   //Setting Counter to count when img is clicked
                   String countValue = textCount.getText().toString();
                   scoreCounter = Integer.parseInt(countValue);
                   scoreCounter++;
                   textCount.setText(String.valueOf(scoreCounter));
                   break;


                case MotionEvent.ACTION_POINTER_DOWN:
                    break;

                case MotionEvent.ACTION_POINTER_UP:
                    break;


            }



            //checking score
            if(scoreCounter == 10 )
            {
                Toast.makeText(MainActivity.this,"You win", Toast.LENGTH_LONG).show();

            }

            rootLayout.invalidate();
            return true;
        }
    }
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
Marcus Cantu
  • 463
  • 3
  • 14
  • put `if (isAttached())` around `getActivity().runOnUiThread` – OneCricketeer Oct 22 '17 at 07:39
  • I am slightly confused what you mean put it around. Can you help me out just a bit more? I am sorry. – Marcus Cantu Oct 22 '17 at 07:48
  • `if (condition) { ... your code... }` – OneCricketeer Oct 22 '17 at 07:52
  • I feel so stupid. My mind is so cluttered right now I forgot the { on the if statement. Now I am getting that isAttatched() cant be resolved – Marcus Cantu Oct 22 '17 at 07:54
  • Sorry, `isAdded()`... Basically, `getActivity()` can return null when the Fragment is not bound to the Activity.... That will get around the error, but you will still need to figure out how to run that TimerTask – OneCricketeer Oct 22 '17 at 07:56
  • Hey good stuff man! It cleared all of my errors but now when ever I go to run the fragment I am getting a white screen. If you want to help with that too that would be cool but I am pretty sure I know what the problem is with this one. Thanks again! – Marcus Cantu Oct 22 '17 at 08:05
  • Well, you can always add an else statement to the if and print things to the log... But the problem is that `startRandomButton(img);` method using `getActivity()`. See if this helps https://stackoverflow.com/a/18078475/2308683 – OneCricketeer Oct 22 '17 at 08:12
  • Would that work within a fragment though? – Marcus Cantu Oct 22 '17 at 08:18
  • remove this `if (view != null) { ViewGroup parent = (ViewGroup) view.getParent(); if (parent != null) { parent.removeView(view); } } try { view = inflater.inflate(R.layout.fragment_level_one, container, false); } catch (InflateException e) { }` and change your `View view = inflater.inflate(R.layout.fragment_level_one, container, true);` to `View view = inflater.inflate(R.layout.fragment_level_one, container, false);` to prevent the whitescreen. – dotGitignore Oct 22 '17 at 08:18
  • @Cantum2 That question is specifically related to Fragments, yes. `onAttach` can safely be overriden – OneCricketeer Oct 22 '17 at 08:20
  • That removed the white screen! Thank you! Now my randomMovement(img) is not being called as a result of get activity being null – Marcus Cantu Oct 22 '17 at 08:23
  • Where do I create the method you referenced? The one in the link. Also I am getting that onAttatch is depracted that is because I imported import android.support.v4.app.Fragment; right? @cricket_007 – Marcus Cantu Oct 22 '17 at 08:29
  • The Activity parameter is deprected. `@Override public void onAttach(Context context)` is the correct one. https://stackoverflow.com/a/35802755/2308683 – OneCricketeer Oct 22 '17 at 08:34
  • Ahhh okay do I create that out of the onCreateView or what? Thank you so much by the way!!!!!!!!!!!!!!!! – Marcus Cantu Oct 22 '17 at 08:36
  • Hey I have been messing with the timer and I am not coming closer to a solution. It works in my activity. I added "if(isAdded()) around every place where randomMovement(img) is called and I added it around my getActivity()runOnUiThread section and had all of them log if something was wrong and non of them logged but it still isnt working. Any ideas? @cricket_007 – Marcus Cantu Oct 22 '17 at 20:26
  • Did you implement onAttach like I showed? – OneCricketeer Oct 22 '17 at 21:18

0 Answers0