Menu item not visible in Fragment - android

I would like to show a menu in my fragment. I've done this a million times, yet it is not working now for some reason. This is the first time I experiment with the new androidx library, maybe bug?
Fragment:
public class FragmentDogs extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_dogs, container, false);
setHasOptionsMenu(true);
return rootView;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_dogs, menu);
}
}
Activity:
public class ActivityMain extends AppCompatActivity {
Toolbar toolbar;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new FragmentDogs()).commit();
}
}
Menu:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/dogs_add_menu_item"
android:icon="#drawable/ic_plus"
android:title="#string/dogs" />
Gradle:
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.platinum"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
implementation 'com.google.android.gms:play-services-maps:16.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
Screenshot:

You have to set the custom toolbar to the Fragment Layout and as SupportActionBar.
Your Fragment Layout
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="#color/colorPrimary"
android:elevation="5dp"
android:minHeight="?attr/actionBarSize"
app:contentInsetEnd="50dp"
app:contentInsetRight="50dp"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
android:title="testtext"
app:contentInsetStartWithNavigation="0dp">
</android.support.v7.widget.Toolbar>
Your Fragment class
public class YourFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.yourfragmentlayout, container, false);
setHasOptionsMenu(true);
Toolbar toolbar = (Toolbar)rootView.findViewById(R.id.toolbar);
((AppCompatActivity)getActivity()).setSupportActionBar(toolbar);
((AppCompatActivity)getActivity()).getSupportActionBar().setTitle("YourFragment");
return rootView;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_dogs, menu);
super.onCreateOptionsMenu(menu, inflater);
}
}
If YourFragment() is red underlined
Make sure that you are using
import android.support.v4.app.Fragment;
instead of
import android.app.Fragment;

you are missing the closing tag on menu.xml, which possibly should end with </menu>.
the testInstrumentationRunner is not the correct test-runner for androidx, along with the other test dependencies. androidx.fragment:fragment:1.0.0 would be the proper dependency for the Fragment class. see the migration guide for further androidx dependencies, which you might be lacking; alike androidx.appcompat:appcompat:1.0.2 for the AppCompatActivity.
it might be a X/Y problem... first fix the dependencies - and then the menu.

Related

BottomAppBar 4 Icons not align properly

