Xamarin NavigationView menu item customization - c#

Hi I use C# and Xamarin to develop my new application and ran into many problems using this platform. Is it possible to customize menu items inside NavigationView using xamarin? all I found are the valid properties for the menu items.
But what if instead of this:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/itemOne"
android:title="Go to page one" />
<item
android:id="#+id/itemTwo"
android:title="Go to page two" />
</menu>
I want to do this:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<TextView></TextView>
<Button></Button>
<SomeOtherControlHere></SomeOtherControlHere>
</menu>
Is it possible using xamarin? What are my other options?
Aside from that I found that Xamarin API's are very restrictive, for example you cant use custom ttf fonts directly inside xml to set the fonts for menu items:
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/itemOne"
android:title="Go to page one"
android:fontFamily="MyCustomFontName Or MyPathToFonts" /> <-- NOT VALID
</menu>
Also if I apply style for an entire menu items container it is also not possible to use custom fonts, the only fonts we can use is the built in fonts...
Even if I get reference inside my Activity to an individual menu item (IMenuItem), there is no property or function to set font family.

It's possible to define a more complex NavigationView. Just put the child controls inside the NavigationView-Tag. For example, this is how I use the NavigationView to implement a footer. There are no restrictions to the child controls so you can you Buttons etc. as well:
<android.support.design.widget.NavigationView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:id="#+id/navigation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true"
local:headerLayout="#layout/drawer_header"
local:theme="#style/NavigationDrawerStyle"
local:menu="#menu/drawer_menu">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:orientation="vertical">
<TextView
android:id="#+id/empty_spacer"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:clickable="false"
android:text="" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="65dp"
android:background="#drawable/footer_small"
android:orientation="vertical"
android:weightSum="1" />
</LinearLayout>
</android.support.design.widget.NavigationView>
To change the TextSize of the items for example, you have to define an own style:
<style name="NavigationDrawerStyle">
<item name="android:textSize">24sp</item>
<!-- more properties -->
</style>
Then assign it to your NavigationView:
<android.support.design.widget.NavigationView app:theme="#style/NavigationDrawerStyle">
<!-- ... -->
</android.support.design.widget.NavigationView>

This is how I format the Navigation Menu Item which starts by icon, then menu text and the last one is number. It look like the one in gmail app.
OnCreate
navigationView = FindViewById<NavigationView>(Resource.Id.wnl_nav_view);
//Add customize menu item style
IMenu menuNav = navigationView.Menu;
View view = View.Inflate(this, Resource.Layout._drawerMenuItemTemplate, null);
IMenuItem logoutItem = menuNav.FindItem(Resource.Id.nav_mail);
MenuItemCompat.SetActionView(logoutItem, view);
TextView txtNewNumber = view.FindViewById<TextView>(Resource.Id.txtNewNumber);
_drawerMenuItemTemplate.axml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#color/primary_text"
android:text="3/30"
android:id="#+id/txtNewNumber"
android:layout_gravity="right"
android:fontFamily="#string/abc_font_family_display_2_material"
android:textSize="13sp"
android:textStyle="bold"
android:paddingRight="6dp"
android:layout_marginTop="14dp" />
</FrameLayout>

Related

How to put button, edittext etc below custom toolbar

I have created a custom toolbar. But when I put things like imageview, button etc it wont be below toolbar. I also tried android:layout_below but i either its not working or I put wrong id (i tried multiple ids). Its just mixing with the toolbar.
In the code the imageview is merging with the toolbar and i want the imageview to be below it.
Thanks for anyone who answers
code:
<?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:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<ImageView
android:id="#+id/icon"
android:layout_below="#id/toolbar"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#drawable/shoppingcart"
android:layout_width="100dp"
android:layout_height="100dp"
/>
<android.support.design.widget.TextInputLayout
android:layout_below="#+id/icon"
android:id="#+id/forgot_input_email"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/forgot_email"
android:hint="Enter groceries"
android:inputType="textCapWords"
android:maxLines="1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</android.support.design.widget.TextInputLayout>
P.s.
include is just the normal toolbar settings
I got my answer! I had to put on image view tag android:layout_marginTop="?attr/actionBarSize", it just do it below the height of the toolbar/actionbar Like that:
<ImageView
android:layout_marginTop="?attr/actionBarSize"
android:id="#+id/icon"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#drawable/shoppingcart"
android:layout_width="100dp"
android:layout_height="100dp"

How to disable all touches for a Layout in Android

I am trying to implement a bottom sheet in Xamarin.Android and I want to disable all touches on everything that is not the bottom sheet (i.e. main layout), when the bottom sheet is active.
Main.axml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/main_layout">
<include
android:id="#+id/toolbar"
layout="#layout/toolbar" />
<!-- Main Layou -->
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/main_content"
android:paddingLeft="16dp"
android:paddingRight="16dp" >
<Button
android:id="#+id/btn_test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/logout"
android:layout_gravity="center" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="16dp"
android:clickable="true"
android:src="#drawable/ic_plus" />
</FrameLayout>
<FrameLayout
android:id="#+id/tint"
android:background="#000000"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- Bottom sheet -->
<FrameLayout
android:id="#+id/bottom_fragment_container"
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="#E0E0E0"
android:layout_gravity="bottom"
android:elevation="16dp"
android:translationY="160dp" />
I tried iterating over all the children and disabling them, but that changes the appearance of the button and I want to avoid that. I also tried setting the Enabled property of the layout to false, but the button was still touchable.
I think i need to somehow intercept all touches before they reach the button (and everything else that will be there later), but I don't know how to do that. By intercepting all touches I could also implement hiding of the bottom sheet after those touches.
Create a transparent RelativeLayout that covers the entire screen and use the android:clickable="true" property in it to make sure it intercepts all the click events.
Then add android:layout_alignParentBottom to your bottom sheet and put it inside this newly created RelativeLayout. This way it'll appear at the bottom and everything else won't be clickable.
<FrameLayout>
<!-- Main Layout -->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0000"
android:clickable="true">
<FrameLayout
android:id="#+id/bottom_fragment_container"
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="#E0E0E0"
android:layout_alignParentBottom="true"
android:elevation="16dp"
android:translationY="160dp" />
</RelativeLayout>
</FrameLayout>

