Android Outsourcing Navigation Drawer - java

how can I create a class that instantiates my navigation drawer correctly?
I want to outsource it because it is a lot of code and its always the same.
I already tried to create such a class. The problem is,
there are these two methods:
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
that are overriden in the activity itself. Moreover the title doesnt change if the drawer is opened/closed and at last the arrow that is used as the button to open is not animated!
Thx for help!

First android studio provides a template for creating Drawer Activity. If you are going to create your project for the first time you can use:
or if you have created your project and you want to create a Drawer Activity you can find it like this:
Now if you do not like above approaches you can create an abstract activity class name it for example DrawerActivity and do all initialization in it. Then in every project you can add it and extends it. That is one time work. But you must design it carefully so it must be general enough and also meet your common requirements. For example it can have a protected DrawerLayout field so when you extends it you initialize that field after setContentView of subclass activity and all the stuff like onPostCreate and onConfigurationChanged are done in the DrawerActivity(superclass).

Related

Android: Is there a way to hide MainActivity layout elements in fragments?

My MainActivity layout includes a bottom navigation bar because I would like to use this as the main navigation components within my application's fragments. However, I have a login page which I do not want the navigation bar to be visible on. Since the fragment is being created from the MainActivity, it inherits the navigation bar and I can't find a way to hide it on the login fragment and show it on subsequent fragments.
For ease:
I have a MainActivity layout with a BottomNavigationBar
All fragments natively inherit the BottomNavigationBar from the MainActivity layout
I want the visibility of the navigation bar to be "GONE" on the user login fragment
I want the visibility of the navigation bar to be "VISIBLE" on the remaining fragments
Is there a way to do this?
The reason I am defining the BottomNavigationBar within the MainActivity is that I initially had a separate navigation bar on each fragment which required separate listeners on each fragment (making the code more extensive than it should be). Additionally, when I implemented the navigation bar as an individual component within each fragment, the item selected animations no longer functioned.
I have tried to use <include layout="#layout/main_activity android:visibility="GONE" android:layout_width="match_parent" android:layout_height="wrap_content"/> from within the login fragment but this has not worked.
I would appreciate any help people have on this matter.
Please feel free to let me know if you would like to see any of my code. I wasn't really sure which parts of my code would be relevant.
I would suggest you to use separate activities for this case - LoginActivity and MainActivity. Since you may at some point add ForgotPasswordFragment and maybe something else. To hide something you don't need in the first place is bad practice IMHO.
In case you don't want to change your approach you can create BaseFragment that will have abstract val showBottomNavBar() and will override it in every fragment.
And then in onViewCreated you'll check that flag and update UI accordingly.
Something like this:
abstract class BaseFragment : Fragment() {
abstract val showBottomNavBar: Boolean
//.. your other stuff
}
class FragmentA : BaseFragment() {
override val showBottomNavBar = false
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (!showBottomNavBar) {
(requireActivity() as YourAcitivy).hideNavBar() //this is bad
someKindOfBroadcastManager.sendEvent(hideNavBar) // this is somewhat better
}
}
}
But I would still suggest you to decouple login/main logic from single activity
You can access activity from fragment with getActivity() method and cast to your activity. Of course you have to add hideBottomNavigationBar method to your activity and also you have to be sure that your fragments host activity is MyActivity.
MyActivity activity = ((MyActivity)getActivity());
activity.hideBottomNavigationBar();
After that you can define a marker interface that named IFullScreen then in your BaseFragment's onCreateView method you can check if this class is instance of IFullScreen and decide to show or hide bottom navigation bar.
interface IFullScreen { }
class BaseFragment extends Fragment {
#CallSuper
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
MyActivity activity = ((MyActivity)getActivity());
if (this instanceof IFullScreen)
activity.hideBottomNavigationBar();
else
activity.showBottomNavigationBar();
}
}
class FragmentA extends BaseFragment implements IFullScreen {
//Rest of fragment code
}

Sending information from one fragment to another Android