how can I align the icons properly as it?
This is my activity main xml with bottom app bar and floating action button.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
tools:context=".activities.MainActivity">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/fragmentview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottom_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:backgroundTint="#color/bluPrincipale"
app:fabAlignmentMode="center"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_icona_menu_mappa"
app:layout_anchor="#id/bottom_app_bar" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
This is my activity main that make work for fragments I think.
MainActivity.java
package com.example.test.activities;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.example.test.R;
import com.example.test.fragments.ConvenzioniFragment;
import com.example.test.fragments.DoveAndareFragment;
import com.example.test.fragments.HomeFragment;
import com.example.test.fragments.MappaFragment;
import com.example.test.fragments.MoreFragment;
import com.google.android.material.bottomappbar.BottomAppBar;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
public class MainActivity extends AppCompatActivity {
private FloatingActionButton floatingActionButton;
private BottomAppBar bottomAppBar;
private boolean isFabTabbed = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
floatingActionButton = findViewById(R.id.fab);
bottomAppBar = findViewById(R.id.bottom_app_bar);
setSupportActionBar(bottomAppBar);
if(savedInstanceState == null) {
handleFrame(new HomeFragment());
}
handleFab();
}
private void handleFab() {
floatingActionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
isFabTabbed = !isFabTabbed;
if(isFabTabbed) {
handleFrame(new MappaFragment());
}
else
{
handleFrame(new HomeFragment());
}
}
});
}
private void handleFrame(Fragment fragment) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
fragmentTransaction.replace(R.id.fragmentview, fragment);
fragmentTransaction.commit();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.bottomappbar_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch(item.getItemId()) {
case R.id.app_bar_home:
handleFrame(new HomeFragment());
return true;
case R.id.app_bar_dove_andare_sagre_eventi:
handleFrame(new DoveAndareFragment());
return true;
case R.id.app_bar_convenzioni:
handleFrame(new ConvenzioniFragment());
return true;
case R.id.app_bar_more:
handleFrame(new MoreFragment());
return true;
}
return super.onOptionsItemSelected(item);
}
}
This is my custom bottom app bar menu.
bottomappbar_menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="#+id/app_bar_home"
android:icon="#drawable/ic_icona_menu_home"
android:title="Home"
app:showAsAction="always"
/>
<item
android:id="#+id/app_bar_dove_andare_sagre_eventi"
android:icon="#drawable/ic_icona_menu_dove_andare_sagre_eventi"
android:title="Dove Andare"
app:showAsAction="always"
/>
<item
android:id="#+id/app_bar_convenzioni"
android:icon="#drawable/ic_icona_menu_convenzioni"
android:title="Convenzioni"
app:showAsAction="always"
/>
<item
android:id="#+id/app_bar_more"
android:icon="#drawable/ic_icona_menu_more"
android:title="More"
app:showAsAction="always"
/>
</menu>
This is my gradle code. It's correct for me.
Gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.example.test"
minSdkVersion 16
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.google.android.material:material:1.1.0-beta01'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
But the bottom bar result not is as this:
picture correct
It's mine result :|
mineresult
I'm using latest material design.
Thanks for any helps!
Cris
Remove menu from BottomAppBar and add it in BottomNavigationView then add BottomNavigationView inside BottomAppBar, like this:
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="#+id/fragmentview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottom_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:fabAlignmentMode="center">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
style="#style/MyBottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:itemIconTint="#color/selector_bottom_navigation"
app:itemTextColor="#color/selector_bottom_navigation"
app:labelVisibilityMode="labeled"
app:menu="#menu/activity_home_bottom_nav" />
</com.google.android.material.bottomappbar.BottomAppBar>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic__right_arrow"
app:layout_anchor="#id/bottom_app_bar" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
If you do this, your items will appear in centre according to your expectation, but you may experience that icon of 2nd and 3rd item overlapped by FAB, to refrain from this situation, add an empty item in centre of your menu, like this:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/itemRenewals"
android:icon="#drawable/menu_renewals"
android:title="Renewals" />
<item
android:id="#+id/itemViewOwner"
android:icon="#drawable/menu_view_owner"
android:title="View User" />
<item
android:id="#+id/itemEmpty"
android:title=""/>
<item
android:id="#+id/itemEnquiry"
android:icon="#drawable/menu_enquiry"
android:title="Enquiry" />
<item
android:id="#+id/itemProfile"
android:icon="#drawable/menu_profile"
android:title="Profile" />
</menu>
Add this in your class,This code must solve your alignment problem
#SuppressLint("RestrictedApi")
private void disableShiftMode(BottomNavigationView view) {
BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
try {
Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
shiftingMode.setAccessible(true);
shiftingMode.setBoolean(menuView, false);
shiftingMode.setAccessible(false);
for (int i = 0; i < menuView.getChildCount(); i++) {
BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
item.setShiftingMode(false);
// set once again checked value, so view will be updated
item.setChecked(item.getItemData().isChecked());
}
} catch (NoSuchFieldException e) {
Log.e("BNVHelper", "Unable to get shift mode field", e);
} catch (IllegalAccessException e) {
Log.e("BNVHelper", "Unable to change value of shift mode", e);
}
}

Android App crash, can't figure out the issue [duplicate]

