Search code examples
javaandroidandroid-fragmentspopupandroid-toolbar

My app is crashing when I click on an ImageView in the toolbar - Fragments


Below are my dependencies

implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'

Below is my HomeFragment.java

package com.example.practice.fragments;

import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;

import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.denzcoskun.imageslider.ImageSlider;
import com.denzcoskun.imageslider.models.SlideModel;
import com.example.practice.MainActivity;
import com.example.practice.R;
import com.example.practice.activities.SettingsActivity;
import com.example.practice.activities.login_n_register.LoginActivity;
import com.example.practice.activities.login_n_register.ProfileActivity;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.FirebaseApp;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.shashank.sony.fancytoastlib.FancyToast;
import com.thefinestartist.finestwebview.FinestWebView;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import de.hdodenhof.circleimageview.CircleImageView;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link HomeFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class HomeFragment extends Fragment {
    private FirebaseFirestore firebaseFirestore;
    private FirebaseAuth mAuth;
    private String current_user_id;
    private FirebaseUser user;
    private String userName,name,email;
    private String userid;
    Dialog myDialog;
    String currentUserImage;
    CircleImageView currentUserImageCV;
    private static final String TAG = "MainActivity";
    final String PREFS_NAME = "MyPrefsFile";

    private FirebaseFirestore db = FirebaseFirestore.getInstance();
    private CollectionReference notebookRef = db.collection("Users");

    // TODO: Rename parameter arguments, choose names that match
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";

    // TODO: Rename and change types of parameters
    private String mParam1;
    private String mParam2;

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

    /**
     * Use this factory method to create a new instance of
     * this fragment using the provided parameters.
     *
     * @param param1 Parameter 1.
     * @param param2 Parameter 2.
     * @return A new instance of fragment HomeFragment.
     */
    // TODO: Rename and change types and number of parameters
    public static HomeFragment newInstance(String param1, String param2) {
        HomeFragment fragment = new HomeFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
        setHasOptionsMenu(true);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_home, container, false);

        Toolbar mToolbar = (Toolbar) view.findViewById(R.id.home_toolbar);
        if (mToolbar != null) {
            ((AppCompatActivity)getActivity()).setSupportActionBar(mToolbar);
            ((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("");
        }
        mToolbar.setTitle(null);

        ImageSlider imageSlider = view.findViewById(R.id.image_slider);

        List<SlideModel> slideModels = new ArrayList<>();

        slideModels.add(new SlideModel("SomeImageURL"));
        slideModels.add(new SlideModel("SomeImageURL"));
        slideModels.add(new SlideModel("SomeImageURL"));
        slideModels.add(new SlideModel("SomeImageURL"));
        slideModels.add(new SlideModel("SomeImageURL"));
        slideModels.add(new SlideModel("SomeImageURL"));

        imageSlider.setImageList(slideModels, true);

        currentUserImageCV = view.findViewById(R.id.currentUserImageCV);
        myDialog = new Dialog(getActivity().getApplicationContext());

        FirebaseApp.initializeApp(getActivity().getApplicationContext());
        mAuth = FirebaseAuth.getInstance();
        firebaseFirestore = FirebaseFirestore.getInstance();
        SharedPreferences settings = this.getActivity().getSharedPreferences(PREFS_NAME, 0);
        user = FirebaseAuth.getInstance().getCurrentUser();

        if(user!=null)
        {
            userid = FirebaseAuth.getInstance().getCurrentUser().getUid();
            final DocumentReference docRef = db.collection("Users").document(userid);
            docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
                @Override
                public void onEvent(@Nullable DocumentSnapshot snapshot,
                                    @Nullable FirebaseFirestoreException e) {
                    if (snapshot.exists()){
                        userName = snapshot.getString("username");
                        name = snapshot.getString("name");
                        email = snapshot.getString("email");
                        currentUserImage = snapshot.getString("image");

                        Glide.with(getActivity().getApplicationContext())
                                .load(currentUserImage)
                                .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                                .centerCrop()
                                .placeholder(R.drawable.default_profile)
                                .into(currentUserImageCV);
                    } else {
                        FancyToast.makeText(getActivity().getApplicationContext(), getString(R.string.things_gone_bad), FancyToast.LENGTH_LONG, FancyToast.ERROR,false).show();
                    }
                }
            });

            userid = FirebaseAuth.getInstance().getCurrentUser().getUid();
            firebaseFirestore.collection("Users").document(userid).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
                @Override
                public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                    if(task.isSuccessful()){
                        if(task.getResult().exists()){
                            userName = task.getResult().getString("username");
                            name = task.getResult().getString("name");
                            email= task.getResult().getString("email");
                            currentUserImage = task.getResult().getString("image");

                            Glide.with(getActivity().getApplicationContext())
                                    .load(currentUserImage)
                                    .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                                    .centerCrop()
                                    .placeholder(R.drawable.default_profile)
                                    .into(currentUserImageCV);

                        }
                    } else {
                        String error = task.getException().getMessage();
                        FancyToast.makeText(getActivity().getApplicationContext(),"500 Server Retrieve Error: " + error, FancyToast.LENGTH_LONG, FancyToast.ERROR,false).show();
                    }
                }
            });
        }

        currentUserImageCV.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ShowPopup(v);
            }
        });

        return view;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.main_menu, menu);
        super.onCreateOptionsMenu(menu,inflater);
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {

            case R.id.action_settings:
                startActivity(new Intent(getActivity().getApplicationContext(), SettingsActivity.class));
                return true;
        }
        return false;
    }

    public void ShowPopup(View v) {
        TextView userName;
        CircleImageView manageAcc_userImage;
        Button manageAccountBtn,signoutBtn,privacyBtn,termsBtn;
        myDialog.setContentView(R.layout.manage_acc_popup);
        manageAcc_userImage = myDialog.findViewById(R.id.manageAcc_userImage);
        userName =(TextView) myDialog.findViewById(R.id.manageAcc_userEmail);
        userName.setText(email);
        manageAccountBtn = (Button) myDialog.findViewById(R.id.button);
        signoutBtn = (Button) myDialog.findViewById(R.id.signoutBtn);
        privacyBtn = (Button) myDialog.findViewById(R.id.privacyBtn);
        termsBtn = (Button) myDialog.findViewById(R.id.termsBtn);

        signoutBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myDialog.dismiss();
                logout();
            }
        });

        privacyBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myDialog.dismiss();

                new FinestWebView.Builder(getActivity().getApplicationContext()).theme(R.style.FinestWebViewTheme)
                        .titleDefault(getString(R.string.privacy_policy))
                        .toolbarScrollFlags(0)
                        .statusBarColorRes(R.color.colorPrimary)
                        .toolbarColorRes(R.color.colorPrimary)
                        .titleColorRes(R.color.colorWhiteText)
                        .urlColorRes(R.color.colorWhiteText)
                        .iconDefaultColorRes(R.color.colorWhiteText)
                        .theme(R.style.webview)
                        .progressBarColorRes(R.color.colorPrimaryDark)
                        .swipeRefreshColorRes(R.color.colorPrimaryLight)
                        .menuSelector(R.drawable.selector_dark_theme)
                        .menuTextGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT)
                        .menuTextPaddingRightRes(R.dimen.defaultMenuTextPaddingLeft)
                        .dividerHeight(0)
                        .gradientDivider(false)
                        .setCustomAnimations(R.anim.slide_left_in, R.anim.hold, R.anim.hold,
                                R.anim.slide_right_out)
                        .disableIconBack(true)
                        .disableIconClose(false)
                        .disableIconForward(true)
                        .disableIconMenu(false)
                        .show("https://www.habbo.com/playing-habbo/safety");

            }
        });

        termsBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                myDialog.dismiss();

                new FinestWebView.Builder(getActivity().getApplicationContext()).theme(R.style.FinestWebViewTheme)
                        .titleDefault(getString(R.string.terms_of_service))
                        .toolbarScrollFlags(0)
                        .statusBarColorRes(R.color.colorPrimary)
                        .toolbarColorRes(R.color.colorPrimary)
                        .titleColorRes(R.color.colorWhiteText)
                        .urlColorRes(R.color.colorWhiteText)
                        .iconDefaultColorRes(R.color.colorWhiteText)
                        .theme(R.style.webview)
                        .progressBarColorRes(R.color.colorPrimaryDark)
                        .swipeRefreshColorRes(R.color.colorPrimaryLight)
                        .menuSelector(R.drawable.selector_dark_theme)
                        .menuTextGravity(Gravity.CENTER_VERTICAL | Gravity.RIGHT)
                        .menuTextPaddingRightRes(R.dimen.defaultMenuTextPaddingLeft)
                        .dividerHeight(0)
                        .gradientDivider(false)
                        .setCustomAnimations(R.anim.slide_left_in, R.anim.hold, R.anim.hold,
                                R.anim.slide_right_out)
                        .disableIconBack(true)
                        .disableIconClose(false)
                        .disableIconForward(true)
                        .disableIconMenu(false)
                        .show("https://nft.habbo.com/terms");

            }
        });

        Glide.with(getActivity().getApplicationContext())
                .load(currentUserImage)
                .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
                .centerCrop()
                .placeholder(new ColorDrawable(Color.GRAY))
                .into(manageAcc_userImage);

        manageAccountBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent profileIntent = new Intent(getActivity().getApplicationContext(), ProfileActivity.class);
                startActivity(profileIntent);
                getActivity().overridePendingTransition(R.anim.slide_from_right, R.anim.slide_to_left);
            }
        });
        myDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        myDialog.setCancelable(true);
        myDialog.show();
    }

    private void logout() {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity().getApplicationContext(),R.style.MyCustomAlert);
        builder.setTitle(getString(R.string.logoutBtn));
        builder.setMessage(getString(R.string.are_you_sure_logout));
        builder.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                mAuth.signOut();
                sendToLoginPage();
            }
        });

        builder.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        AlertDialog alertDialog = builder.create();
        alertDialog.show();

    }

    private void sendToLoginPage() {
        Intent intent = new Intent(getActivity().getApplicationContext(), LoginActivity.class);
        startActivity(intent);
        getActivity().finish();
        getActivity().overridePendingTransition(R.anim.slide_from_left, R.anim.slide_to_right);
    }

}