I am having this issue where I have nested fragments. I need one to be able to send information to the other.
For example, if I press a button in the inner fragment I want the outer fragment to perform an action.
Any help would be great!
Edit: I forgot to mention that both of these are live fragments. As far as I know using bundles only allows me to set arguments when creating a fragment but not after it has been created.
Well there are plenty of ways to manage this. It really depends on the architecture you want to go with.
You could go lazy and use a Bus library that uses sub/pub modeling and reflection for notifying generic objects that registered and have matching signature methods of changes, However, this is frowned upon to use reflection for regular coding practices that could be implemented without it.
I would say you can either create an interface that represents the calls that would go back and forth like IMainActivityCallbacks with methods like dataChange(myObject obj)
.
Then in your onAttach of fragment you cast the context as IMainActivityCallbacks. Make sure the MainActivity implements the interface.
Then simply call the mIMainActivityCallbacks.dataChange(someObject);
This will call the method in the parent activity and allow him to pass it to the child fragment that needs it with mMyOtherFragment.publicMethod(newDataJustReceived).
You could also get crazier if you want and pass an interface into the child fragment that references the outer fragment so when MainActivity news up the children fragment, the outer one could implement an interface of doStuff and then be passed as an interface to the inner child fragment. So the child fragment can easily say if "mParentInterface" is not null then mParentInterface.doStuff.
There are millions of ways to skin a cat, but prefer to use interfaces rather then Reflection based libraries typically. Hope that helps.
Use interface in this case. 1) Define interface in you first fragment(in which you click something and waiting something to happen in a second fragment) and use callback method you define in your interface. For example:
OnButtonClickListener mCallback;
......your code
public interface OnButtonClickListener {
void onButtonSelected(int position);
}
......your code
then you call your callback method
.....
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
mCallback.onButtonSelected(position);
}
});
2) Then implement this interface in host activity you have for nested fragments.
For example:
public class MainActivity extends AppCompatActivity implements YourFragment.OnButtonClickListener{....
3) Define callback method of your interface in this activity. For example:
public void onButtonSelected(int position) {
...Here just change something in your second fragment.....
Hope this will be helpful.
I use greenrobot EventBus in that cases.
You need to add this library to your build gradle:
compile 'org.greenrobot:eventbus:3.0.0'
That you can send message like this:
EventBus.getDefault().post(new ActionEvent("test action"));
And another fragment can catch it this way:
#Subscribe(threadMode = ThreadMode.MAIN)
public void onActionEvent(ActionEvent event) {
//do something
}
You can sending different actions, if you want, same way.
Don`t forget to according to fragment lifecycle:
#Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
#Override
public void onStop() {
EventBus.getDefault().unregister(this);
super.onStop();
}

Custom Listview not responding to listener after activity destroyed

I have a BaseActivity that takes care of Fragment transitions by acting as the central controller for it's Fragment's touch listeners. One of the Fragment is a custom Listview that will cause the BaseActivity to display a new Fragment when tapped. This works when the Activity is created from scratch, but I have a problem with it when the activity is destroyed (through the Dev options "Don't Keep Activities", or through memory cleanup).
I have verified through logs that I am setting the Fragment's listener when the activity starts up from being destroyed, but tapping on the Listview doesn't transition to a new Fragment. I also tried to see if it was a focusing issue but putting android:descendantFocusability="blocksDescendants" in the Listview layout xml also doesn't solve the issue.
The listener is set when I create the fragment and it is the first fragment the activity instantiates when it starts up. Any insights would be appreciated!
I'll add a answer to be easier to help you. The first thing is that you listener should be set inside fragment's onAttach:
#Override
public void onAttach(Context context) {
// here, your context is also your activity
super.onAttach(context);
if (context instanceof YourListener) {
this.fragmentListener = (YourListener) context;
}
}
Please change this and check if something changed!

Toolbar style changes in Android 4 when activity called from a static method

Found a strange issue in the app.
Toolbar style changes itself just for one acitvity in whole app and only on devices below 5.0 Android version.
All the screens have the same <include> field for the toolbar.
The activities, where style changes, are all inflated with a static method:
public static void startAsRecent(Context context, TransferTemplate template) {
Intent starter = new Intent(context, TransferAnotherAccountActivity.class);
starter.putExtra(TransferCommonActivity.EXTRA_KEY_TEMPLATE, template);
starter.putExtra(TransferCommonActivity.EXTRA_KEY_IS_RECENT, true);
context.startActivity(starter);
}
Strange, that it works normail in devices with Android versions abowe 5.0.
What could be the reason of this kind of behavior? And where to look to fix this?
Thanks in advance!
Ok, the problem was in inheritance.
onCreate() method of inherited activities, where was the problem, called setContentView() first, and then super.OnCreate(). Still don't understand, why this affected only pre-lollipop devices, but the temporary solution is to make something like this in the superclass.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentViewId());
//other stuff
}
#LayoutRes
public abstract int getContentViewId();

Cannot set the view from activity android

I am facing a strange problem suddenly in android. I am creating layout .xml file in res>layout but from a class that extends activity, I can not access it. I have done this several a time but I can not figure out this strange problem. I restarted the eclipse, even the computer but no. When I go for setting the contentView it says something as below :
The method onCreate(Bundle) of type MainActivity must override or implement a supertype method
That is let I have created an xml file at res>layout named "whynot.xml" and from a activity when I try to set it like
setContentView(R.layout.whynot);
It shows red mark below and the above message.
you have to extends Activity and call super.onCreate(savedInstanceState) in the onCreate. For each callback of the Activity's lifecycle is mandatory to call its super
As the error says,
must override or implement a supertype method
you need the super call like
#Override
protected void onCreate(Bundle bundle)
{
super.onCreate(bundle); // here
setContentView(...);
...
}

Categories