I have been following the tutorial here:
And this code here has been confusing me:
/** Swaps fragments in the main content view */
private void selectItem(int position) {
// Create a new fragment and specify the planet to show based on position
Fragment fragment = new PlanetFragment();
Bundle args = new Bundle();
args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
fragment.setArguments(args);
// Insert the fragment by replacing any existing fragment
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
// Highlight the selected item, update the title, and close the drawer
mDrawer.setItemChecked(position, true);
setTitle(mPlanetTitles[position]);
mDrawerLayout.closeDrawer(mDrawer);
Right now my app runs and looks great, but when you press on the buttons in the navigation drawer, nothing happens. I need to figure out how that if a user presses one button, it swaps in a new FrameLayout. Also another question: I have this in my activity_main.xml layout:
<!-- As the main content view, the view below consumes the entire
space available using match_parent in both dimensions. -->
<FrameLayout android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:keepScreenOn="true"
>
</ListView>
</FrameLayout>
<!-- android:layout_gravity="start" tells DrawerLayout to treat
this as a sliding drawer on the left side for left-to-right
languages and on the right side for right-to-left languages.
The drawer is given a fixed width in dp and extends the full height of
the container. A solid background is used for contrast
with the content view. -->
<ListView
android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
I'm not entirely sure if I should have my list view with the content in it yet (the ListView inside of the FrameLayout). I tried making its own xml layout but when I refrenced it to inflate the ListView it didn't work. So do i set up a separate 'xml' file for each frame? If so, how do I swap in that fragment based on what button is clicked? Thanks for your time and help!
EDIT!!
THIS IS THE SELECTITEM METHOD
private void selectItem(int position) {
Log.i("MainActivity", "selectItem()" + position); //this gets called successfully
//not sure if this equals() thing is the best way to do this
if("Stuff".equals(getListView().getItemAtPosition(position))){
Log.i("MainActivity", "getItemAtPosition()-Stuff" + position); //this doesn't get called
mDrawerList.setItemChecked(position, true);
setTitle(mPlanetTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}else if("Stuff2".equals(getListView().getItemAtPosition(position))){
Log.i("MainActivity", "getItemAtPosition()-Stuff2" + position); //this also doesn't get called
mDrawerList.setItemChecked(position, true);
setTitle(mPlanetTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
Intent openHelpAvtivity = new Intent("com.schrodingerscat.hh.math.glossary.THEOREMSLIST");
startActivity(openHelpAvtivity);
}
Have you tried stepping through it with a debugger? Is selectItem() getting called? If not, make sure that you set the OnClickListener correctly.
You don't need separate XML files for each frame. (What do you mean by frame? Fragment? I'm assuming so.) The whole point is that you can create a new fragment and use setArguments() to set what it displays. The list view should have its data populated with the following code, as provided:
mPlanetTitles = getResources().getStringArray(R.array.planets_array);
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// Set the adapter for the list view
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mPlanetTitles));
Try downloading the full example code (http://developer.android.com/shareables/training/NavigationDrawer.zip) and see what you're doing differently. I think that this example is meant to be downloaded, not reconstructed: the tutorial page doesn't quite include all the code that you need.
I fixed it! Yay! Thanks to #bee for the enlightenment! All i had to do, instead of using getListView(), I did this instead: if("Stuff".equals(mDrawerList.getItemAtPosition(position))){} and that finally worked!
Related
I'm looking for some help in Android studio with replacing a parent fragment's view with the view of a child fragment when a view in the parent fragment is clicked. Thank you in advance for your help.
Right now I have a parent fragment which is a chat list, and a child fragment (the chat screen) that shows up when you click on an element of the chat screen (i.e. a button). The chat list looks like this:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.myapplication.ChatListFragment">
<!-- Empty Container for Fragment to Live in -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView
android:id="#+id/chatListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/moonstone">
</ListView>
</FrameLayout>
I have set the onClickListener for the chatListView as follows:
_chatListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String chatName = _chatListAdapter.getItem(i).getChatTitle();
openChatScreen(chatName);
}
});
And the openChatScreenWindow() looks like this:
private void openChatScreen(String chatName)
{
_fragmentManager = getChildFragmentManager();
Log.i(CHAT_LIST_TAG, "starting chat screen fragment");
FragmentTransaction fragmentTransaction = _fragmentManager.beginTransaction();
ChatScreenFragment chatScreenFragment = ChatScreenFragment.newInstance(chatName);
fragmentTransaction.add(R.id.fragment_container, chatScreenFragment);
fragmentTransaction.addToBackStack(GlobalConstants.OPEN_CHAT_WINDOW_FRAGMENT_STRING + chatName);
fragmentTransaction.commit();
}
However, when I run this code, the child fragment is obscured, because both the frame layout (the view that the fragment is displayed in) and the chatListView have their widths and heights set to match_parent (I figured this out by testing the height and width of the chat list as 200dp, and I was able to see the child fragment behind it).
Is there a simple way to get the fragment to replace the chatListView whenever it is loaded?
For example, is there a way to change this view:
To this one:
... when an element in the chat list (the first one) is clicked?
I was thinking of changing the list view's visibility to invisible and visible based on whether the fragment is loaded, but that seems like a headache.
Please let me know what you think, thank you!
First off most modern way of managing fragments is - Navigation component
According your approach - you are adding child fragment on top of the prev fragment with fragmentTransaction.add, you can use fragmentTransaction.replace instead
Also, you might want to set child fragment background to solid color - to hide previous fragment, if you use this method - make child's fragment root clickable - to prevent fragments click through.
My recommendation - spend more time on learning Navigation component
I have only one listview in a fragment with other views.
As shown in the view dump below, for some reason, there are two listviews in the hierarchy (with same resource id).
The unpopulated listview (top one) here I think, masks my populated listview.
What is this listview (that is selected in the screenshot) and how can I remove it/find its origin.
My code for this fragment looks like:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/dark"
android:orientation="vertical">
<include layout="#layout/empty_view"/>
<include layout="#layout/progress_bar"/>
<com.application.custom.CustomListView
android:id="#+id/main_list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
UPDATE:
The activity simply loads the fragments:
HomeFrag homeFragment = new HomeFrag();
getSupportFragmentManager().beginTransaction()
.add(R.id.homelist_fragment_container, homeFragment, "home_fragment")
.commit();
Here we are using add to add the fragment, without checking if the fragment exists. This resulted in multiple view hierarchies with same resource ids.
Adding the following check to see if the fragment already exists, around the add fragment code fixes this:
if (getSupportFragmentManager().findFragmentByTag("my_frag_tag") == null) {
//add fragment with tag "my_frag_tag"
HomeFrag homeFragment = new HomeFrag();
getSupportFragmentManager().beginTransaction()
.add(R.id.homelist_fragment_container, homeFragment, "my_frag_tag")
.commit();
}
This also ensures that the fragment isn't created when there is no need to create it (unlike replace).
I have great problems getting the Navigation Tabs work. I am aware of this guide http://developer.android.com/guide/topics/ui/actionbar.html#Tabs
but I have problems understanding the article. It says the following:
To get started, your layout must include a ViewGroup in which you place each Fragment associated with a tab. Be sure the ViewGroup has a resource ID so you can reference it from your code and swap the tabs within it. Alternatively, if the tab content will fill the activity layout, then your activity doesn't need a layout at all (you don't even need to call setContentView()). Instead, you can place each fragment in the default root view, which you can refer to with the android.R.id.content ID.
As I don't use a Fragment for my Main Layout, but for others, I think the "alternative" way is right for me (I would like Tab 1 to be the Main Layout I have right now and then 2 and 3 to be my fragments), but I don't know how to accomplish this. Can someone maybe help out on this?
I was able to set up the tabs and the TabListener, so that is not the problem. The problem is that the first tab is NOT supposed to be a fragment, but my main activity layout! This is where I need help!
I did try to use my main activity-layout for a fragment, but for some reason if I click that tab, the tab changes but the screen stays white. I cannot see my fragment view.
The old code was:
mListView = (ListView) findViewById(R.id.list_view);
mListView.setAdapter(mAdapter);
mListView.setTextFilterEnabled(true);
and I've changed it in the fragment to:
View view = inflater.inflate(R.layout.list, container, false);
mListView = (ListView) view.findViewById(R.id.list_view);
mListView.setAdapter(mAdapter);
mListView.setTextFilterEnabled(true);
// do stuff here //
return view;
and this is list.xml:
<FrameLayout xmlns:android:="http://schemas.android.com/apk/res/android"
android:id="#id/main_fragment"
android:layout_width="match_parent"
android:layout:height=match_parent">
<ListView android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout:height=0dp"
android:layout_weight="1"
android:layout:marginTop="20dp"
android:descendantFocusability="blocksDescendants"/>
</FrameLayout>
how come I cannot see anything?
Solved: This was because I set the height to 0dp.
Please update your code by this:
<FrameLayout xmlns:android:="http://schemas.android.com/apk/res/android"
android:id="#+id/main_fragment"
android:layout_width="match_parent"
android:layout:height=match_parent">
<ListView android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:descendantFocusability="blocksDescendants"/>
</FrameLayout>
I'm trying to find solution how to create sub menu in navigation drawer. I will be the best to show example from iOS app video
I dont see any methods in navigation drawer documentation to do such layout animations. I will appreciate any help
there is not such concept called sub menu in navigation drawer on the android SDK.
but there are also good news - since Navigation Drawer is eventually layout container - nothing stops you from host inside of it any view or nested layout container you desire instead of host inside of it only ListView , and therefore - you can use also Fragments
if you'll do that - you could perform fragment transactions between them to swipe to another fragment representing the sub menu... also you'll get "for free" the fragment transaction animation, if you'll set it to use one.
each fragment would show ListView (or whatever..) representing different menu screen
add to it you own UI back button header and implement the onClick callback to perform fragment transaction to the "main menu" fragment, and you've got exactly what you want.
this is how your main activity UI xml layout file should look like:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<FrameLayout android:id="#+id/left_drawer_layout_fragment_conatiner"
android:layout_width="240dp"
android:layout_height="match_parent"
android:background="#111"/>
as you see, I replaces the traditional navigation drawer ListView with a FrameLayout. the left drawer can be replaced with any other view or custom component you want, and can act also as fragment container.
EDIT
#Meryl requested from me to show based on the documentation example how I use Fragment as drawer menu. so, assuming you want that your menu would look exactly like the documentation example (which is not must at all because you can make any UI you wish..) this would be the way to translate it into Fragment:
the fragment_menu.xml layout file:
<ListView android:id="#+id/list_view"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
the FragmentMenu java class:
public class FragmentMenu extends Fragment {
private ListView mListView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_menu, null);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mListView = (ListView)view.findViewById(R.id.list_view);
// Set the adapter for the list view
mListView.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mPlanetTitles));
// Set the list's click listener
mListView.setOnItemClickListener(new DrawerItemClickListener());
}
}
attaching the FragmentMenu to the Activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView...
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.left_drawer_layout_fragment_conatiner, new FragmentMenu());
.commit();
}
all the rest should stat almost the same.. and of course - the code in the documentation that creates the menu list and setting the adapter in the activity is not necessary anymore, because it's implemented inside the fragment instead.
I am trying to implement an Action Bar with Tabs navigation set using ActionBarSherlock. I currently have three tabs which I can switch between ok. On one of my tabs I am implementing a ListView. When one of the items in the list is selected I want to replace the list with another fragment which will be a detail view of the selection.
When I call the FragmentTransaction.replace method with the new detail fragment I can see the new fragment appear but it overlaps the ListView, meaning I can see both fragments. Is this kind of navigation possible using the ActionBar tabs navigation, or am I on completely the wrong lines. I feel I am missing something really fundamental here.
I have a SherlockFragmentActivity which is implementing a TabListener to handle moving between tabs. The fragment hosting the ListView inherits from SherlockListFragment and I have attached a OnItemClickListener to respond to the tap and to replace the fragment. I am using this code
numbersList.setOnItemClickListener(new ListView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int i, long l) {
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(android.R.id.content, new NumberSelectedNavigationMenuFragment());
ft.commit();
}
});
The fragment which is replacing the ListView is currently just a basic LinearLayout with a TextView.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Test"
android:id="#+id/textView"/>
</LinearLayout>
Any help appreciated with this as I am well and truly stuck ...