I have a problem with ButterKnife library. My views stopped binding after syncing gradle - before it was working without any problem.
I attached some code.
build.gradle (app)
compile 'com.jakewharton:butterknife:8.6.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0'
MainActivity
public class MainActivity extends AppCompatActivity {
#BindView(R.id.navigation)
BottomNavigationView navigation;
private Fragment fragment;
private FragmentManager fragmentManager;
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.navigation_home:
fragment = new HomeFragment();
break;
case R.id.navigation_dashboard:
fragment = new GraphFragment();
break;
case R.id.navigation_notifications:
fragment = new ProfileFragment();
break;
}
final FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(R.id.content, fragment).commit();
return true;
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.setDebug(true);
ButterKnife.bind(this);
fragmentManager = getSupportFragmentManager();
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}}
ButterKnife logs
D/ButterKnife: Looking up binding for
com.example.azkb.instproject.refactor.MainActivity D/ButterKnife: Not
found. Trying superclass android.support.v7.app.AppCompatActivity
D/ButterKnife: MISS: Reached framework class. Abandoning search.
The problem occured when I added Kotlin to my project.
Solution:
kapt 'com.jakewharton:butterknife-compiler:8.7.0'
Thanks for downvoting :)
Related
So this is my main activity class
public class NewMainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener{
DrawerLayout drawerLayout;
NavigationView navigationView;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_main_activity);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
getWindow().setStatusBarColor(ContextCompat.getColor(this, R.color.purple_500));
BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, new HomeFragment()).commit();
bottomNav.setOnNavigationItemSelectedListener(navListener);
//NewNav
drawerLayout = findViewById(R.id.drawer_layout);
navigationView = findViewById(R.id.navView);
navigationView.bringToFront();
ActionBarDrawerToggle toggle=new ActionBarDrawerToggle(this,drawerLayout,toolbar,R.string.navigation_drawer_open,R.string.navigation_drawer_close);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
navigationView.setNavigationItemSelectedListener(this);
navigationView.setCheckedItem(R.id.mm_home);
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
Fragment selectedFragment = null;
switch (item.getItemId()){
case R.id.nav_home:
selectedFragment = new HomeFragment();
break;
case R.id.nav_faq:
selectedFragment = new FAQFragment();
break;
case R.id.nav_price:
selectedFragment = new PriceMarketFragment();
break;
case R.id.nav_news:
selectedFragment = new NewsFragment();
break;
}
getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, selectedFragment).commit();
return true;
}
};
I have a frame layout in my mainactivity xml which i have given ID fragment_container.
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="#id/appBarLayout"
app:layout_constraintBottom_toTopOf="#id/navBottom"/>
In bottom navigation, I have 4 fragments, in which 3 fragments (Home, Price and News), I have tablayouts (more fragments within fragments).
When the mainactivity starts (the application starts) i want all of the parent fragments and child fragments to be loaded. and then i only need to navigate through them.
How can i do this please help.
I have moved BottomNavigation codes from MainActivity to A class I have created for the BottomNaviction to make the code more organizing. When I moved the codes I got this error java.lang.RuntimeException: Unable to start activity ComponentInfo{com.moataz.mox/com.moataz.mox.ui.view.activity.MainActivity}: java.lang.IllegalStateException: FragmentManager has not been attached to a host. Short error message FragmentManager has not been attached to a host.
And The error In this line of code
// The error is here
final FragmentManager fragmentManager = fragmentActivity.getSupportFragmentManager();
Here's My BottomNavigation Class
public class BottomNavigation extends BottomNavigationView {
FragmentActivity fragmentActivity = new FragmentActivity();
final Fragment homeFragment = new HomeFragment();
final Fragment searchFragment = new SearchFragment();
final Fragment videosFragment = new VideosFragment();
final Fragment favouriteFragment = new FavouriteFragment();
final Fragment premiumFragment = new PremiumFragment();
// The error is here
final FragmentManager fragmentManager = fragmentActivity.getSupportFragmentManager();
Fragment mainFragment = homeFragment;
public BottomNavigation(#NonNull Context context) {
super(context);
}
#SuppressLint("NonConstantResourceId")
public void initializeBottomNavigation() {
// first one transaction to add each Fragment
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(R.id.fragment_layout, premiumFragment, "5").hide(premiumFragment);
fragmentTransaction.add(R.id.fragment_layout, favouriteFragment, "4").hide(favouriteFragment);
fragmentTransaction.add(R.id.fragment_layout, videosFragment, "3").hide(videosFragment);
fragmentTransaction.add(R.id.fragment_layout, searchFragment, "2").hide(searchFragment);
fragmentTransaction.add(R.id.fragment_layout, homeFragment, "1");
// commit once! to finish the transaction
fragmentTransaction.commit();
// show and hide them when click on BottomNav items
BottomNavigationView navigationView = findViewById(R.id.bottom_navigation);
navigationView.setOnItemSelectedListener(item -> {
// start a new transaction
FragmentTransaction localFragmentTransaction = fragmentManager.beginTransaction();
// TODO: ADD Animations
switch (item.getItemId()) {
case R.id.home_item:
localFragmentTransaction.hide(mainFragment).show(homeFragment).commit();
mainFragment = homeFragment;
return true;
case R.id.search_item:
localFragmentTransaction.hide(mainFragment).show(searchFragment).commit();
mainFragment = searchFragment;
return true;
case R.id.videos_item:
localFragmentTransaction.hide(mainFragment).show(videosFragment).commit();
mainFragment = videosFragment;
return true;
case R.id.saved_item:
localFragmentTransaction.hide(mainFragment).show(favouriteFragment).commit();
mainFragment = favouriteFragment;
return true;
case R.id.premium_item:
localFragmentTransaction.hide(mainFragment).show(premiumFragment).commit();
mainFragment = premiumFragment;
return true;
}
return false;
});
}
And here I haved Called my class and method In MainActivity
private void initializeBottomNavigation() {
BottomNavigation bottomNavigation = new BottomNavigation(this);
bottomNavigation.initializeBottomNavigation();
}
I have tried to find a sloution and anderstand the error but I didn't found sothing In my case. So what is the problem here and How can I fix It?
You cannot make a new instance of an activity; activity instances are built only by Android itself. The only thing you can do in order to obtain an activity reference is to use an existing one.
public class BottomNavigation extends BottomNavigationView {
final FragmentActivity fragmentActivity;
...
final FragmentManager fragmentManager;
public BottomNavigation(#NonNull Context context, #NonNull FragmentActivity activity) {
super(context);
fragmentActivity = activity;
fragmentManager = fragmentActivity.getSupportFragmentManager();
}
...
}
And pass your existing reference of your activity:
private void initializeBottomNavigation() {
FragmentActivity activity = this; // Or your activity reference
BottomNavigation bottomNavigation = new BottomNavigation(this, activity);
bottomNavigation.initializeBottomNavigation();
}
Note that you still need to attach your BottomNavigation to a view parent in the activity to make it visible.
I'm trying to switch between fragments using a bottom navigation. However, if I switch to other fragments from the map fragment, the map fragment is still in the background while other fragment is being shown on the front.
Please see my code here:
public class MainActivity extends AppCompatActivity {
private FragmentManager fragmentManager;
private Fragment messageFragment = new MessageFragment();
private Fragment mapFragment = new MapsFragment();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().add(R.id.hostFragment, mapFragment, null).commit();
fragmentManager.beginTransaction().add(R.id.hostFragment, messageFragment, null).commit();
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
//bottomNavigationView.setSelectedItemId(R.id.mapsFragment);
bottomNavigationView.setOnNavigationItemSelectedListener(navListener);
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.mapsFragment:
fragmentManager.beginTransaction().hide(messageFragment).show(mapFragment).commit();
break;
case R.id.messageFragment:
fragmentManager.beginTransaction().hide(mapFragment).show(messageFragment).commit();
break;
}
return true;
}
};
}
Your Problem
You are adding both fragments to the same container, R.id.hostFragment.
fragmentManager.beginTransaction().add(R.id.hostFragment, mapFragment, null).commit();
fragmentManager.beginTransaction().add(R.id.hostFragment, messageFragment, null).commit();
Per the documentation for hide and show, this means that you are hiding and then showing the same container.
A Solution
Use two different container views:
fragmentManager.beginTransaction().add(R.id.mapContainer, mapFragment, null).commit();
fragmentManager.beginTransaction().add(R.id.messageContainer, messageFragment, null).commit();
Another Solution
Use replace instead of hiding and showing.
fragmentManager.beginTransaction().add(R.id.hostFragment, mapFragment, null).commit();
// Don't add this in `onCreate`
// fragmentManager.beginTransaction().add(R.id.hostFragment, messageFragment, null).commit();
...
// Replace the fragment currently being displayed
switch (item.getItemId()) {
case R.id.mapsFragment:
fragmentManager.beginTransaction().replace(R.id.hostFragment, mapFragment).commit();
break;
case R.id.messageFragment:
fragmentManager.beginTransaction().replace(R.id.hostFragment, messageFragment).commit();
break;
}
// I learned android studio about BottomNavigationView, but I have a problem like this ... please help me :(
// Caused by: java.lang.NullPointerException: Attempt to invoke
virtual method 'void
android.support.design.widget.BottomNavigationView.setOnNavigationItemSelectedListener(android.support.design.widget.BottomNavigationView$OnNavigationItemSelectedListener)'
on a null object reference// eror logcat
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
BottomNavigationView bottomNav = findViewById(R.id.bottom_navigation);
bottomNav.setOnNavigationItemSelectedListener(navListener);
}
private BottomNavigationView.OnNavigationItemSelectedListener navListener =
new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem menuItem) {
Fragment selectedFragment = null;
switch (menuItem.getItemId()) {
case R.id.nav_home:
selectedFragment = new HomeFragment();
break;
case R.id.nav_search:
selectedFragment = new SearchFragment();
break;
case R.id.nav_filter:
selectedFragment = new PesananFragment();
break;
case R.id.nav_notifikasi:
selectedFragment = new NotificationFragment();
break;
case R.id.nav_akun:
selectedFragment = new AccountFragment();
break;
}
assert selectedFragment != null;
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, selectedFragment).commit();
return true;
}
};
}
It looks like a problem with the initial bottomNav stationing.
Maybe try to put explicit casting like:
BottomNavigationView bottomNav=(BottomNavigationView)findViewById(R.id.bottom_navigation);
If that does not work check the BottomNavigationView implementation requirements.
You can use android studio to create a activity that already has a Bottom navigation.
So i've encountered a small problem today. I was making a bottom navigation view in my app, and after clicking buttons, it replaces the fragment on the screen (and it works perfectly!).
But just after launching the app, and without clicking any button, there is no fragment on the screen.
I've realized that the fragments are shown only after clicking a button, and I'd like to have a default fragment (kalkulatorFragment).
I've been trying my best to somehow set it up, but no success...
public class Main extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
= new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
kalkulatorFragment kalkulator_fragment = new kalkulatorFragment();
wzoryFragment wzory_fragment = new wzoryFragment();
definicjeFragment definicje_fragment = new definicjeFragment();
switch (item.getItemId()) {
case R.id.kalkulator:
ft.replace(android.R.id.content, kalkulator_fragment);
ft.commit();
return true;
case R.id.wzory:
ft.replace(android.R.id.content, wzory_fragment);
ft.commit();
return true;
case R.id.definicje:
ft.replace(android.R.id.content, definicje_fragment);
ft.commit();
return true;
}
return false;
}
Ok i just figured it out.
I moved the ft.replace to the onCreate() method, so the kalkulatorFragment is going to be shown just after creating an Activity.
public class Main extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
kalkulatorFragment kalkulator_fragment = new kalkulatorFragment();
FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(android.R.id.content, kalkulator_fragment);
ft.commit();
BottomNavigationView navigation = (BottomNavigationView) findViewById(R.id.navigation);
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
}
You need to use this code OUTSIDE of OnCreate Method:
navigation.setSelectedItemId(R.id.IdOFYourItemFromBottomNavigationMenuItems);
I don't know why, but it wont work inside OnCreate method. You can declare and initialize it inside OnCreate method, just can't set the default item in there.
In my case I am using it inside OnCreateOptionsMenu.