Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is going on with my Android Navigation drawer activity?

I am building an OpenGL live wallpaper. I decided to have a Navigation Drawer in my main activity since there are a lot of features the user will have access to.

The problem/issue If I press the "hardware" back button to normally close an app the initial fragment that is shown just refreshes and the app never closes. If I hit the home button and go back to the app everything is a black screen. I've searched all throughout Google thinking that maybe I wasn't destroying the MainActivity properly or for a way to terminate a fragment. I've tried calling finish() in the main activity's onDestroy method. I've tried utilizing the remove method from fragment manager in each fragments onDetach method per posts that I've found online. Nothing has worked. I'm stumped. I've set debug points in the main activity on the onDestroy method and on the fragments onDetach method with no error being produced or any information being given. At this point I am clueless. Here's my MainActivity class.

    public class MainActivity extends AppCompatActivity implements OnNavigationItemSelectedListener, OnPostSelectedListener{

    FragmentManager mFragmentManager;
    FragmentTransaction mFragmentTransaction;
    TextView usrTag, tagrEmail;
    CircleImageView tagrPic;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        mFragmentManager = getSupportFragmentManager();
        mFragmentTransaction = mFragmentManager.beginTransaction();
        mFragmentTransaction.add(R.id.cLMain, new PreviewFragment()).addToBackStack("PreviewFragment").commit();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);
        View header = navigationView.getHeaderView(0);
        usrTag = (TextView)header.findViewById(R.id.usrName);
        tagrEmail = (TextView)header.findViewById(R.id.usrEmail);
        tagrPic = (CircleImageView)header.findViewById(R.id.usrImg);

        Log.i("MainActivity: ", "User Photo: " + getProfilePic(this));

        usrTag.setText(getUserName(getBaseContext()));
        tagrEmail.setText(getUserEmail(getBaseContext()));
        GlideUtils.loadProfileIcon(getProfilePic(getBaseContext()), tagrPic);

    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();


        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        Fragment fragment = null;
        Class fragmentClass = null;
        int id = item.getItemId();

        if (id == R.id.nav_home) {
            fragmentClass = PreviewFragment.class;
        } else if (id == R.id.nav_custom) {
            startCustomLabelCreator();
        } else if (id == R.id.nav_mylabels) {

        } else if (id == R.id.nav_commLabels) {
            fragmentClass = PostsFragment.class;
        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        try {
            fragment = (Fragment) fragmentClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // Insert the fragment by replacing any existing fragment
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().replace(R.id.cLMain, fragment).commit();

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    public void startCustomLabelCreator(){
        Intent cLC = new Intent(getBaseContext(), CreateLabel.class);
        startActivity(cLC);
    }

    @Override
    public void onPostComment(String postKey) {

    }

    @Override
    public void onPostLike(String postKey) {

    }

    @Override
    public void onPhotoSelected(String photoUrl) {

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        finish();
    }
}

My Fragments

    public class PostsFragment extends Fragment implements ConfirmSelectedPhotoListener{

    public static final String TAG = "PostsFragment";
    private static final String KEY_LAYOUT_POSITION = "layoutPosition";
    private int mRecyclerViewPosition = 0;
    private OnPostSelectedListener mListener;


    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter<PostViewHolder> mAdapter;

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

    public static PostsFragment newInstance() {
        PostsFragment fragment = new PostsFragment();
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_posts, container, false);
        rootView.setTag(TAG);

        mRecyclerView = (RecyclerView) rootView.findViewById(R.id.my_recycler_view);
        return rootView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
        linearLayoutManager.setReverseLayout(true);
        linearLayoutManager.setStackFromEnd(true);
        mRecyclerView.setLayoutManager(linearLayoutManager);

        Log.d(TAG, "Restoring recycler view position (all): " + mRecyclerViewPosition);
        Query allPostsQuery = FirebaseUtil.getPostsRef();
        mAdapter = getFirebaseRecyclerAdapter(allPostsQuery);
        mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onItemRangeInserted(int positionStart, int itemCount) {
                super.onItemRangeInserted(positionStart, itemCount);
                // TODO: Refresh feed view.
            }
        });


        mRecyclerView.setAdapter(mAdapter);
    }

    private FirebaseRecyclerAdapter<Post, PostViewHolder> getFirebaseRecyclerAdapter(Query query) {
        return new FirebaseRecyclerAdapter<Post, PostViewHolder>(
                Post.class, R.layout.post_item, PostViewHolder.class, query) {
            @Override
            public void populateViewHolder(final PostViewHolder postViewHolder,
                                           final Post post, final int position) {
                setupPost(postViewHolder, post, position, null);
            }

            @Override
            public void onViewRecycled(PostViewHolder holder) {
                super.onViewRecycled(holder);
//                FirebaseUtil.getLikesRef().child(holder.mPostKey).removeEventListener(holder.mLikeListener);
            }
        };
    }

    private void setupPost(final PostViewHolder postViewHolder, final Post post, final int position, final String inPostKey) {
        postViewHolder.setPhoto(post.getThumb_url());
        Log.d(TAG, post.getThumb_url());
        postViewHolder.setText(post.getText());
        postViewHolder.setTimestamp(DateUtils.getRelativeTimeSpanString(
                (long) post.getTimestamp()).toString());
        final String postKey;
        if (mAdapter instanceof FirebaseRecyclerAdapter) {
            postKey = ((FirebaseRecyclerAdapter) mAdapter).getRef(position).getKey();
        } else {
            postKey = inPostKey;
        }

        Author author = post.getAuthor();
        postViewHolder.setAuthor(author.getFull_name(), author.getUid());
        postViewHolder.setIcon(author.getProfile_picture(), author.getUid());

        ValueEventListener likeListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                postViewHolder.setNumLikes(dataSnapshot.getChildrenCount());
                if (dataSnapshot.hasChild(FirebaseUtil.getCurrentUserId())) {
                    postViewHolder.setLikeStatus(PostViewHolder.LikeStatus.LIKED, getActivity());
                } else {
                    postViewHolder.setLikeStatus(PostViewHolder.LikeStatus.NOT_LIKED, getActivity());
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        };
        FirebaseUtil.getLikesRef().child(postKey).addValueEventListener(likeListener);
        postViewHolder.mLikeListener = likeListener;

        postViewHolder.setPostClickListener(new PostViewHolder.PostClickListener() {
            @Override
            public void showComments() {
                Log.d(TAG, "Comment position: " + position);
                mListener.onPostComment(postKey);
            }

            @Override
            public void toggleLike() {
                Log.d(TAG, "Like position: " + position);
                mListener.onPostLike(postKey);
            }

            @Override
            public void savePhotoUrl() {
                //mListener.onPhotoSelected(post.getFull_url());
                showLabelConfirm(post.getFull_url());
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mAdapter != null && mAdapter instanceof FirebaseRecyclerAdapter) {
            ((FirebaseRecyclerAdapter) mAdapter).cleanup();
        }
    }


    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        // Save currently selected layout manager.
        int recyclerViewScrollPosition = getRecyclerViewScrollPosition();
        Log.d(TAG, "Recycler view scroll position: " + recyclerViewScrollPosition);
        savedInstanceState.putSerializable(KEY_LAYOUT_POSITION, recyclerViewScrollPosition);
        super.onSaveInstanceState(savedInstanceState);
    }

    private int getRecyclerViewScrollPosition() {
        int scrollPosition = 0;
        // TODO: Is null check necessary?
        if (mRecyclerView != null && mRecyclerView.getLayoutManager() != null) {
            scrollPosition = ((LinearLayoutManager) mRecyclerView.getLayoutManager())
                    .findFirstCompletelyVisibleItemPosition();
        }
        return scrollPosition;
    }

    @Override
    public void onSelectedPhoto(String selectPhoto) {
        mListener.onPhotoSelected(selectPhoto);
    }

    public interface OnPostSelectedListener {
        void onPostComment(String postKey);
        void onPostLike(String postKey);
        void onPhotoSelected(String photoUrl);
    }

    private void showLabelConfirm(String uriBmp) {
        FragmentManager fm = getFragmentManager();
        PhotoDialogFragment editNameDialogFragment = PhotoDialogFragment.newInstance(uriBmp);
        // SETS the target fragment for use later when sending results
        editNameDialogFragment.setTargetFragment(PostsFragment.this, 300);
        editNameDialogFragment.show(fm, "fragment_edit_name");
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnPostSelectedListener) {
            mListener = (OnPostSelectedListener) context;
        } else {
            throw new RuntimeException(context.toString()
                    + " must implement OnPostSelectedListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }
}

Second Fragment:

    public class PreviewFragment extends RajBaseFragment {


    @Override
    public ISurfaceRenderer createRenderer() {
        return new PreviewRenderer(getContext());
    }


}

Which extends:

    public abstract class RajBaseFragment extends Fragment implements IDisplay, View.OnClickListener {


    protected FrameLayout mLayout;
    protected ISurface mRajawaliSurface;
    protected ISurfaceRenderer mRenderer;

    public RajBaseFragment(){

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);


    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);

        // Inflate the view
        mLayout = (FrameLayout) inflater.inflate(getLayoutID(), container, false);

        mLayout.findViewById(R.id.relative_layout_loader_container).bringToFront();

        // Find the TextureView
        mRajawaliSurface = (ISurface) mLayout.findViewById(R.id.rajwali_surface);

        // Create the loader


        mRenderer = createRenderer();
        onBeforeApplyRenderer();
        applyRenderer();
        return mLayout;
    }

    protected void onBeforeApplyRenderer() {

    }

    protected void applyRenderer() {
        mRajawaliSurface.setSurfaceRenderer(mRenderer);
    }

    @Override
    public void onClick(View v) {

    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();

        if (mLayout != null)
            mLayout.removeView((View) mRajawaliSurface);
    }

    @Override
    public int getLayoutID() {
        return R.layout.rajawali_textureview_fragment;
    }




}

I've tried all the recommendations below so far and the primary fragment that is set in the MainActivity's onCreate method still gets refreshed/reloaded when the back button is pressed rather than the app exiting/closing.

like image 648
Steve C. Avatar asked Aug 08 '16 11:08

Steve C.


People also ask

What is navigation drawer activity in Android?

The navigation drawer is a UI panel that shows your app's main navigation menu. The drawer appears when the user touches the drawer icon in the app bar or when the user swipes a finger from the left edge of the screen.

What is drawer in Android?

Android Navigation Drawer is a sliding left menu that is used to display the important links in the application. Navigation drawer makes it easy to navigate to and fro between those links. It's not visible by default and it needs to opened either by sliding from left or clicking its icon in the ActionBar.

Why do we use the navigation drawer in Android app?

Navigation drawers provide access to destinations and app functionality, such as switching accounts. They can either be permanently on-screen or controlled by a navigation menu icon. Navigation drawers are recommended for: Apps with five or more top-level destinations.


2 Answers

In your onNavigationItemSelected method, you are replacing the current fragment with fragment even in cases where fragment is null, which has undefined effects. You should not do that.

One fix is to replace this code block:

try {
  fragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
  e.printStackTrace();
}

with this one:

if (fragmentClass != null) {
  fragment = fragmentClass.newInstance();
  FragmentManager fragmentManager = getSupportFragmentManager();
  fragmentManager.beginTransaction().replace(R.id.cLMain, fragment).addToBackStack().commit();
}

(and then leave out the fragment transaction below this point).

Also, there is a call to finish in the onDestroy method, which probably is not causing the problem but should be taken out because it does not make any sense there.

like image 115
x-code Avatar answered Sep 20 '22 23:09

x-code


 @Override
 public boolean onOptionsItemSelected(MenuItem item) {
          switch (item.getItemId()) {
          case android.R.id.home:
                 onBackPressed();
                 break;
            }
          return true;
  }

replace your onOptionsItemSelected() with mine.

like image 22
Nikhil Borad Avatar answered Sep 17 '22 23:09

Nikhil Borad