This question already has answers here:
Getting android.content.res.Resources$NotFoundException: exception even when the resource is present in android
(16 answers)
Closed 4 years ago.
I have 2 phones, 1 samsung S8 running v8.0 and a LG G4 running v6.0. I have both plugged into the same computer and build the app and run it on the phones. All seems good on the Samsung, and all installs and seems good on the LG until I press the menu button on the first Activity.
My first activity loads a fragment which puts the 3 dot menu in the top right. I only have 1 item in the menu which opens a new activity that has a list of items to select from. On the LG when this 3 dot menu is pressed, the app crashes, but on the S8, it opens the menu and allows me to select the 1 item and open the next activity.
Looking for any ideas on where to go with this.
The Error I get:
I/ViewRootImpl: ViewRoot's Touch Event : ACTION_DOWN
I/ViewRootImpl: ViewRoot's Touch Event : ACTION_UP
I/AudioManagerEx: AudioManagerEx created
I/ListPopupWindow: Could not find method setEpicenterBounds(Rect) on PopupWindow. Oh well.
W/ResourceType: Failure getting entry for 0x7f07013a (t=6 e=314) (error -75)
D/AndroidRuntime: Shutting down VM
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.czdev.booktimeline, PID: 15910
android.content.res.Resources$NotFoundException: Resource ID #0x7f07013a
at android.content.res.Resources.getValue(Resources.java:1401)
at android.support.v7.widget.AppCompatDrawableManager.loadDrawableFromDelegates(AppCompatDrawableManager.java:332)
at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:197)
at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:190)
at android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:100)
at android.support.v7.view.menu.MenuItemImpl.getIcon(MenuItemImpl.java:425)
at android.support.v7.view.menu.ListMenuItemView.initialize(ListMenuItemView.java:116)
at android.support.v7.view.menu.MenuAdapter.getView(MenuAdapter.java:100)
at android.support.v7.view.menu.MenuPopup.measureIndividualMenuWidth(MenuPopup.java:160)
at android.support.v7.view.menu.StandardMenuPopup.tryShow(StandardMenuPopup.java:153)
at android.support.v7.view.menu.StandardMenuPopup.show(StandardMenuPopup.java:187)
at android.support.v7.view.menu.MenuPopupHelper.showPopup(MenuPopupHelper.java:290)
at android.support.v7.view.menu.MenuPopupHelper.tryShow(MenuPopupHelper.java:175)
at android.support.v7.widget.ActionMenuPresenter$OpenOverflowRunnable.run(ActionMenuPresenter.java:803)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5525)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Application terminated.
Here is my Gradle:
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.oss.licenses.plugin'
android {
compileSdkVersion 27
defaultConfig {
applicationId "<com.android.application>"
minSdkVersion 21
targetSdkVersion 27
versionCode 25
versionName "0.8"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.google.android.gms:play-services-oss-licenses:15.0.1'
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:cardview-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
implementation 'com.android.support:support-vector-drawable:27.1.1'
implementation 'com.android.support:support-v4:27.1.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.github.bumptech.glide:glide:4.7.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.7.1'
}
repositories {
mavenCentral()
}
Here is my first fragment:
public class HomeFrag extends Fragment {
View rootView;
public HomeFrag() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_home, container, false);
Toolbar toolbar = (Toolbar) rootView.findViewById(R.id.toolbar);
toolbar.setTitle(R.string.app_name);
((MainActivity) Objects.requireNonNull(getActivity())).setSupportActionBar(toolbar);
setHasOptionsMenu(true);
return rootView;
}
#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) {
int id = item.getItemId();
if (id == R.id.menu_action_info) {
startActivity(new Intent(getContext(), InfoMenu.class));
return true;
}
return super.onOptionsItemSelected(item);
}
}
Here is my menu:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="#+id/menu_action_info"
android:icon="#drawable/ic_info_outline_white_24dp"
android:orderInCategory="100"
android:title="#string/menu_info_action"
app:showAsAction="never" />
</menu>
Any ideas would be great.
From the crash logs , it seems its failing to load the icon
at android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:100)
at android.support.v7.view.menu.MenuItemImpl.getIcon(MenuItemImpl.java:425)
Can you please check your R.java for Resource ID #0x7f07013a , it will tell you exactly which resource is failing to load, my guess is the icon is missing in a particular drawable folder.
Ankit

Android Toolbar return button didn't work after adding productFlavors