Clickable Button in a custom listview

My problem is I can't make the button I added in my custom listview to be clickable.
Here is the XML file of my custom listview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="335dp"
android:layout_height="100dp"
android:minHeight="80dp"
android:maxHeight="250dp"
android:background="#ffffff"
android:id="#+id/list"
android:baselineAligned="false"
android:longClickable="false"
android:descendantFocusability="blocksDescendants"
android:clickable="false">
<Button
android:background="#drawable/grbgCan"
android:layout_width="15dp"
android:layout_height="20dp"
android:id="#+id/deleteMemo"
android:layout_gravity="start"
android:layout_marginLeft="270dp"
android:layout_marginTop="5dp"
android:duplicateParentState="false"
android:clickable="true" />
<TextView
android:text="Text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/id"
android:layout_marginLeft="290dp"
android:layout_marginTop="-20dp"
android:layout_marginRight="15dp"
android:clickable="true" />
<TextView
android:id="#+id/top"
android:text="Title"
android:textColor="#ff7e7777"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="255.5dp"
android:layout_height="19.9dp"
android:paddingLeft="10dp"
android:layout_marginTop="-20dp" />
<TextView
android:id="#+id/bottom"
android:textColor="#ff7e7777"
android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="match_parent"
android:layout_height="63.3dp"
android:paddingLeft="50dp"
android:layout_gravity="left"
android:text="Note" />
<TextView
android:text="Text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/date"
android:layout_marginLeft="250dp"
android:layout_marginRight="5dp" />
</LinearLayout>
In my main activity I tried the Btn.Click event but it only produces an error. And from what I've read in similar problems, their button was initialize in their Array Adapter but I'm using SimpleCursorAdapter because I'm fetching data from my sqlite database.
What should I do then? Please don't give me java codes because some them aren't applicable in xamarin studio since it's c#. Thanks.
You can't do it this way because you have a lot of same items in ListView with same ids
You must set OnClickListener to your button in your Adapter's getView() method like this
(this is java code for android studio, so it can differ from c# code, but gist is the same)
Button btn = (Button) convertView.findViewById(R.id.deleteMemo);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//here you go
}
});
Try something like this (If you don't have Fragments delete the view. below)
var _view = view.FindViewById<ListView>(Resource.Id.listView1);
if (_view.ChildCount > 0){
Button _button = (Button)_view.GetItemAtPosition(0).GetChildAt(0);
}
Because you have a lot of similar objects on a list this is the only way i think to access them,
Remember that item position is relative to the current visible items on the screen and you cant access items that are not visible

Border Class analog in Xamarin Android

I want to draw a candlestick chart (500 itmes). In WPF, I can use 500 borders (System.Windows.Controls.Border) inside 1 scrollviewer.
I also can change any item when it's needed.
How can I do the same in Xamarin.Android? Xamarin.Android doesn't contain the Border class.
you could use a ScrollView, containing a LinearLayout containing itself 500 times a simple <View> that has a size and a drawable stroke as background
something like
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
>
<View
android:layout_width="50dp"
android:layout_height="100dp"
android:background="#drawable/border_white"
/>
<View
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#drawable/border_white"
/>
and in res/drawable, a file named border_white
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="2dip" android:color="#android:color/white" />
</shape>
but it'll be pretty slow I tell you (like on Windows, probably).

MvvmCross Specific ViewModel for MvxItemTemplate to populate AutoCompleteTextView

I was wondering if, when you create a MvxListView in xml and use a MvxItemTemplate to describe the Items, there is a way to assign the ViewModel that gets used (assuming there is one) for each line. I fixed a similar problem by extending my Item class, but I want to have another item be an AutoCompleteTextView that has its hint list populated from a database. I can get the list into and IEnumerable, its just a matter of assign that list to to each item in the list. I figure if I can control that creation of the ViewModel for each item, I can add a property that contains the hint list and bind it.
My main View is:
<?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="fill_parent">
<Mvx.MvxListView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
local:MvxBind="ItemsSource ShipmentInventory.Items"
local:MvxItemTemplate="#layout/inventoryitemview" />
<FrameLayout
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/frameLayout2" />
<EditText
android:inputType="date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/editText1" />
</LinearLayout>
The view for the Item template is:
<?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="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<MvxSpinner
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:padding="2dp"
local:MvxBind="ItemsSource TagColors; SelectedItem TagColor"
android:id="#+id/spinner1" />
<EditText
android:layout_width="300dip"
android:layout_height="wrap_content"
style="#style/InputEditText"
local:MvxBind="Text InventoryNumber" />
<AutoCompleteTextView
android:layout_width="300dp"
android:layout_height="wrap_content"
style="#style/InputEditText"
local:MvxBind="Text Articles; completionHint HintList" />
</LinearLayout>
I figure if I can control the ViewModel its using for each item, I can add a property to it called HintList. Is there a way to do this?
Jim
I figured out most of the nuances for this and created an example at
https://github.com/JimWilcox3/MvxAutoCompleteTest
In a nutshell, when you bind data to an MvxItemList, the object in the datamodel for each item acts as your ViewModel for that item. In my example, I just created a list of items. If you are working with data from say WCF, you can extend the object created in the WCF using a partial class. In that partial class you can create MvxCommand and other things that you might want to bind to. Hope this helps someone.

Categories