When using the [recommended code][1] to start a fragment at launch, it displays properly on a virtual device running Android 5.0 but doesn't display on a phone running 4.4.2.
I've created the activity using mostly auto generated code from Android Studio.
The Toast in the fragment gets activated on the phone, so I know the fragment is being started. It's just not being displayed on the phone for some reason.
Any help getting it to run would be appreciated.
Here's the Activity code:
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.widget.Toast;
public class MainActivity extends ActionBarActivity implements NavigationDrawerCallbacks, UserOverviewFragment.OnFragmentInteractionListener {
private static final String PREF_FIRST_RUN = "false";
private Toolbar mToolbar;
private NavigationDrawerFragment mNavigationDrawerFragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mToolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
// TODO: get this working.
// Check that the activity is using the layout version with
// the fragment_container FrameLayout
if (findViewById(R.id.container) != null) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (savedInstanceState != null) {
return;
}
// Create a new Fragment to be placed in the activity layout
UserOverviewFragment firstFragment = new UserOverviewFragment();
// In case this activity was started with special instructions from an
// Intent, pass the Intent's extras to the fragment as arguments
// firstFragment.setArguments(getIntent().getExtras());
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.container, firstFragment).commit();
}
// TODO: Do something the first time the app is started.
mNavigationDrawerFragment = (NavigationDrawerFragment) getFragmentManager().findFragmentById(R.id.fragment_drawer);
mNavigationDrawerFragment.setup(R.id.fragment_drawer, (DrawerLayout) findViewById(R.id.drawer), mToolbar);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// TODO: invalidate menu as soon as the drawer slides a certain amount
if(mNavigationDrawerFragment.isDrawerOpen()) {
invalidateOptionsMenu();
}else
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public void onNavigationDrawerItemSelected(int position) {
Toast.makeText(this, "Menu item selected -> " + position, Toast.LENGTH_SHORT).show();
}
#Override
public void onBackPressed() {
if (mNavigationDrawerFragment.isDrawerOpen())
mNavigationDrawerFragment.closeDrawer();
else
super.onBackPressed();
}
public void changeMainFragment(){
}
public boolean checkForFirstRun(){
String firstRun = mNavigationDrawerFragment.readSharedSetting(getBaseContext(), PREF_FIRST_RUN, "true");
if(firstRun == "true"){
mNavigationDrawerFragment.saveSharedSetting(getBaseContext(), PREF_FIRST_RUN, "false");
return true;
}
else return false;
}
public void onFirstRun(){
// TODO: Stuff to do just once, the first time the app is run. Possibly not necessary.
// TODO: Delete this next line after testing.
Toast.makeText(this, "First Time!!", Toast.LENGTH_LONG).show();
}
private void determineStartingFragment() {
}
#Override
public void onFragmentInteraction(Uri uri) {
}
}
Activity Layout:
<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar_actionbar"
layout="#layout/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<android.support.v4.widget.DrawerLayout
android:id="#+id/drawer"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/toolbar_actionbar">
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:clickable="true"
android:layout_height="match_parent"/>
<!-- android:layout_marginTop="?android:attr/actionBarSize"-->
<fragment
android:id="#+id/fragment_drawer"
android:name="com.king_kingdom.mathiness.NavigationDrawerFragment"
android:layout_width="#dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
app:layout="#layout/fragment_navigation_drawer"
tools:layout="#layout/fragment_main" />
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
Fragment code:
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link UserOverviewFragment.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link UserOverviewFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class UserOverviewFragment extends Fragment {
// 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;
private OnFragmentInteractionListener mListener;
/**
* 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 user_overview.
*/
// TODO: Rename and change types and number of parameters
public static UserOverviewFragment newInstance(String param1, String param2) {
UserOverviewFragment fragment = new UserOverviewFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
public UserOverviewFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
Toast.makeText(getActivity().getBaseContext(),"This is the User Overview Fragment", Toast.LENGTH_LONG).show();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_user_overview, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
Fragment Layout:
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.king_kingdom.mathiness.UserOverviewFragment">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="User Overview"
android:textSize="#dimen/abc_text_size_large_material"
android:longClickable="false"
android:layout_marginTop="109dp" />
</LinearLayout>
UPDATE: Gradle file
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.king_kingdom.toolbar_test"
minSdkVersion 15
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
}
Thanks #papium for uploading the build.gradle. For now, I would suggest changing in that file:
From: compile 'com.android.support:appcompat-v7:21.0.3'
To: compile ‘com.android.support:appcompat-v7:**18.0.0**
However this impacts the API 21 and future Android versions. Another, maybe you can see the NavigationDrawer but not your ActionBar.
In the end, it was a simple problem of styling. In my style code, I had accidentally assigned both the background and the text color as white. Which means, of course, that you couldn't see it.
I'm not quite sure why it was showing in the emulator except that there was possibly a default style in API v21 that skirted my app.theme.
Related
I'm developing an app with many fragments and each fragment has a button by default in the top-left corner. When I press that small button nothing happens. How can I remove it?
Thanks!
I didn't try anything, but I was thinking that I have to remove the onButtonPressed method, but I'm not sure
This is the code of a fragment
package com.flixarts.ar.*;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link schoolfragment0.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link schoolfragment0#newInstance} factory method to
* create an instance of this fragment.
*/
public class schoolfragment0 extends Fragment {
// 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;
private OnFragmentInteractionListener mListener;
public schoolfragment0() {
// 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 schoolfragment0.
*/
// TODO: Rename and change types and number of parameters
public static schoolfragment0 newInstance(String param1, String param2) {
schoolfragment0 fragment = new schoolfragment0();
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);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_schoolfragment0, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
I want to delete the button that's grey in the top left corner
This is the XML
<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=".schoolfragment0">
<!-- TODO: Update blank fragment layout -->
<TextView
android:id="#+id/espacioFrases"
android:layout_width="325dp"
android:layout_height="111dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="150dp"
android:text=""
android:textColor="#color/ColorPrimary"
android:textSize="36sp" />
<TextView
android:id="#+id/espacioFrasesTraducidas"
android:layout_width="307dp"
android:layout_height="103dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="360dp"
android:text=""
android:textColor="#color/ColorPrimary"
android:textSize="36sp" />
</FrameLayout>
In the XML I have two textviews (I've covered, sorry, I can't find where is that button)
I have a navigation drawer app consist of 5 fragment on the drawer. I want to put google maps v2 activity inside the HomeFragment (the first and default fragment of navigation drawer), but first i tried to put everything it should be on MainActivity on java and activity_main on xml and everything was running well. But i'd like to put it on HomeFragment only, not at whole fragment, so i move the googleMaps code lines from MainActivity to HomeFragment activity and it gone error.
Here is my java code:
package com.mage.unjukrasaid.navigationdrawer.fragment;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.SupportMapFragment;
import com.mage.unjukrasaid.R;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link HomeFragment.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link HomeFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class HomeFragment extends Fragment {
// 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";
// Google Map
private GoogleMap googleMap;
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnFragmentInteractionListener mListener;
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);
}
try {
// Loading map
initilizeMap();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onResume() {
super.onResume();
initilizeMap();
}
/**
* function to load map. If map is not created it will create it for you
* */
private void initilizeMap() {
if (googleMap == null) {
googleMap = ((SupportMapFragment) getActivity().getSupportFragmentManager().findFragmentById(
R.id.map)).getMap();
// check if map is created successfully or not
if (googleMap == null) {
Toast.makeText(getActivity().getApplicationContext(),
"Sorry! unable to create maps", Toast.LENGTH_SHORT)
.show();
}
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_home, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
// if (context instanceof OnFragmentInteractionListener) {
// mListener = (OnFragmentInteractionListener) context;
// } else {
// throw new RuntimeException(context.toString()
// + " must implement OnFragmentInteractionListener");
// }
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
And here is my xml code fragment_home:
<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.mage.unjukrasaid.navigationdrawer.fragment.HomeFragment">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:src="#drawable/mapss" />
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.SupportMapFragment"/>
</FrameLayout>
On the logcat, here is what it said:
02-02 17:41:12.983 3491-3491/com.mage.unjukrasaid E/AndroidRuntime:
FATAL EXCEPTION: main
Process: com.mage.unjukrasaid, PID: 3491
java.lang.NullPointerException: Attempt to invoke virtual method
'com.google.android.gms.maps.GoogleMap
com.google.android.gms.maps.SupportMapFragment.getMap()' on a null
object reference
at
com.mage.unjukrasaid.navigationdrawer.fragment.HomeFragment.initilizeMap(HomeFragment.java:92)
at
com.mage.unjukrasaid.navigationdrawer.fragment.HomeFragment.onResume(HomeFragment.java:83)
at android.support.v4.app.Fragment.performResume(Fragment.java:2238)
at
android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1346)
at
android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
at
android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
at
android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:758)
at
android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2363)
at
android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2149)
at
android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(FragmentManager.java:2103)
at
android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2013)
at
android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:710)
at android.os.Handler.handleCallback(Handler.java:815)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:194)
at android.app.ActivityThread.main(ActivityThread.java:5546)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:967)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762)
it said on HomeFragment line 92 and 83, but i don't know what makes it error
May be you guys have a brilliant solution, i will appreciate it :)
Try using getChildFragmentManager() instead of getSupportFragmentManager() as you're inside a Fragment. SO your code shoud be:
private void initilizeMap() {
if (googleMap == null) {
googleMap = ((SupportMapFragment) this.getChildFragmentManager().findFragmentById(
R.id.map)).getMap();
// check if map is created successfully or not
if (googleMap == null) {
Toast.makeText(getActivity().getApplicationContext(),
"Sorry! unable to create maps", Toast.LENGTH_SHORT)
.show();
}
}
}
Has been a while since I worked with Google's MAP API. But as far as I can remember I used to do things slightly diferente. First, assuming that your using Android Studio IDE.
Right click on your main package -> New -> Google > Google Maps Activity.
This will create Activity that inherits from "FragmentActivity" and implements OnMapReadyCallBack.
Now, make your Fragment.Class a SupportMapFragment's subclass.
Know that you have an superficial overview, go to the API's documentation to deeper details.
So what I want to do is something like this
Select a item from NavigationView
remove activity_main's content
load and show the fragment I've selected
For example:
I selected "Homepage" in NavigationView which should load Homepage.class
Load the fragment_homepage.xml
remove everything in activity_main.xml
What I am getting trouble is, no matter what I've selected in NavigationView, it shows up BOTH fragment_(whatIhaveSelected).xml and activity.xml which I don't want to.
Code:
MainActivity class
package to.epac.factorycraft.drawerlayouttest;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private DrawerLayout drawerLayout;
private NavigationView navigationView;
private Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
navigationView = (NavigationView) findViewById(R.id.navigationView);
toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
drawerLayout.closeDrawer(GravityCompat.START);
int id = item.getItemId();
Fragment myFragment = null;
Class fragmentClass = null;
switch (id) {
case R.id.homepage:
fragmentClass = Homepage.class;
break;
case R.id.station:
fragmentClass = Station.class;
break;
default:
fragmentClass = Homepage.class;
navigationView.setCheckedItem(R.id.homepage);
Toast.makeText(MainActivity.this, "default Homepage clicked", Toast.LENGTH_LONG).show();
break;
}
try {
myFragment = (Fragment) fragmentClass.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction ft = fragmentManager.beginTransaction();
ft.replace(R.id.flcontent, myFragment).commit();
item.setCheckable(true);
setTitle(item.getTitle());
drawerLayout.closeDrawers();
// TODO
// If first open app, it will show "app_name", but when clicked on "Homepage", it will show "主頁", waiting to fix
toolbar.setTitle(item.getTitle());
return true;
}
});
}
#Override
public void onBackPressed() {
if (this.drawerLayout.isDrawerVisible(GravityCompat.START)) {
this.drawerLayout.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout 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/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="to.epac.factorycraft.drawerlayouttest.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:title="#string/app_name" />
<FrameLayout
android:id="#+id/flcontent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:orientation="vertical">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:text="activity_main's textView" />
</FrameLayout>
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="#+id/navigationView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="#layout/header"
app:menu="#menu/drawer">
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>
Homepage class
package to.epac.factorycraft.drawerlayouttest;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link Homepage.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link Homepage#newInstance} factory method to
* create an instance of this fragment.
*/
public class Homepage extends Fragment {
// 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;
private OnFragmentInteractionListener mListener;
public Homepage() {
// 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 Homepage.
*/
// TODO: Rename and change types and number of parameters
public static Homepage newInstance(String param1, String param2) {
Homepage fragment = new Homepage();
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);
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_homepage, container, false);
Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_homepage, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
fragment_homepage.xml
<LinearLayout 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"
android:orientation="vertical"
tools:context="to.epac.factorycraft.drawerlayouttest.Homepage"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
<!-- TODO: Update blank fragment layout -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Homepage Fragment" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</LinearLayout>
I have a fragment_main.xml inside an activity_main.xml.
The fragment is added inside a Tabbed Activity created from an Android Studio template.
I want to do a change in the Fragment's view from within the Activity. That's why I created an Interface that allows the Fragment to call the Activity during the Fragment's onStart, when I know that the Fragment's view is available for modifications.
I did get this to work if I pass the actual Fragment instance using my interface callback. But I'm still frustrated because I don't understand why this function returns null. Does this have anything to do with reusing fragments in different screen orientations?
I've looked over similar questions here on SO reported with this function returning null. Somebody mentioned that there might be an issue with using import android.support.v4.app.Fragment; as opposed to just android.app.Fragment. I don't think this is my case because getsupportFragmentManager seems to return the correct type of Fragment (v4.app). I have no idea why the v4.app is there, I'm kinda new to all this.
Anyway here's the code, all of it, including imports, because they might be relevant.
package org.axonnsd.musicnexus;
import android.app.Activity;
import android.content.Context;
import android.media.MediaPlayer;
import android.os.Environment;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.MediaController;
import android.widget.TextView;
import java.io.FileInputStream;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements OnFragmentReadyListener {
/**
* The {#link android.support.v4.view.PagerAdapter} that will provide
* fragments for each of the sections. We use a
* {#link FragmentPagerAdapter} derivative, which will keep every
* loaded fragment in memory. If this becomes too memory intensive, it
* may be best to switch to a
* {#link android.support.v4.app.FragmentStatePagerAdapter}.
*/
private SectionsPagerAdapter mSectionsPagerAdapter;
private static final String TAG = "MyTabbedApplication";
private Handler handler = new Handler();
/**
* The {#link ViewPager} that will host the section contents.
*/
private ViewPager mViewPager;
#Override
protected void onStop() {
super.onStop();
mediaController.hide();
mediaPlayer.stop();
mediaPlayer.release();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
//the MediaController will hide after 3 seconds - tap the screen to make it appear again
mediaController.show();
return false;
}
public void onFragmentReady(PlaceholderFragment fragment)
{
this.getIntent().putExtra(AUDIO_FILE_NAME,AUDIO_FILE_NAME);
audioFile = this.getIntent().getStringExtra(AUDIO_FILE_NAME);
PlaceholderFragment fragment = (PlaceholderFragment)(getSupportFragmentManager().findFragmentById(R.id.main_audio_view));
//FRAGMENT IS NULL!
fragment.setNowPlayingText(audioFile);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
private TextView _txtNowPlaying;
private MainActivity _parentActivity;
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
_txtNowPlaying = (TextView)rootView.findViewById(R.id.now_playing_text);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
//notifyActivity(_parentActivity);
return rootView;
}
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
_parentActivity = (MainActivity)activity;
}
#Override
public void onAttach(Context context)
{
super.onAttach(context);
if (context instanceof Activity){
_parentActivity = (MainActivity)context;
}
}
#Override
public void onStart()
{
super.onStart();
notifyActivity(_parentActivity);
}
private void notifyActivity(MainActivity activity)
{
activity.onFragmentReady(this);
}
public void setNowPlayingText(String value)
{
_txtNowPlaying.setText(value);
}
}
/**
* A {#link FragmentPagerAdapter} that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
// Show 3 total pages.
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "SECTION 1";
case 1:
return "SECTION 2";
case 2:
return "SECTION 3";
}
return null;
}
}
}
I'm pasting the XMLs too, even though they are fine (as I said, it works if I pass the actual fragment).
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="org.axonnsd.musicnexus.MainActivity">
<android.support.design.widget.AppBarLayout
android:id="#+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="#dimen/appbar_padding_top"
android:theme="#style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="#style/AppTheme.PopupOverlay">
</android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="#dimen/fab_margin"
app:srcCompat="#android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
fragment_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="#+id/main_audio_view"
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="org.axonnsd.musicnexus.MainActivity$PlaceholderFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Now playing:"
android:textSize="25sp"
android:textStyle="bold"
/>
<TextView
android:id="#+id/now_playing_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:layout_gravity="center"
android:text="Now playing.."
android:textSize="16sp"
android:textStyle="italic"
/>
<TextView
android:id="#+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
First of all, you're using findFragmentById wrong, passing id of root layout of your fragment as a parameter, when it expects an id of a layout that contains your fragment (not layout inside a fragment!)
FragmentPagerAdapter is kinda tricky and getting current fragment is not straightforward. Check this answer:
Getting the current Fragment instance in the viewpager
Replace your:
PlaceholderFragment fragment = (PlaceholderFragment)(getSupportFragmentManager().findFragmentById(R.id.main_audio_view));
//FRAGMENT IS NULL!
with
PlaceholderFragment page = (PlaceholderFragment)
getSupportFragmentManager().findFragmentByTag("android:switcher:" +
R.id.container + ":" + mViewPager.getCurrentItem());
I would try the following, but I'm sure it's not the nicest solution.
I would pass the value of section_number instead of the PlaceholderFragment and get the fragment from the SectionPageAdapter. Something like this:
public void onFragmentReady(int position)
{
this.getIntent().putExtra(AUDIO_FILE_NAME,AUDIO_FILE_NAME);
audioFile = this.getIntent().getStringExtra(AUDIO_FILE_NAME);
PlaceholderFragment fragment = (PlaceholderFragment)mSectionsPagerAdapter.getItem(position);
fragment.setNowPlayingText(audioFile);
}
I'm having a problem with an app that I'm making with the main activity set as navigation drawer activity,
What I'm getting is that when i press an item in the navigation list, the fragment is not being replaced by the corresponding fragment.
The code for the replacement is the following:
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
Fragment objFragment = null;
if (id == R.id.nav_dashboard) {
objFragment = new Dashboard_fragment();
} else if (id == R.id.nav_myschedule){
objFragment = new Schedule_fragment();
} else if (id == R.id.nav_rides) {
objFragment = new Rides_fragment();
} else if (id == R.id.nav_vouchers) {
objFragment = new Vouchers_fragment();
} else if (id == R.id.nav_help) {
objFragment = new Help_fragment();
} else if (id == R.id.nav_settings) {
objFragment = new Settings_fragment();
}
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.content_frame, objFragment)
.commit();
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
where each fragment is the following:
package com.example.user.greenmiles;
import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {#link Fragment} subclass.
* Activities that contain this fragment must implement the
* {#link Dashboard_fragment.OnFragmentInteractionListener} interface
* to handle interaction events.
* Use the {#link Dashboard_fragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class Dashboard_fragment extends Fragment {
private OnFragmentInteractionListener mListener;
public static Dashboard_fragment newInstance() {
Dashboard_fragment fragment = new Dashboard_fragment();
return fragment;
}
public Dashboard_fragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
getActivity().setTitle("Dashboard");
return inflater.inflate(R.layout.fragment_dashboard_fragment, container, false);
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
mListener.onFragmentInteraction(uri);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
public void onFragmentInteraction(Uri uri);
}
}
And where the xml file corresponding to the main activity is the following:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include layout="#layout/app_bar_main" android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView android:id="#+id/nav_view"
android:layout_width="wrap_content" android:layout_height="match_parent"
android:layout_gravity="start" android:fitsSystemWindows="true"
app:headerLayout="#layout/nav_header_main" app:menu="#menu/activity_main_drawer" />
and the xml file corresponding to the fragments is the following:
<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.user.greenmiles.Dashboard_fragment">
<!-- TODO: Update blank fragment layout -->
<TextView android:layout_width="match_parent" android:layout_height="match_parent"
android:text="Dashboard"
android:textSize="16pt" />
Please I have been stuck in this for a couple of days without being able to solve it.
Thanks a lot
I've found the answer finally, it was not related to the coding, but instead to the xml file. The problem is specifically with the following block:
<include layout="#layout/app_bar_main" android:layout_width="match_parent"
android:layout_height="match_parent" />
The height property is taking all the space in the fragment, and this the included fragment in the frame layout wasn't showing. A modification can be done by changing match_parent to wrap_content and it will be solved.
Thank you guys anyways