Before adding productFlavors in build.gradle(Module:app), the return button in Toolbar works.
But once I added productFlavors into build.gradle(Module:app) for Build >> Generate Signed APK..., the return button become invalid.
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.comp548.note">
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme"
tools:ignore="AllowBackup,GoogleAppIndexingWarning">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".NoteEditActivity">
<meta-data android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
</activity>
</application>
</manifest>
build.gradle(Module:app) after adding productFlavors:
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "com.comp548.note"
minSdkVersion 19
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
productFlavors {
free {
applicationId "com.comp548.note.free"
versionName "1.0-free"
}
paid {
applicationId "com.comp548.note.paid"
versionName "1.0-paid"
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:design:24.2.0'
}
toolbar.xml in layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#color/colorPrimary"
app:theme="#style/ThemeOverlay.AppCompat.Dark"
app:popupTheme="#style/ThemeOverlay.AppCompat.Light"
tools:ignore="Overdraw">
</android.support.v7.widget.Toolbar>
activity_note_edit.xml in layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.comp548.note.NoteEditActivity">
<include layout="#layout/toolbar"
android:id="#+id/note_edit_toolbar" />
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="#dimen/fragment_margin"
android:name="com.comp548.note.NoteEditFragment"
android:id="#+id/fNoteEdit"
android:layout_centerHorizontal="true"
tools:layout="#layout/fragment_note_edit"
android:layout_below="#id/note_edit_toolbar"/>
</RelativeLayout>
MainActivity.java:
package com.comp548.note;
import android.content.Intent;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar)findViewById(R.id.note_list_toolbar);
// Set the Toolbar to act as the ActionBar for this Activity window
setSupportActionBar(toolbar);
if(getSupportActionBar() != null) {
getSupportActionBar().setTitle(R.string.toolbar_title);
}
getSupportActionBar().setIcon(R.drawable.ic_toolbar);
FloatingActionButton fabAdd = (FloatingActionButton)findViewById(R.id.fabAdd);
fabAdd.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, NoteEditActivity.class);
startActivity(intent);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.menu_exit:
finish();
break;
}
return super.onOptionsItemSelected(item);
}
}
NoteEditActivity.java:
package com.comp548.note;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
public class NoteEditActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_note_edit);
Toolbar toolbar = (Toolbar)findViewById(R.id.note_edit_toolbar);
// Set the Toolbar to act as the ActionBar for this Activity window
setSupportActionBar(toolbar);
// Enable return button
if(getSupportActionBar() != null) {
getSupportActionBar().setHomeButtonEnabled(true);
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
Intent intent = getIntent();
NoteEntity noteEntity = (NoteEntity) intent.getSerializableExtra("noteEntity");
// Set values for Views in NoteEditFragment
if (noteEntity != null) {
NoteEditFragment noteEditFragment = (NoteEditFragment)getSupportFragmentManager().findFragmentById(R.id.fNoteEdit);
noteEditFragment.setValues(noteEntity);
}
}
}
App screenshots:
After remove the productFlavors from build.gradle(Module:app) the return button works again.
Why the return button on Toolbar didn't work after adding productFlavors.
How to fix it if I still want to add productFlavors?
Okay in your NoteEditActivity add the callback method onOptionsItemSelected(MenuItem item) and do the following:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
onBackPressed();
break;
}
return super.onOptionsItemSelected(item);
}
It should fix your issue, allowing the toolbar back button to execute the action of the back button. Hope this helps.
Reason: You put different applicationId for each flavor.
In manifest you set metadata for parent activity, but during building flavor all packages are automatically moved to package com.comp548.note.free or com.comp548.note.paid. Your metadata points to com.comp548.note.MainActivity though your actual activity is located under com.comp548.note.paid|free.MainActivity.
Solutions:
Create separate manifests for each flavor with metadata points to correct packages.
Handle it at runtime like KudzieChase described.

Error inflating class Fragment when testing fragment using DataBinding

