I have a Xamarin.Forms SearchBar on a StackLayout with a dark background color.
By default the input field is dark as well, probably due to a transparent background. To modify the search bar background color there is a BackgroundColor property. (In the example below I set it to dark gray.)
But how to adjust the text color? There is no such property. And even with a custom search bar renderer I don't find a solution.
This is how it looks with just the placeholder:
...and with some input (black "Hello world!" on a pretty dark background):
Here is the code for an Android Custom renderer that will do the trick. I would upload a screenshot, but I don't have enough points yet :(
using System;
using Android.Widget;
using Android.Text;
using G = Android.Graphics;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly:ExportRenderer( typeof(MySearchBar), typeof(Some.Namespance.MySearchBar_Droid) )]
namespace Some.Namespace
{
public class MySearchBar_Droid : SearchBarRenderer
{
protected override void OnElementChanged( ElementChangedEventArgs<SearchBar> args )
{
base.OnElementChanged( args );
// Get native control (background set in shared code, but can use SetBackgroundColor here)
SearchView searchView = (base.Control as SearchView);
searchView.SetInputType( InputTypes.ClassText | InputTypes.TextVariationNormal );
// Access search textview within control
int textViewId = searchView.Context.Resources.GetIdentifier( "android:id/search_src_text", null, null );
EditText textView = (searchView.FindViewById( textViewId ) as EditText);
// Set custom colors
textView.SetBackgroundColor( G.Color.Rgb( 225, 225, 225 ) );
textView.SetTextColor( G.Color.Rgb( 32, 32, 32 ) );
textView.SetHintTextColor( G.Color.Rgb( 128, 128, 128 ) );
// Customize frame color
int frameId = searchView.Context.Resources.GetIdentifier( "android:id/search_plate", null, null );
Android.Views.View frameView = (searchView.FindViewById( frameId ) as Android.Views.View);
frameView.SetBackgroundColor( G.Color.Rgb( 96, 96, 96 ) );
}
}
}
You can achieve this by creating a custom View that has a bindable-property like ForegroundTextColor and then create a custom renderer.
In the custom renderer you can inherit from the platform specific renderer, i.e. on WindowsPhone it is:-
Xamarin.Forms.Platform.WinPhone.SearchBarRenderer
You can then monitor for property changes to the bindable-property you created and set the platform native control Text-color that is used to change the appearance of the non-editing view of the SearchBar.
You also have to monitor for IsFocused and apply the colouring on WindowsPhone, at least, also. This may also apply for other platforms possibly as well.
Update 1:-
========
In reply to your comment you don't have to render the whole SearchBar yourself.
If you inherit from the renderer you are able to customize things finer.
With specific reference to Android to achieve this you have to get reference to AutoCompleteTextView and then you can call SetTextColor to change the color.
Update 2:-
==========
SearchBar is a composite control in Android.
The AutoCompleteTextView is buried rather deep in the hierarchy.
On 4.4 this can be found using the following code. Other versions may well differ. This is by no means a good approach necessarily for production using ordinal indexes however:-
AutoCompleteTextView objAutoTextView = (AutoCompleteTextView)(((this.Control.GetChildAt(0) as ViewGroup).GetChildAt(2) as ViewGroup).GetChildAt(1) as ViewGroup).GetChildAt(0);
Where this is the renderer class.
You can then call objAutoTextView.SetTextColor with the color to achieve the change in color to the SearchBar foreground text.
I finally found a very simple solution:
I accidentally used the Android Theme #android:style/Theme.Holo.Light and modified all colors explicitly. But to get a bright text color on a search bar you better use #android:style/Theme.Holo.
It does not allow you to set the color very precisely, but changing it from black to white was all I needed in this case.
You can make the following changes in the xaml if you are using xaml to obtain the different text color of search bar on different platforms:
<SearchBar x:Name="Search"
Placeholder="Search"
TextChanged="SearchBar_OnTextChanged"
SearchButtonPressed="OnSearch" BackgroundColor="#19588F">
<SearchBar.TextColor>
<OnPlatform x:TypeArguments="Color">
<OnPlatform.iOS>
Black
</OnPlatform.iOS>
<OnPlatform.Android>
White
</OnPlatform.Android>
<OnPlatform.WinPhone>
White
</OnPlatform.WinPhone>
</OnPlatform>
</SearchBar.TextColor>
</SearchBar>
Here's how I did it, another way:
[assembly: ExportRenderer(typeof (CustomSearchBar), typeof (CustomSearchBarRenderer))]
namespace Bahai.Android.Renderers
{
public class CustomSearchBarRenderer : SearchBarRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<SearchBar> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
SearchBar element = (SearchBar) this.Element;
var native = (global::Android.Widget.SearchView) Control;
// do whatever you want to the controls here!
//--------------------------------------------
// element.BackgroundColor = Color.Transparent;
// native.SetBackgroundColor(element.BackgroundColor.ToAndroid());
// native.SetBackgroundColor(Color.White.ToAndroid());
//The text color of the SearchBar / SearchView
AutoCompleteTextView textField = (AutoCompleteTextView)
(((Control.GetChildAt(0) as ViewGroup)
.GetChildAt(2) as ViewGroup)
.GetChildAt(1) as ViewGroup)
.GetChildAt(0);
if (textField != null)
textField.SetTextColor(Color.White.ToAndroid());
}
}
}
}
SearchBar has a TextColor property. At least in Xamarin 5.
<SearchBar
TextColor="Black"
Text="{Binding SearchString}">
Related
I am building a cross platform app using Xamarin forms on a mac using Visual code for mac.
I need to be able to change the status bar text and background colors on both the iOS and Android version of the APP.
I tried James Montemagno's solution from his video.
https://www.youtube.com/watch?v=GKJRR8_DSSs
So every thing was good till we needed to use this code window.DecorView.SystemUiVisibility
This code is deprecated and Visual Studio does not offert any hint to what I can use instead. I have tried to find but all I get is Android native related information 1.
I really wish I would not have to use "native" code for some thing so basic in mobile App development. I understand that using the Shell class will allow me do use the minimal amount of "native" code possible, really wish to avoid coding any native code if possibly.
Context: I need to set the Android version of the app so that is has a white status bar and black text. Also I have 1 page with a black background image taking the full view, so on this page I need the status bar to be transparent and use a white foreground color.
So what does replace window.DecorView.SystemUiVisibility = darkStatusBarTint ? flag : 0; ??
The app is targeting Android API 30.
This is the code that is in the video
From main project stub
using System;
using System.Drawing;
namespace MyApp.Helpers
{
public interface IEnvironment
{
void SetStatusBarColor(Color color, bool darkStatusBarTint);
}
}
From android stub
using System;
using System.Drawing;
using System.Runtime.CompilerServices;
using Android.OS;
using EGrid18.Helpers;
using Xamarin.Essentials;
using Xamarin.Forms;
using Color = System.Drawing.Color;
using DependencyAttribute = Xamarin.Forms.DependencyAttribute;
[assembly: Dependency(typeof(MyApp.Droid.Environment))]
namespace MyApp.Droid
{
public class Environment: IEnvironment
{
public void SetStatusBarColor(Color color, bool darkStatusBarTint)
{
if (Build.VERSION.SdkInt < Android.OS.BuildVersionCodes.Lollipop)
return;
var activity = Platform.CurrentActivity;
var window = activity.Window;
window.AddFlags(Android.Views.WindowManagerFlags.DrawsSystemBarBackgrounds);
window.ClearFlags(Android.Views.WindowManagerFlags.TranslucentStatus);
window.SetStatusBarColor(color.ToPlatformColor());
if(Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M)
{
var flag = (Android.Views.StatusBarVisibility)Android.Views.SystemUiFlags.LightStatusBar;
#pragma warning disable CS0618 // Le type ou le membre est obsolète
//problen is here
window.DecorView.SystemUiVisibility = darkStatusBarTint ? flag : 0;
#pragma warning restore CS0618 // Le type ou le membre est obsolète
}
}
}
}
If you want to make sure that the status bar text and icons remain legible when you set the status bar color, then you can do the following:
public void SetSystemBarColor(Color color, bool lightStatusBarTheme)
{
Window?.SetStatusBarColor(color);
var statusBarFlags = lightStatusBarTheme ? (int)WindowInsetsControllerAppearance.LightStatusBars : 0;
Window?.InsetsController?.SetSystemBarsAppearance(statusBarFlags, (int)WindowInsetsControllerAppearance.LightStatusBars);
}
Then call it as follows in your Activity:
//black status bar
SetSystemBarColor(Color.Black, false);
//white status bar
SetSystemBarColor(Color.White, true);
As systemUiVisibility property is deprecated, you could use WindowInsetsControllerCompat. Refer to jamesmontemagno's MyCoffeeApp and try the following code:
WindowCompat.GetInsetsController(window, window.DecorView).AppearanceLightStatusBars = darkStatusBarTint;
That means if set AppearanceLightStatusBars to true, then changes the foreground color of the status bars to light so that the items on the bar can be read clearly.
For more information, you could see WindowInsetsControllerCompat
Hope it works for you.
How can I change background colour of search support fragment in android leanback library. I have tried to find a public function to do the same just like in BrowseSupportFragment.
Try this:
val backgroundManager = BackgroundManager.getInstance(requireActivity())
val backgroundManager.attach(requireActivity().window)
backgroundManager?.color = Color.parseColor("#ff0000")
It works for the RowsSupportFragment, so I guess it works for search too
Currently, I'm looking to change the design of the button that closes the Android keyboard. Currently it looks like: Basic Android Keyboard. I want to remove the checkmark and replace it with some text like OK or Done without changing the whole keyboard.
Using ImeOptions, I know i can set the Android.Views.InputMethods.ImeAction to a default icon, but none of the default icons are what I'm looking for.
Using SetImeActionLabel("OK", Android.Views.InputMethods.ImeAction.Done), I can edit the text that's being shown, but it's only text. I need it to have the green, circular background. If I go with this route, I'm unsure on how I can edit the styles of this ActionLabel. Here is a picture for reference: Android Keyboard with OK.
I'm having a lot of trouble finding a similar example or problem and can't exactly solve it myself.
You cann add shape to it as a background
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Entry> e)
{
base.OnElementChanged(e);
var newCustomEntryElement = e.NewElement as CustomEntry;
if (Control == null || newCustomEntryElement == null)
{
return;
}
Control.ImeOptions = ImeAction.Go;
Control.SetImeActionLabel("Go", ImeAction.Go);
var shape = new ShapeDrawable(new RectShape());
shape.Paint.Color = Android.Graphics.Color.Red;
shape.Paint.StrokeWidth = 0;
shape.Paint.SetStyle(Paint.Style.Stroke);
Control.SetBackground(shape);
}
My app is using a custom Notification layout with RemoteViews.
To display text, the layout is using the following system styles:
android:TextAppearance.Material.Notification.Title
android:TextAppearance.Material.Notification
This works fine.
However, the TextAppearance style can't be used to set the value of android:tint, so I had to hardcode the color.
To my best knowledge, there's no special system style for setting notification ImageButton tint.
Hardcoded colors work fine on the current Android 5+ systems, but some users install custom ROMs with custom dark themes, and the notification looks wrong, i.e. black icons on black background.
Is there any way to get the system notification icon / imagebutton color, and apply it from an XML layout?
Or maybe there's another way to achieve this?
Sorry, But as per my knowledge custom ROM's have separate system designs,configurations and that are not official as well.
So,supporting Custom ROM without knowledge about its design is not possible.
And android APIs are for supporting official ROM's.
Hope it Helps!!
Try this example :
Definition for notification :
// Declare variable
public static Bitmap icon;
// Assign value but this line can be different depends on current
// android sdk vesion ...
icon = BitmapFactory.decodeResource(getApplicationContext().getResources(), R.drawable.YOUR_IMAGE);
mBuilder = new NotificationCompat.Builder(this);
mBuilder.setShowWhen(false);
mBuilder.setDefaults(Notification.DEFAULT_ALL);
mBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
mBuilder.setSmallIcon(R.drawable.image1); // One way to load img
mBuilder.setContentText("this text not visible");
mBuilder.setLargeIcon(icon);// This is the line
mBuilder.setPriority(Notification.PRIORITY_DEFAULT);
mBuilder.setContent(contentNotifySmall); // ORI
//mBuilder.setAutoCancel(false);
mBuilder.setCustomBigContentView(contentNotify);
I setup small and big variant for any case , this is important.
for background can you try these attributes...
app:backgroundTint="#color/pay"
---------Or-------------
android:tint="#color/white"
You can take textColor from TextAppearance_Compat_Notification_Title and add it as tint to an image programmatically like this
val remoteViews = RemoteViews(service.packageName, R.layout.notification_layout)
val icon = Icon.createWithResource(context, R.drawable.icon)
val attrs = intArrayOf(android.R.attr.textColor)
with(context.obtainStyledAttributes(R.style.TextAppearance_Compat_Notification_Title, attrs)) {
val iconColor = getColor(0, Color.GRAY)
icon.setTint(iconColor)
recycle()
}
remoteViews.setImageViewIcon(R.id.ibPlayPause, icon)
You can use a notificationlistenerservice to get an active notification. This returns a list of StatusBarNotifications, then just:
StatusBarNotifcation sBNotification = activeNotifications[0];
Notification notification = sBNotification.getNotification();
int argbColor = notification.color;
If you change ImageButton to ImageView in your layout you can update it with
RemoteViews remoteView = getRemoteViews(context);
// load base icon from res
Bitmap baseIcon = BitmapFactory.decodeResource(context.getResources(), R.drawable.base_icon);
// edit Bitmap baseIcon any way for your choose
Bitmap editedBitmap = ...
// update notification view with edited Bitmap
remoteView.setImageViewBitmap(R.id.button_icon, edited);
P.S. you can edit Bitmap like this:
https://stackoverflow.com/a/5935686/7630175 or any other way
Hope it's help
I wanted to try out this funny title bar coloring, but it doesn't work for me as
getWindow().findViewById(android.R.id.title);
returns null. So I had a look at it with Hierarchy Viewer and found out that the view is called id/action_bar instead. But there's no R.id.action_bar (autocomplete doesn't offer it and there's nothing like this is R.java).
So now I'm doubly confused:
Is android.R.id.title sort of obsolete now (I'm using version 16 in my emulator)?
Where does id/action_bar come from?
What's the recommended and simple practice w.r.t. compatibility?
Should I get ActionBarSherlock? I originally just wanted to change the title bar color... not fool around with it a lot.
Use the code below to get the ActionBar's id:
val actionBarId = resources.getIdentifier("action_bar", "id", packageName)
And use findViewById you can find the action bar.
Then find the title from actionbar's children (in normal cases):
val actionbar = findViewById<ViewGroup>(actionBarId)
for (view in actionbar.children) {
if (view is TextView) {
// this is the titleView
}
}
However, if you just want to change the title view's text, just use getSupportActionBar:
supportActionBar?.apply {
// set title text
title = "Hello"
// set colored title text
val coloredTitle = SpannableString("Hello")
coloredTitle.setSpan(ForegroundColorSpan(Color.RED), 0, coloredTitle.length, 0)
title = coloredTitle
}
I would recommend using ActionBarSherlock if you're looking for compatibility with Android versions before API level 14 / Android 4.0.
Changing the background of the ActionBar is straightforward and is most easily done via styles. See the "Background" section of http://android-developers.blogspot.com/2011/04/customizing-action-bar.html
You can also change it via code. Put this in your onCreate():
GradientDrawable gradientDrawable = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, new int[] {Color.RED, Color.GREEN});
getActionBar().setBackgroundDrawable(gradientDrawable);
Here is a screenshot of this code in action: