In my Xamarin.Forms app, I want my Grid background color to be the same as the Navigation Bar's background color, something like this:
BackgroundColor="{StaticResource BarBackgroundColor}"
How can I do this?
You can retrieve the color of your navbar by casting your current page to a navigation page. Then you can simply change the color of your grid with that retrieved color. On the OnAppearing override of your page, use the following code to obtain your nav bar color:
protected override void OnAppearing()
{
var navPage = Application.Current.MainPage as NavigationPage;
if (navPage != null)
{
var barColor = navPage.BarBackgroundColor;
}
base.OnAppearing();
}
Or, as someone mentioned earlier, you can predefine your colors in App.xaml and then simple use it from there.
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="Blue"/>
<Setter Property="BarTextColor" Value="White"/>
</Style>
The BarBackgroundProperty is an attached property from NavigationPage. Be aware that it can change on every page you push to your NavigationPage.
Supposing you have an App.Current.MainPage set like this:
Page main = new MainPage();
Page navigation = new NavigationPage(main)
{
BarBackgroundColor = Color.Red,
BarTextColor = Color.Yellow
};
The navigation page is the one that owns the BarBackgroundColor property. So if you want to retrieve it, you should get it from there. I can't see how you can get this through a StaticResource.
I guess you can achieve this through a property on your viewmodel. For example:
public class MyViewModel
{
...
public Color BarBackgroundColor
{
get
{
return ((NavigationPage)App.Current.MainPage)?.BarBackgroundColor;
}
}
...
}
And to use it on your XAML (Once MyViewModel {or some inheritance of it} is the BindingContext or your page):
BackgroundColor="{Binding BarBackgroundColor}"
I hope it helps.
You may use global style by placing the code below into App.xaml
<Application.Resources>
<ResourceDictionary>
<Color x:Key="NavigationPrimary">#1A237E</Color>
<Style TargetType="NavigationPage">
<Setter Property="BarBackgroundColor" Value="{StaticResource NavigationPrimary}" />
<Setter Property="BarTextColor" Value="White" />
</Style>
<Style TargetType="Grid">
<Setter Property="BackgroundColor" Value="{StaticResource NavigationPrimary}" />
</Style>
</ResourceDictionary>
</Application.Resources>
Related
I need to set style at the back of the code. How do I achieve that? I have set style in the app, however I am using on Idom and seems I can't add OnPlatform to the same style so I have decided to keep on Idiom and set this in the back of the page
I have this and this throws an exception
if (DefaultSettings.DevicePlatform == "iOS" )
{
layout.Style = (Style)Resources["Relative"];
}
else
{
layout.Style = (Style)Resources["RelativeAndroid"];
}
App.xaml
<Style x:Key="YouriOSStyle" TargetType="RelativeLayout">
<Setter Property="BackgroundColor" Value="Blue"/>
</Style>
<Style x:Key="YourAndroidStyle" TargetType="RelativeLayout">
<Setter Property="BackgroundColor" Value="Red"/>
</Style>
Code behind
// better statement would be this
if(Device.RuntimePlatform == Device.iOS)
{
layout.SetDynamicResource(RelativeLayout.StyleProperty, "YouriOSStyle");
}
else
{
layout.SetDynamicResource(RelativeLayout.StyleProperty, "YourAndroidStyle");
}
What is the best way to place a SearchBar inside of your NavigationBar for an android app?
What is the best way to place a SearchBar inside of your NavigationBar?
The TitleView could help you display the SearchBar in the navigation bar easily.
Check the code:
<ContentPage ...>
<NavigationPage.TitleView>
<<SearchBar Text="testing for search bar"/>
</NavigationPage.TitleView>
...
</ContentPage>
Update:
Page.xaml
<local:CustomPage
...
xmlns:local="clr-namespace:App19F_5"
x:Class="App19F_5.Page6">
...
</local:CustomPage>
Page.xaml.cs
public partial class Page6 : CustomPage
{
...
}
CustomPage.xaml
<ContentPage ... x:Class="App19F_5.CustomPage">
<NavigationPage.TitleView>
<SearchBar />
</NavigationPage.TitleView>
</ContentPage>
I am working on a mvvm light xamarin forms application where i allow the user to create there own theme with in the application itself. As of right now, i have everything working as intended with the exception of the send button(image icon), add button (image icon), and hamburger menu icon.
The user selects a image/name, then the hex value from that color is applied to the control/font. But i have run into the issue when trying to programmatically set the hamburger menu color.I started with the android side of things.I can set the color once using styles.xml.
But this not sufficient for what i am trying to do. I haven't figure out how to get a reference to the toggledrawer to change the color without creating a new reference and supplying drawables.
I will also need to have the same action happen on iOS(changeable color hamburger menu). I don't want to supply images because the user will set the color based on a hex value...what is my best option? Is what i am trying to do even possible at this point?
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected ActionBarDrawerToggle drawerToggle;
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
Rg.Plugins.Popup.Popup.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
drawerToggle.getDrawerArrowDrawable().setColor(getResources().getColor(R.color.white));
}
}
i found this code here:
drawerToggle.getDrawerArrowDrawable().setColor(getResources().getColor(R.color.white));
It would be ideal, but i don't have a reference to drawerToggle...(the object is null)
i also tried to setting it using styles.xml as should below:
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MainTheme" parent="MainTheme.Base">
</style>
<!-- Base theme applied no matter what API -->
<style name="MainTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
<!--If you are using revision 22.1 please use just windowNoTitle. Without android:-->
<item name="windowNoTitle">true</item>
<!--We will be using the toolbar so no need to show ActionBar-->
<item name="windowActionBar">false</item>
<!-- Set theme colors from http://www.google.com/design/spec/style/color.html#color-color-palette -->
<!-- colorPrimary is used for the default action bar background -->
<item name="colorPrimary">#2196F3</item>
<!-- colorPrimaryDark is used for the status bar -->
<item name="colorPrimaryDark">#1976D2</item>
<!-- colorAccent is used as the default value for colorControlActivated
which is used to tint widgets -->
<item name="colorAccent">#FF4081</item>
<!-- You can also set colorControlNormal, colorControlActivated
colorControlHighlight and colorSwitchThumbNormal. -->
<item name="windowActionModeOverlay">true</item>
<item name="android:datePickerDialogTheme">#style/AppCompatDialogStyle</item>
<item name="drawerArrowStyle">#style/DrawerArrowStyle</item>
</style>
<style name="DrawerArrowStyle" parent="#style/Widget.AppCompat.DrawerArrowToggle">
<item name="spinBars">true</item>
<item name="color">#android:color/green</item>
</style>
<style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
<item name="colorAccent">#FF4081</item>
</style>
</resources>
This code does work to set it once, but i need it reset within the application by a button click. So this is not sufficient for the what i am trying to do.
add hamburger menu icon to drawable folder
Add code where you wish to change it.
var toolbar = FindViewById<AndroidToolbar>(Resource.Id.toolbar);
var view = (AppCompatImageButton)toolbar.GetChildAt(2);
// 1. actionmenuview (primary/secondary menu icons),
// 2. appcompattextview (title),
// 3. appcompatimagebutton (hamburger icon)
view.SetImageDrawable(d);
// view.SetImageDrawable(d);
In my case, I have menu Icons so I select GetChildAt(2) [the third item]
Here's my XAML:
<?xml version="1.0" encoding="UTF-8"?>
<TemplatedView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:Core.View.Control"
x:Class="Core.View.Control.MyButton">
<TemplatedView.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="MyButtonTemplate">
<Grid BackgroundColor="Teal">
<!-- other irrelevant stuff. Trust me, it's irrelevant. -->
<Grid x:Name="MyGrid" Grid.Row="1" ColumnSpacing="0" BackgroundColor="{TemplateBinding Parent.BGCol}"> <!-- Can't get this TemplateBinding to work -->
<!-- If I change the above to something static, like BackgroundColor="Orange", it works. -->
</ControlTemplate>
<Style TargetType="TemplatedView" x:Key="MyButtonStyle">
<Setter Property="ControlTemplate" Value="{StaticResource MyButtonTemplate}" />
</Style>
And my code behind:
namespace Core.View.Control
{
public partial class MyButton : TemplatedView
{
public static readonly BindableProperty BGColProperty =
BindableProperty.Create("BGCol", typeof(Color), typeof(MyButton), Color.Orange);
public Color BGCol
{
get
{
return (Color)GetValue(BGColProperty);
}
set
{
SetValue(BGColProperty, value);
}
}
public MyButton()
{
InitializeComponent();
Style = (Style)this.Resources["MyButtonStyle"];
}
// ...
If I change BGColproperty to be of type string and use "Orange" instead of Color.Orange everywhere...it still doesn't work.
How do I bind the background property of the Grid control in my ControlTemplate to BGCol?
[ignore]
Irrelevant text because SO is still not happy, saying too much code.
Sometimes code with inline comments (as I've done) pretty much explains it better than any amount of text can, and you'd think that a site like SO would understand this, but nah.
More blabber.
More still.
Oh here we go, this seems enough.
[/ignore]
<Grid x:Name="MyGrid" BackgroundColor="{TemplateBinding BGCol}" >
Template Bindings go to the control, so the Parent is just confusing it.
How to change text color and font of rows header in browse fragment?.
The text not in menu but the text that appears above the rows.
I am assuming you are using the provided android.support.v17.leanback.widget.RowHeaderPresenter as the presenter for the HeaderFragment in your BrowseFragment.
The RowHeaderPresenter inflates the layout from R.layout.lb_row_header which looks like this:
<android.support.v17.leanback.widget.RowHeaderView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/row_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?rowHeaderStyle" />
As you can see, this uses a style attribute called rowHeaderStyle, which is normally pointing to #style/Widget.Leanback.Row.Header. You can override this by putting the following in your styles.xml:
<style name="MyCustomRowHeaderStyle" parent="Widget.Leanback.Row.Header">
<item name="android:textColor">#color/red</item>
</style>
<style name="MyCustomBrowseStyle" parent="Theme.Leanback.Browse">
<item name="rowHeaderStyle">#style/MyCustomRowHeaderStyle</item>
</style>
And then use MyCustomBrowseStyle for the Activity containing the BrowseFragment by declaring it in your AndroidManifest.xml.
In addition to David's answer.
rowHeaderStyle applies the style both to menu items in HeaderFragment and row titles in RowFragment (these two fragments compose your BrowseFragment).
If you want their styles (font colors in particular) to be different, you can override BrowseFragment::onCreateHeadersFragment() and apply specific theme at that point.
1) Add these styles to styles.xml:
<style name="AppTheme.Leanback.Browse.Row" parent="#style/Theme.Leanback.Browse">
<item name="rowHeaderStyle">#style/AppTheme.Leanback.Row</item>
</style>
<style name="AppTheme.Leanback.Browse.Header" parent="#style/AppTheme.Leanback.Browse.Row">
<item name="rowHeaderStyle">#style/AppTheme.Leanback.Header</item>
</style>
<style name="AppTheme.Leanback.Row" parent="Widget.Leanback.Row.Header">
<item name="android:textColor">#color/font_row</item>
</style>
<style name="AppTheme.Leanback.Header" parent="Widget.Leanback.Row.Header">
<item name="android:textColor">#color/font_header</item>
</style>
2) Apply AppTheme.Leanback.Browse.Row theme to your activity in manifest.
3) Apply AppTheme.Leanback.Browse.Header theme to headers in your BrowseFragment:
// Kotlin snippet
override fun onCreateHeadersFragment() : HeadersFragment {
class CustomHeadersFragment : HeadersFragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return super.onCreateView(
inflater.cloneInContext(ContextThemeWrapper(inflater.context, R.style.AppTheme_Leanback_Browse_Header)),
container,
savedInstanceState
)
}
}
return CustomHeadersFragment()
}
The answer by david.mihola helps with the color, however I still had problems with setting a custom font globally. For everybody who stumbles upon this question and is puzzled about this as well, here is my solution:
Thanks to the awesome work done by chrisjenx (Calligraphy), you can easily set a global (custom) font.
Simply add Calligraphy to your gradle.build and add the following snippet to your Application.onCreate():
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath("fonts/MyCustomFont.ttf")
.setFontAttrId(R.attr.fontPath)
.build()
);
and in every Activity add the following:
#Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(CalligraphyContextWrapper.wrap(newBase));
}
This has done the font-trick for me on every single TextView, without modifying layouts. The documentation of Calligraphy also offers some more possibilities. Check it out.
I hope this helps other people who find this question and are trying to set (custom) fonts globally.