Actually my app have 2 themes (pink and blue), handled by ResourceDictionary in App.xaml
Switching a switch in settings page change programmatically the values of the ResourceDictionary and the elements change as wanted (background, text colors etc).
It's maybe not the prettiest way but it works..
But i have a problem to change background colors of the Tabbar in android.
The color value of it is set in the Android project (colorPrimary from styles.xml and Tabbar.axml).
But i can't find
How to change or access this value from my PCL project.
Or how to change, in Android project, the value of that colorPrimary
each time the settings switch value is changed.
Or also, the best solution, make the tabbar transparent and make it
overlap the current background (if i set Color.Transparent it just
become white now)
The tabbed page code is as been created by Xamarin forms project.
public MainPage()
{
Page centerPage, rightPage, leftPage;
string TitleCenter = "S'exercer";
string TitleLeft = "Comprendre";
string TitleRight = "Aller plus loin";
switch (Device.RuntimePlatform)
{
case Device.iOS:
centerPage = new NavigationPage(new Center_Main())
{
Title = TitleCenter
};
rightPage = new NavigationPage(new Right_Main())
{
Title = TitleRight
};
leftPage = new NavigationPage(new Left_Main())
{
Title = TitleLeft
};
centerPage.Icon = "tab_feed.png";
rightPage.Icon = "tab_about.png";
leftPage.Icon = "offline_logo.png";
break;
default:
centerPage = new Center_Main()
{
Title = TitleCenter
// Nothing tab related here
};
rightPage = new Right_Main()
{
Title = TitleRight
};
leftPage = new Left_Main()
{
Title = TitleLeft
};
break;
}
Thanks
Using Xaml it is something like this:
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" BarBackgroundColor="your_Color"></Tabbedpage>
Programatically:
TabbedPage page=new Tabbedpage(){ BarBackgroundColor=Color.Blue};
You can do the following in your tabbedPage constructor :
public MainPage()
{
BarBackgroundColor=Color.Blue;
}
Note: Can be used with static resources just put it in place of the color name.
Something like this
<... BarBackgroundColor={StaticResource color_name}>
Maybe if you go straight into the color that fills in the Tabbar this way:
xaml:
<ContentPage Title = "Menu" BackgroundColor = "{DynamicResource primary_colour}">
MainPage.
Application.Current.Resources ["primary_colour"] = Color.Green;
Related
I am struggling how I could replicate the drop-down ToolbarItem from Xamarin.Forms when a ToolbarItem's order is set to Secondary for IOS, in order for it to look like it does for Android.
Here are some images to better explain what I am looking for:
How it works on Android:
Code:
ToolbarItem toolbarItem = new ToolbarItem()
{
Text = "ToolbarItem",
Order = ToolbarItemOrder.Secondary
};
Images on how it looks on Android:
Image showing the "More" icon
Image showing the "More" icon expanded to show more toolbar items
There is no default "More" icon on the toolbar when setting the Order to Secondary in iOS. Instead what happens, is that a bar below the navigation bar is created, which includes all of the toolbar items - something I do not wish to have for my Application.
This is an example of how it has been achieved before on IOS:
A screenshot I took from one of my Apps that implements this
effect
In native iOS, you can use UIPopoverController to achieve your effect. But please notice that this control can only be used in iPad.
Since you are using Xamarin.Forms, we can create a custom renderer in iOS platform to get this.
Firstly, create a page renderer to display the UIPopoverController. We can show it from a UIBarButtonItem or a UIView depending on your request. Here I use UIBarButtonItem like:
//I defined the navigateItem in the method ViewWillAppear
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
rightItem = new UIBarButtonItem("More", UIBarButtonItemStyle.Plain, (sender, args) =>
{
UIPopoverController popView = new UIPopoverController(new ContentViewController());
popView.PopoverContentSize = new CGSize(200, 300);
popView.PresentFromBarButtonItem(rightItem, UIPopoverArrowDirection.Any, true);
});
NavigationController.TopViewController.NavigationItem.SetRightBarButtonItem(leftItem, true);
}
Secondly, construct the content ViewController in the UIPopoverController(just like the secondary list in android):
public class ContentViewController : UIViewController
{
public override void ViewDidLoad()
{
base.ViewDidLoad();
UITableView tableView = new UITableView(new CGRect(0, 0, 200, 300));
tableView.Source = new MyTableViewSource();
View.AddSubview(tableView);
}
}
public class MyTableViewSource : UITableViewSource
{
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(new NSString("Cell"));
if (cell == null)
{
cell = new UITableViewCell(UITableViewCellStyle.Default, new NSString("Cell"));
}
cell.TextLabel.Text = "Item" + indexPath.Row;
return cell;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
return 10;
}
}
At last we can show it on the screen by calling PresentFromBarButtonItem.
Image shows versions 7.1 and 4.4,the top two images are the default ones, to the bottom two we added some customization ,see description
What I want to achieve is that on Android 4.4 the hamburger button to have a space in front so that it doesn't start right from the edge of the action bar/screen(much like on 7.1,see screenshot).Can I add a padding to the hamburger button?I am using Xamarin.Forms with Xamarin Studio.
The problem seems to be worse when we add a custom view to the action bar,it sets the hamburger button more to the left I think,and doesn't entirely fit in the screen and somehow "cuts it off".
This is the relevant part of how we add the custom view to the action bar.We do this with a custom NavigationRenderer and we do the UI from code.
actionBar.SetDisplayShowCustomEnabled(true);
LinearLayout linearLayout = new LinearLayout(activity);
linearLayout.SetGravity(GravityFlags.CenterVertical);
LinearLayout.LayoutParams textViewParameters = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MatchParent, LinearLayout.LayoutParams.MatchParent);
switch (activity.Resources.DisplayMetrics.DensityDpi)
{
case DisplayMetricsDensity.Xhigh:
textViewParameters.RightMargin = (int)(48 * activity.Resources.DisplayMetrics.Density);
break;
case DisplayMetricsDensity.Xxhigh:
textViewParameters.RightMargin = (int)(64 * activity.Resources.DisplayMetrics.Density);
break;
default:
textViewParameters.RightMargin = (int)(48 * activity.Resources.DisplayMetrics.Density);
break;
}
TextView modelTitle = new TextView(activity);
modelTitle.Text = view;
modelTitle.Gravity = GravityFlags.Center;
modelTitle.TextSize = 17f;
Typeface type = Typeface.CreateFromAsset(Forms.Context.Assets, "abc.ttf");
modelTitle.SetTypeface(type, TypefaceStyle.Bold);
modelTitle.SetTextColor(Android.Graphics.Color.White);
linearLayout.AddView(modelTitle, textViewParameters);
ActionBar.LayoutParams actionbarParams =
new ActionBar.LayoutParams(ActionBar.LayoutParams.MatchParent, ActionBar.LayoutParams.MatchParent);
activity.ActionBar.SetCustomView(linearLayout, actionbarParams);
I also tried to change the hamburger icon to a drawable(I added a space before the same hamburger icon,and it would do the job),but once I navigate back to the page using the back button (from the same action bar),my icon is replaced by the default hamburger button again.
I would appreciate any help.Thank you!
Edit:
public class MainView : MasterDetailPage
{
public MainView(parameter){
......
sideMenu = new CustomContentPage();//my custom Content Page with listview items
base.MasterBehavior = MasterBehavior.Split;
sideMenu.Padding = new Thickness(0, Device.OnPlatform(50, 0, 0), 0, 0);
Master = sideMenu;
.......
}
...
}
public class App : Application
{
private MainView lcMenu = null;
.....
if (lcMenu == null)
{
MustSet = true;
lcMenu = new MainView(parameter);
lcMenu.RequestPage += LcMenu_RequestPage;
}
....
MainPage = lcMenu;
}
This is the relevant part of how we add the custom view to the action bar.We do this with a custom NavigationRenderer and we do the UI from code.
Seems that you're creating your own master detail instead of using the MasterDetailPage of XF? Not sure, but I think you went the wrong direction, for setting the padding of hamburger button we need to customize MasterDetailPage.
I also tried to change the hamburger icon to a drawable(I added a space before the same hamburger icon,and it would do the job),but once I navigate back to the page using the back button (from the same action bar),my icon is replaced by the default hamburger button again.
As I said, we can customize the MasterDetailPage, in the renderer, we can find the ImageButton for hamburger button, for example:
public class MyMasterDetailRenderer : MasterDetailPageRenderer
{
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
var toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
for (var i = 0; i < toolbar.ChildCount; i++)
{
var imageButton = toolbar.GetChildAt(i) as ImageButton;
var drawerArrow = imageButton?.Drawable as DrawerArrowDrawable;
if (drawerArrow == null)
continue;
//set drawable
imageButton.SetImageDrawable(Forms.Context.GetDrawable(Resource.Drawable.hamburger));
//set padding
imageButton.SetPadding(80, 30, 80, 30);
//set background
imageButton.SetBackgroundColor(Android.Graphics.Color.Red);
}
}
}
I'm running into a strange issue when adding a Toolbar to my Form in my Codenameone app. If I set a toolbar on my form, it shows another title with the toolbar hamburger and new title below the title of the previous form instead of replacing it like I would expect. It looks like this:
The functionality works fine replacing the old title like I would expect when I run in the Codenameone simulator, but I get this weird behavior shown in the image when I make an Android build and run it on a Nexus 5 (6.0.1). The back arrow and "12 of 12" is the title from the previousForm
This is my code, am I doing anything wrong here with the Toolbar usage?
void goShowResource(final Form previousForm) {
previous = previousForm;
final Toolbar bar = new Toolbar();
final Form rd = new Form("resource details");
final Resource thisResource = this;
rd.setToolbar(bar);
bar.addCommandToSideMenu(new Command("command 1") {
#Override
public void actionPerformed(ActionEvent evt) {
AddResources ar = new AddResources(settings, thisResource);
ar.goAddResources(rd);
}
});
bar.addCommandToSideMenu(new Command("command 2") {
#Override
public void actionPerformed(ActionEvent evt){
UpdateResource ur = new UpdateResource(settings);
ur.goUpdateResource(rd, thisResource);
}
});
rd.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
showDetails(rd);
rd.show();
}
edit: Additonal info, if I open the sidemenu once, the old title bar at the top shrinks away, and I'm left with the the single correct yet incorrectly formatted title area.
You should use the Toolbar for all the forms in the app or disable the default which is native menu bar when working with the toolbar. You can do the latter by editing the theme and selecting the constants tab then pressing "Add" and selecting commandBehavior=Side.
Android currently defaults to the native ActionBar behavior and Toolbar implicitly overrides that, however when a transition occurs from the native to the lightweight component things can get pretty hairy (and might also look unnatural) so we recommend picking one UI paradigm and going with it.
Since the ActionBar is a volatile API we recommend Toolbar going forward as its far more customizable and gives us a lot of control.
This can be fixed by removing all command from the form after setting the toolbar, then add a fresh back command to the toolbar if required.
void goShowResource(final Form previousForm) {
previous = previousForm;
final Toolbar bar = new Toolbar();
final Form rd = new Form("resource details");
final Resource thisResource = this;
rd.removeAllCommands();
rd.setBackCommand(null);
rd.setToolbar(bar);
//Add back command
Command back = new Command("back") {
#Override
public void actionPerformed(ActionEvent evt) {
previousForm.showBack();
}
};
bar.addCommandToSideMenu(back);
bar.addCommandToSideMenu(new Command("command 1") {
#Override
public void actionPerformed(ActionEvent evt) {
AddResources ar = new AddResources(settings, thisResource);
ar.goAddResources(rd);
}
});
bar.addCommandToSideMenu(new Command("command 2") {
#Override
public void actionPerformed(ActionEvent evt){
UpdateResource ur = new UpdateResource(settings);
ur.goUpdateResource(rd, thisResource);
}
});
rd.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
showDetails(rd);
rd.show();
}
I have created a new Blank App (Xamarin.Forms Portable) project in Visual Studio 2015 and modified App.cs to get "hamburger menu":
public class App : Application
{
public App()
{
var masterPage = new ContentPage()
{
Content = new Label { Text = "Hello from Master!"},
Title = "Master Page"
};
var detailPage = new ContentPage()
{
Content = new Label { Text = "Hello from Detail!" },
Title = "Detail Page"
};
var mainPage = new MasterDetailPage()
{
Master = masterPage,
Detail = detailPage,
Title = "Main Page"
};
// The root page of your application
MainPage = mainPage;
}
. . .
}
Everything works fine, but how can I customize these four things:
1) Hide / change Arrow
2) Hide / change Icon
3) Hide / change Title text
4) Hide whole toolbar
You can change arrow to hamburger icon if you use your DetailPage within NavigationPage:
Detail = new NavigationPage(detailPage);
To change icon, just change project files:
YourProject/Resources/drawable/icon.png
YourProject/Resources/drawable-hdpi/icon.png
YourProject/Resources/drawable-xhdpi/icon.png
YourProject/Resources/drawable-xxhdpi/icon.png
or on your MasterDetailPage set Icon property to another resource.
If you want to hide icon - it only applies to Android. It can be solved with custom renderer (http://developer.xamarin.com/guides/cross-platform/xamarin-forms/custom-renderer/):
public class CustomNavigationRenderer : NavigationRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<NavigationPage> e)
{
base.OnElementChanged (e);
var actionBar = ((Activity)Context).ActionBar;
actionBar.SetIcon (Resource.Color.transparent);
}
}
EDIT:
It can also be done in MainActivity.cs:
ActionBar.SetIcon (new ColorDrawable(Resources.GetColor (Android.Resource.Color.Transparent)));
Just use Title property on Page.
SetHasNavigationBar(page, false);
I have a problem with Xamarin.Forms (version 1.2.2) on Android (Nexus 5).
The alignment of Button.Text is often not centered after performing a click.
In a short project, I figured out, that updating the UI causes the problem.
public class App
{
public static Page GetMainPage()
{
var label = new Label {
Text = "label",
};
var buttonBad = new Button {
Text = "buttonBad",
Command = new Command(() => label.Text += "1"),
};
var buttonGood = new Button {
Text = "buttonGood",
};
return new ContentPage {
Content = new StackLayout {
Children = {
buttonBad,
buttonGood,
label,
}
}
};
}
}
A click on "buttonBad" (updating the label.Text) causes the text-alignment of this button to not be centered anymore. A click on "buttonGood" does not cause the problem.
Is there a good workaround to solve this problem?
This workaround seems to be too complicated:
http://forums.xamarin.com/discussion/20608/fix-for-button-layout-bug-on-android
edit:
A programatically edit of the UI also cases the bug. Changing the label.Text in an async method after a short waiting leads the "buttonGood" to align its text wrong after a click.
edit2:
I created an example / test project on GitHub:
https://github.com/perpetual-mobile/ButtonTextAlignmentBug.git
The alignment is correct, when the StackLayout is replaced by an AbsolutLayout, but i need the StackLayout to work well.
Ok, after hours of dealing with this silly bug, I resolved it by implementing a custom renderer and overriding ChildDrawableStateChanged:
public override void ChildDrawableStateChanged(Android.Views.View child)
{
base.ChildDrawableStateChanged(child);
Control.Text = Control.Text;
}