The above code looks fine to me. Moved it from the MainActivity.java and did some changes to work inside the fragment, but now I don't understand why the following below is happening

My app crashes when I click the ImageView that's working also as a button.

I'm getting below error:

2022-03-10 00:50:47.012 16503-16503/com.example.practice E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.practice, PID: 16503
    android.view.InflateException: Binary XML file line #2 in com.example.practice:layout/manage_acc_popup: Binary XML file line #2 in com.example.practice:layout/manage_acc_popup: Error inflating class com.google.android.material.card.MaterialCardView
    Caused by: android.view.InflateException: Binary XML file line #2 in com.example.practice:layout/manage_acc_popup: Error inflating class com.google.android.material.card.MaterialCardView
    Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
        at android.view.LayoutInflater.createView(LayoutInflater.java:852)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1004)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:657)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
        at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:455)
        at android.app.Dialog.setContentView(Dialog.java:569)
        at com.example.practice.fragments.HomeFragment.ShowPopup(HomeFragment.java:237)
        at com.example.practice.fragments.HomeFragment$3.onClick(HomeFragment.java:210)
        at android.view.View.performClick(View.java:7448)
        at android.view.View.performClickInternal(View.java:7425)
        at android.view.View.access$3600(View.java:810)
        at android.view.View$PerformClick.run(View.java:28305)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.MaterialComponents (or a descendant).
        at com.google.android.material.internal.ThemeEnforcement.checkTheme(ThemeEnforcement.java:243)
        at com.google.android.material.internal.ThemeEnforcement.checkMaterialTheme(ThemeEnforcement.java:217)
        at com.google.android.material.internal.ThemeEnforcement.checkCompatibleTheme(ThemeEnforcement.java:145)
        at com.google.android.material.internal.ThemeEnforcement.obtainStyledAttributes(ThemeEnforcement.java:76)
        at com.google.android.material.card.MaterialCardView.<init>(MaterialCardView.java:124)
        at com.google.android.material.card.MaterialCardView.<init>(MaterialCardView.java:114)
        at java.lang.reflect.Constructor.newInstance0(Native Method) 
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343) 
        at android.view.LayoutInflater.createView(LayoutInflater.java:852) 
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1004) 
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:657) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:532) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:479) 
        at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:455) 
        at android.app.Dialog.setContentView(Dialog.java:569) 
        at com.example.practice.fragments.HomeFragment.ShowPopup(HomeFragment.java:237) 
        at com.example.practice.fragments.HomeFragment$3.onClick(HomeFragment.java:210) 
        at android.view.View.performClick(View.java:7448) 
        at android.view.View.performClickInternal(View.java:7425) 
        at android.view.View.access$3600(View.java:810) 
        at android.view.View$PerformClick.run(View.java:28305) 
        at android.os.Handler.handleCallback(Handler.java:938) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:223) 
        at android.app.ActivityThread.main(ActivityThread.java:7656) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 