Can someone help me on this? In my test I want to check if the login button is displayed on the StartPage.
I've been struggling with this error for a while today and I don't know how it should be resolved.What am I missing here?
Maybe this problem is somehow similar to this question:
Espresso test fails with java.lang.String cannot be cast to com.abc.events.databinding.SponsorDetailBinding
android.view.InflateException: Binary XML file line #6: Error inflating class fragment
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:770)
at android.view.LayoutInflater.inflate(LayoutInflater.java:483)
at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
at android.view.LayoutInflater.inflate(LayoutInflater.java:366)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:256)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:109)
at io.turbela.turbela.login.view.StartActivity.onCreate(StartActivity.java:16)
at android.app.Activity.performCreate(Activity.java:6289)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.support.test.runner.MonitoringInstrumentation.callActivityOnCreate(MonitoringInstrumentation.java:532)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2655)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767)
at android.app.ActivityThread.access$900(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5951)
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:1400)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void io.turbela.turbela.databinding.FragmentStartBinding.setViewModel(io.turbela.turbela.login.viewmodel.DispatchViewModel)' on a null object reference
at io.turbela.turbela.StartActivityFragment.onCreateView(StartActivityFragment.java:34)
at android.app.Fragment.performCreateView(Fragment.java:2114)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:875)
at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1060)
at android.app.FragmentManagerImpl.addFragment(FragmentManager.java:1162)
at android.app.FragmentManagerImpl.onCreateView(FragmentManager.java:2131)
at android.app.Activity.onCreateView(Activity.java:5610)
at android.support.v4.app.BaseFragmentActivityHoneycomb.onCreateView(BaseFragmentActivityHoneycomb.java:34)
at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:79)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:740)
... 20 more
LoginTest.java
#RunWith(AndroidJUnit4.class)
public class LoginTest {
#Rule
public ActivityTestRule<StartActivity> mActivityRule = new ActivityTestRule(StartActivity.class);
#Test
public void displayLoginPage() {
onView(withId(R.id.login_button)).check(matches(isDisplayed()));
}
}
StartActivity.java
public class StartActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
}
...onCreateOptionsMenu(...
...onOptionsItemSelected(...
}
activity_start.xml
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment"
class="io.turbela.turbela.StartActivityFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
StartActivityFragment.java
public class StartActivityFragment extends Fragment {
public StartActivityFragment() {
}
public static StartActivityFragment newInstance(){
Bundle args = new Bundle();
args.putString("key", "value");
StartActivityFragment fragment = new StartActivityFragment();
fragment.setArguments(args);
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
FragmentStartBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_start, container, false);
binding.setViewModel(new DispatchViewModel());
return binding.getRoot();
}
}
fragment_start.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="viewModel" type="io.turbela.turbela.login.viewmodel.DispatchViewModel" />
</data>
<RelativeLayout
style="#android:style/Theme.Holo"
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">
<Button
android:id="#+id/login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:layout_marginTop="128dp"
android:onClick="#{viewModel.onClickLogin}"
android:text="#string/login" />
</RelativeLayout>
</layout>
DispatchViewModel.java
public class DispatchViewModel extends BaseObservable{
public View.OnClickListener onClickLogin() {
//loginWithEmail
return v -> Log.d("H", "onClickLogin");
}
}
build.gradle
apply plugin: 'com.android.application'
apply plugin: 'me.tatarka.retrolambda'
android {
compileSdkVersion 23
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "io.turbela.turbela"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
dataBinding{
enabled = true
}
packagingOptions {
exclude 'LICENSE.txt'
}
lintOptions {
abortOnError false
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:cardview-v7:23.1.1'
compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.parse:parse-android:1.12.0'
compile 'com.parse.bolts:bolts-android:1.3.0'
compile 'com.facebook.android:facebook-android-sdk:4.8.1'
compile 'com.parse:parsefacebookutils-v4-android:1.10.3#aar'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
androidTestCompile 'com.android.support.test:runner:0.5'
}
There is android:name attribute missing from <fragment> tag in your activity_start.xml
As per the docs, you must include it.
So your activity.start.xml should look like this:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment"
android:name="io.turbela.turbela.StartActivityFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Note:
The class= attribute you are trying to use is for custom Views as in here

findViewById(R.id.tabhost) always return null

I have an app in Google play already and has no problem at all until I upgrade my Android Studio. The build.gradle has to be modified so that the project can be compiled Here is what I changed:
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
compile 'com.android.support:appcompat-v7:21.0.0'
compile 'com.google.android.gms:play-services:6+'
compile 'com.android.support:support-v4:+'
}
The only change is com.android.support:appcompat-v7:+ which is changed to com.android.support:appcompat-v7:21.0.0.
My problem is the .findViewById(R.id.tabhost) always return null so that the application crashes. Here is my layout file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.app.FragmentTabHost xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent" >
My java code:
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTabHost;
public class MenuLeftFragment extends Fragment {
private FragmentTabHost mFragmentTabHost;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mView = getView();
if (mView != null) {
mFragmentTabHost = (FragmentTabHost) mView
.findViewById(R.id.tabhost);
Any idea? Thanks.
You should do this in onCreateView() where you should define as follows :
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.your_layout, container, false);
mFragmentTabHost = (FragmentTabHost) v.findViewById(R.id.tabhost);
return v;
}
If you want to keep this code, the getView() on the onActivityCreated() is wrong, if you have a view on your onCreate() you can do something like :
mView = v;
Then in your onActivityCreated() instead of call getView() use mView
Then it should work.

Categories

Resources