I have a button on a layout, but I want this available on the actionbar, I tried to move it but it does not work, any ideas?
thanks in advance.
You can't add the button directly through the layout.
Create instead a menu folder insede the res folder. And than add there an xml-file like
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="#+id/item1"
android:title="#string/ac_rate"
android:icon="#drawable/ab_star"
android:showAsAction="always"></item>
</menu>
and call it from the code with something like:
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.short_menu, menu);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
return true;
}
Related
Im looking for a way to disable a tab within a TabbedPage,
here my example of two tabs
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<TabbedPage xmlns=".."
xmlns:x=".."
x:Class="App.Views.Pages_Tabbed"
x:Name="myTabs"
xmlns:page="clr-App.Views">
<TabbedPage.Children>
<page:MemberShip x:Name="firstPage" ></page:MemberShip>
<page:Consent x:Name="secondPage"></page:Consent>
<page:Question x:Name="thirdPage"> </page:Question >
</TabbedPage.Children>
</TabbedPage> ```
I tried to set the Page to IsEnabled = false or IsVisible= false but not working .. it hide only content.
Also i followed https://stackoverflow.com/questions/54657758/how-to-set-the-currentpage-property-of-a-tabbedpage-in-the-oncurrentpagechanged but it crash the app cuz of the infinite loop.
The official does not seem to provide a way to directly disable the tab.
You can also hide the tab temporarily when you don't want the user to click on it. Let the user load it when he can click.
Here is the background code:
public partial class TabbedPage1 : TabbedPage
{
public static TabbedPage theTabbedPage {get; set;}
public TabbedPage1()
{
InitializeComponent();
theTabbedPage = this;
theTabbedPage.Children.RemoveAt(1);//Hide the second tab
}
}
When the user can click, use abbedPage1.theTabbedPage.Children.Insert(1,new Page2() {Title="page2"}); to add the tab.
Hope this method can help you too.
I want to migrate to single activity design using navigation component. I am using one activity and others are fragment. For some screens, I have only layouts, no preference. No problems to inflate those in fragment. But i faced problem when i try to work with preference.
My requirements is:
I need to inflate a toolbar and preference list in a fragment.
My approaches:
Add preference using this following code.
SettingFragment.java
#Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.setting_main, rootKey);
}
Configure for app bar for navigation component.
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mNavController = Navigation.findNavController(view);
AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(mNavController.getGraph()).build();
Toolbar toolbar = view.findViewById(R.id.the_toolbar);
NavigationUI.setupWithNavController(toolbar, mNavController, appBarConfiguration);
}
In app theme, i used a layout for preference which contains toolbar and framelayout.
<style name="Theme.MyApp" parent="#style/Theme.AppCompat.Light.NoActionBar">
...
<item name="preferenceTheme">#style/PreferenceThemeOverlay</item>
</style>
<style name="PreferenceThemeOverlay">
<item name="android:layout">#layout/fragment_settings </item>
</style>
fragment_settings.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="#+id/the_toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:layout_gravity="bottom"
android:layout_marginBottom="12dp"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#android:id/list_container">
</FrameLayout>
</LinearLayout>
setting_main.xml
<androidx.preference.PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:key="MyApp"
android:title="My application">
<androidx.preference.Preference
android:icon="#drawable/ic_list1"
android:key="PreferenceList1"
android:title="PreferenceList1" />
<androidx.preference.PreferenceCategory android:key="SecondCategory">
<androidx.preference.Preference
android:icon="#drawable/ic_list2"
android:key="PreferenceList2"
android:title="PreferenceList2" />
</androidx.preference.PreferenceCategory>
</androidx.preference.PreferenceScreen>
My problems:
If I do this, I can successfully add toolbar and preference. But i see a blinking issue in title during transaction from one fragment to another.
I have searched a lot, but did not find any suitable solutions. I am a newbie.
My questions:
How can I solve this issue?
Is there any way to work with preference in navigation component which also have a toolbar and preference in Fragment?
For others fragment, which does not have preference i can inflate using this code which works fine with no blink issue. Is there any ways to do this for preference also adjusting with my requirements?
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable
Bundle savedInstanceState) {
return inflater.inflate(R.layout.setting_main_fragment, container, false);
}
I know this might been asked before but since I didn't find anything convincing, I need to ask again.
How do you design an app that's going to support tablets and handsets when you also need to provide some sort navigation panel(e.g. Navigation Drawer)?
I think I know how to use the Navigation Drawer with handsets and tablets in portrait orientation because in those cases I'm only showing a single pane(fragment) at the time. But with tablets in landscape that's totally different since you have enough room to display at least two panes(fragments) that most of the time are going to be related in a sort of "mater-detail" way.
Edit #1
Just to provide a bit of context about my app and why I think I need to have two panes apart from the navigation list.
Well the main goal of my app is to help waiters take orders, this scenario comes into play when:
The waiter selects the option "Take order" from the left menu (ideally a navigation drawer)
In the first part(left pane) of the the what I called the "Content Part", the waiter can choose among all the categories of food they serve (pretend it's the list at the top) and according to the category selected, the below list shows all the dishes under that specific category.
Once the waiter taps on a dish it's automatically added to the second part(right pane) of the "Content Part"
Knowing that the basic structure of a navigation drawer is similar to this:
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="#+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
</android.support.v4.widget.DrawerLayout>
How do you handle the "tablet-in-landscape-orientation" scenario? Do you use nested fragments for the multi-pane layout that might be necessary to use in this case?(that sounds awfully complicated) Do you use a custom library perhaps? Do you know of any open source app in Git that implements this and that I can use as a reference?
EDIT #2
After trying some ideas, I realized that the most convenient way of implementing the same navigation drawer for multiple activities, was to create a BaseActivity that would handle all the drawer functionality and from which all my activities could inherit.
This is what I've got so far:
BaseActivity
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
public class BaseActivity extends Activity {
private DrawerLayout mDrawerLayout;
private ActionBarDrawerToggle mDrawerToggle;
private ListView mDrawerListView;
protected void onCreate(Bundle savedInstanceState, int resLayoutID) {
setContentView(resLayoutID);
super.onCreate(savedInstanceState);
setupNavDrawer();
}
private void setupNavDrawer() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerListView = (ListView) findViewById(R.id.drawer);
mDrawerListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
String[] rows = getResources().getStringArray(R.array.drawer_rows);
mDrawerListView.setAdapter(new ArrayAdapter<String>(
this, R.layout.drawer_row, rows));
mDrawerToggle =
new ActionBarDrawerToggle(this, mDrawerLayout,
R.string.drawer_open,
R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View row,
int position, long id) {
if (position == 0) {
Log.d("Menu", "European Union");
} else {
Log.d("Menu", "Other Option");
}
mDrawerLayout.closeDrawers();
}
});
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
#Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Every activity that needs to have a Navigation Drawer now needs to extend the BaseActivity:
EuropeanUnionActivity
public class EuropeanUnionActivity extends BaseActivity{
//...
}
Also every activity layout needs to contain in its code a android.support.v4.widget.DrawerLayout element like this:
activity_europeanunion
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="#layout/main" />
<ListView
android:id="#+id/drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>
Here's important to mention that the ID's for the DrawerLayout(drawer_layout) and the ListView(drawer) needs to be the same in all the activity layouts that are going to have a navigation drawer because those ID's are used by the BaseActivity.
For the sake of brevity and to quickly test this approach I have used this example by #CommonsWare (I hope he doesn't mind). There you can find the implementation for #layout/main.
Now, although almost everything works as expected, I haven't been able to understand why if I take the code for the ListView and place it in a separate file listview_options the Navigation drawer simply wouldn't close and tapping on the ActionBarDrawerToggle would only make the app crash and show this in the LogCat:
FATAL EXCEPTION: main
Process: com.idealsolution.simplenavigationdrawer, PID: 17725
java.lang.IllegalArgumentException: No drawer view found with gravity LEFT
at android.support.v4.widget.DrawerLayout.openDrawer(DrawerLayout.java:1293)
at android.support.v7.app.ActionBarDrawerToggle.toggle(ActionBarDrawerToggle.java:290)
at android.support.v7.app.ActionBarDrawerToggle.onOptionsItemSelected(ActionBarDrawerToggle.java:280)
at com.idealsolution.simplenavigationdrawer.BaseActivity.onOptionsItemSelected(BaseActivity.java:86)
at android.app.Activity.onMenuItemSelected(Activity.java:2608)
at com.android.internal.widget.ActionBarView$3.onClick(ActionBarView.java:167)
at android.view.View.performClick(View.java:4456)
at android.view.View$PerformClick.run(View.java:18465)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5086)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
This is line 86:
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) { //Line 86
return true;
}
return super.onOptionsItemSelected(item);
}
This is the same code for
activity_europeanunion, but using a include tag for the ListView
<include layout="#layout/main" />
<include layout="#layout/listview_options" />
The code for listview_options.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/menu_layout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:background="#111"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp" />
</LinearLayout>
This is the code I tried in the BaseActivity to retrieve the ListView, but that obviously isn't working:
private void setupNavDrawer() {
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
//Please pay special attention to the following two lines
mDrawerLinearLayout = (LinearLayout) findViewById(R.id.menu_layout);
mDrawerListView = (ListView) mDrawerLinearLayout.findViewById(R.id.drawer);
mDrawerListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
String[] rows = getResources().getStringArray(R.array.drawer_rows);
mDrawerListView.setAdapter(new ArrayAdapter<String>(
this, R.layout.drawer_row, rows));
mDrawerToggle =
new ActionBarDrawerToggle(this, mDrawerLayout,
R.string.drawer_open,
R.string.drawer_close);
mDrawerLayout.setDrawerListener(mDrawerToggle);
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> listView, View row,
int position, long id) {
//...
mDrawerLayout.closeDrawers();
}
});
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
}
Any ideas and suggestions are welcome.
Thanks.
P.S. I found this question in which it is said that using a Navigation Drawer is not advisable.
For phone and tablet-portrait mode you can use a layout like this:
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include layout="#layout/fragments_layout" />
<include layout="#layout/drawer_list" />
</android.support.v4.widget.DrawerLayout>
This could be the layout for the tablet-landscape mode:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<include layout="#layout/drawer_list" />
<include layout="#layout/fragments_layout" />
</LinearLayout>
Here is drawer_list:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="260dp"
android:layout_height="match_parent"
android:layout_gravity="start" >
<ListView
android:id="#+id/drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:background="#111"
android:divider="#android:color/darker_gray"
android:dividerHeight="0dp" />
</RelativeLayout>
and fragments_layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<fragment android:id="+#id/master_fragment" />
<fragment android:id="+#id/detail_fragment" />
</FrameLayout>
On the activity, you'll have to check if you're in tablet-landscape mode and show both fragments. Otherwise, you'll show master fragment first, hiding the details
If navigation drawer is visible on all activities, declare an abstract activity that takes care of the drawer. Then, all the activities inherit from this abstract activity. The BaseActivity you posted is a good example
I have looked at "Down at Android Fragments" and the samples and they show the use of a single fragment in a view. In that view you Find the fragment and set its' ViewModel
We do this in a few places, like so
// Expand the patient banner
var myFragment = (MyFragment)SupportFragmentManager.FindFragmentById(Resource.Id.banner);
this.vm = (MyViewModel)this.ViewModel;
myFragment.ViewModel = this.vm;
That is fine. What I do not know how to do is set the ViewModel on a Fragment when that Fragment is used in a List's MvxItemTemplate.
For example a bound MvxListView that has an MvxItemTemplate set to this axml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
local:MvxBind="Click ClickCommand">
<fragment
class="MyComp.MyDept.Droid.Views.ItemFragment"
android:id="#+id/ItemFragment"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
How do I set the correct Item ViewModel for the fragment in each of the ListView's items?
The simplest way would be to do it in your adapter. When the list containing the items calls to GetBindableView, you'll have access to the dataContext and templateId which spawned the creation of the cell in the first place, so you can set them accordingly there, after pulling the fragment directly out of the view with a simple FindFragmentById.
So, something approximately like this should do fine for you:
protected override View GetBindableView (View convertView, object dataContext, int templateId)
{
var view = base.GetBindableView (convertView, dataContext, templateId);
var frag = (this.Context as Activity).FragmentManager.FindFragmentById<MvxFragment>(<YourDroidNamespace>.Resource.Id.ItemFragment); // Better to pass in a fragment manager instance in the constructor
frag.DataContext = dataContext;
return view;
}
First, get the view where the fragment is. Second, get the fragment manager and do a FindFragmentById on it to find your particular fragment within the view. Finally, set the DataContext and return it.
I'm writing my first Android application and I have one activity that I'd like to display two separate dialogs:
Dialog A - A simple AlertDialog that shows text and gets dismissed
Dialog B - A "Save As" pop-up with an EditText and Save and Cancel buttons
I've found tutorials on creating AlertDialogs and Custom Dialogs and I've been able to get each of them to work, but only separately. When I try to put all of the code into a switch/case statement in the onCreateDialog method, the application crashes when the AlertDialog is launched.
Here's my onCreateDialog code:
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
// Display dialog
case 0:
AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);
alertDialog.setMessage(messageText);
alertDialog.setNegativeButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
return alertDialog.create();
// Save As dialog
case 1:
Dialog dialog = new Dialog(this);
dialog.setContentView(R.layout.save_as);
dialog.setTitle("Save as:");
Button cancel = (Button)findViewById(R.id.cancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
}
});
return dialog;
}
return null;
}
Either case will work by itself, but the application crashes when I put both cases in.
Here's the XML for the custom dialog layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:text="Save this list as:"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<EditText
android:id="#+id/list_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#android:drawable/bottom_bar"
android:paddingLeft="4.0dip"
android:paddingTop="5.0dip"
android:paddingRight="4.0dip"
android:paddingBottom="1.0dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/save"
android:layout_width="0.0dip"
android:layout_height="fill_parent"
android:text="Save"
android:layout_weight="1.0"
></Button>
<Button
android:id="#+id/cancel"
android:layout_width="0.0dip"
android:layout_height="fill_parent"
android:text="Cancel"
android:layout_weight="1.0"
></Button>
</LinearLayout>
</LinearLayout>
Should I stick with just one format or the other? I've also read that DialogFragments are preferred now, but I haven't found any good novice-level tutorials on those yet. Any suggestions will be greatly appreciated.
I eventually realized that I needed to pass data to and from the dialog, and I am targeting a low API so I just changed the Save As dialog to an Activity, and everything works fine. Learned a lot of limitations of dialogs along the way though....