2022-03-10 00:50:47.013 16503-16503/com.example.practice E/CustomActivityOnCrash: App has crashed, executing CustomActivityOnCrash's UncaughtExceptionHandler
    android.view.InflateException: Binary XML file line #2 in com.example.practice:layout/manage_acc_popup: Binary XML file line #2 in com.example.practice:layout/manage_acc_popup: Error inflating class com.google.android.material.card.MaterialCardView
    Caused by: android.view.InflateException: Binary XML file line #2 in com.example.practice:layout/manage_acc_popup: Error inflating class com.google.android.material.card.MaterialCardView
    Caused by: java.lang.reflect.InvocationTargetException
        at java.lang.reflect.Constructor.newInstance0(Native Method)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343)
        at android.view.LayoutInflater.createView(LayoutInflater.java:852)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1004)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:657)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:532)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:479)
        at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:455)
        at android.app.Dialog.setContentView(Dialog.java:569)
        at com.example.practice.fragments.HomeFragment.ShowPopup(HomeFragment.java:237)
        at com.example.practice.fragments.HomeFragment$3.onClick(HomeFragment.java:210)
        at android.view.View.performClick(View.java:7448)
        at android.view.View.performClickInternal(View.java:7425)
        at android.view.View.access$3600(View.java:810)
        at android.view.View$PerformClick.run(View.java:28305)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
     Caused by: java.lang.IllegalArgumentException: The style on this component requires your app theme to be Theme.MaterialComponents (or a descendant).
        at com.google.android.material.internal.ThemeEnforcement.checkTheme(ThemeEnforcement.java:243)
        at com.google.android.material.internal.ThemeEnforcement.checkMaterialTheme(ThemeEnforcement.java:217)
        at com.google.android.material.internal.ThemeEnforcement.checkCompatibleTheme(ThemeEnforcement.java:145)
        at com.google.android.material.internal.ThemeEnforcement.obtainStyledAttributes(ThemeEnforcement.java:76)
        at com.google.android.material.card.MaterialCardView.<init>(MaterialCardView.java:124)
        at com.google.android.material.card.MaterialCardView.<init>(MaterialCardView.java:114)
        at java.lang.reflect.Constructor.newInstance0(Native Method) 
        at java.lang.reflect.Constructor.newInstance(Constructor.java:343) 
        at android.view.LayoutInflater.createView(LayoutInflater.java:852) 
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:1004) 
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:959) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:657) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:532) 
        at android.view.LayoutInflater.inflate(LayoutInflater.java:479) 
        at com.android.internal.policy.PhoneWindow.setContentView(PhoneWindow.java:455) 
        at android.app.Dialog.setContentView(Dialog.java:569) 
        at com.example.practice.fragments.HomeFragment.ShowPopup(HomeFragment.java:237) 
        at com.example.practice.fragments.HomeFragment$3.onClick(HomeFragment.java:210) 
        at android.view.View.performClick(View.java:7448) 
        at android.view.View.performClickInternal(View.java:7425) 
        at android.view.View.access$3600(View.java:810) 
        at android.view.View$PerformClick.run(View.java:28305) 
        at android.os.Handler.handleCallback(Handler.java:938) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:223) 
        at android.app.ActivityThread.main(ActivityThread.java:7656) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947) 

Solution

  • Here's the problem: myDialog = new Dialog(getActivity().getApplicationContext());

    – Do not use the application Context there, because it doesn't have a theme on it. You want the Activity instead; e.g., just new Dialog(getActivity()). If this Fragment is in MainActivity where this code originally worked, then that should be all you need to change, if I'm following your description correctly. Otherwise, you might need to look into your theme setup, as the answers below suggest.

    This answer is taken from Mike M.'s comment on the question — thank you, it was the only real solution to the problem.