3

I want to implement material outlined textbox in Xamarin.Forms. I had created custom renderers but not able to apply style to it. I want text box like this image https://i.stack.imgur.com/7pWPr.png

By creating custom renderer and inheriting from TextInputLayout displays default material textbox. https://i.stack.imgur.com/Ek9Vb.jpg

Himanshu Dwivedi
  • 7,934
  • 3
  • 31
  • 52
Saiyam Shah
  • 57
  • 1
  • 6
  • Custom renderer is an option but you can also do it using with Grid,Boxview (or Frame),Label, Entry and some imagination. – ayberkzeray Dec 02 '19 at 07:27
  • @SaiyamShah Hi , if you want to custom a `EntryRenderer` to use `Material Design Text Input Layout` , it will be impossible . Beacause `EntryRenderer` of Xamarin Forms Inherited from `EditText` in Android . Therefore , if using Renderer to realize it , you should use `ViewRenderer` . – Junior Jiang Dec 11 '19 at 01:34

3 Answers3

3

You can achieve using Grid with some -ve margin value like this:

<Grid>
    <Frame Padding="10"
            BorderColor="#570dff"
            HasShadow="False">
        <Entry Placeholder="Enter here"/>
    </Frame>
    <Label Text=" UserName "
            FontSize="15"
            TextColor="#570dff"
            BackgroundColor="white"
            HorizontalOptions="Start"
            VerticalOptions="Start"
            Margin="20,-10,0,0"/>
</Grid>

Output:

enter image description here

Himanshu Dwivedi
  • 7,934
  • 3
  • 31
  • 52
  • Actually I can use Grid, but I want to use Material Design Text Input Layout. i.e Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense I had created custom renderer, but not able to apply styles to control programmatically. – Saiyam Shah Dec 05 '19 at 15:16
3

You can use Custom Renderer to custom a View which contained a material designed Entry .

Create a EntryView in Forms:

public class EntryView : ContentView
{
    public static readonly BindableProperty TextProperty =
      BindableProperty.Create("Text", typeof(string), typeof(EntryView), null);
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
}

Second , you need to create the EntryViewRenderer in Android :

public class EntryViewRenderer : ViewRenderer
{
    global::Android.Views.View view;
    global::Android.Widget.EditText editText;
    EntryView entryView;
    Activity activity;

    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
    {
        base.OnElementChanged(e);
        if(e.NewElement != null)
        {
            entryView= e.NewElement as EntryView;
        }

        if (e.OldElement != null || Element == null)
        {
            return;
        }

        try
        {
            SetupUserInterface();
            SetupEventHandlers();
            AddView(view);
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(@"           ERROR: ", ex.Message);
        }
    }

    private void SetupEventHandlers()
    {
        editText.TextChanged += EditText_TextChanged;
    }

    private void EditText_TextChanged(object sender, Android.Text.TextChangedEventArgs e)
    {
        entryView.Text = editText.Text; 
        Console.WriteLine("chanegd +" + entryView.Text);
    }

    void SetupUserInterface()
    {
        activity = this.Context as Activity;
        view = activity.LayoutInflater.Inflate(Resource.Layout.EntryLayout, this, false);

        editText = view.FindViewById<EditText>(Resource.Id.editText1);
    }

    protected override void OnLayout(bool changed, int l, int t, int r, int b)
    {
        base.OnLayout(changed, l, t, r, b);

        var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
        var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);

        view.Measure(msw, msh);
        view.Layout(0, 0, r - l, b - t);
    }
}

In addition , you need to add EntryLayout for this View :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox">
        <EditText
            android:id="@+id/editText1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Label"
            android:outlineSpotShadowColor="@color/cardview_shadow_start_color"/>
    </android.support.design.widget.TextInputLayout>

</LinearLayout>

Now , you can use it in Xaml of Xamarin Forms :

xmlns:app18="clr-namespace:App18"

<app18:EntryView Text="abc"/>

The effect :

enter image description here

If need to modify color of outline , just add style in Resources/values/styles.xml .

  <style name="LoginTextInputLayoutStyle" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense">
    <item name="boxStrokeColor">#570dff</item>
    <item name="boxStrokeWidth">2dp</item>
    <item name="android:textColorHint">#570dff</item>
  </style>

In Resources/values/colors.xml add follow code :

<color name="mtrl_textinput_default_box_stroke_color">#570dff</color>

Finally used in EntryLayout.xml :

<android.support.design.widget.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    style="@style/LoginTextInputLayoutStyle">
    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Label"/>
</android.support.design.widget.TextInputLayout>

The efect:

enter image description here

Junior Jiang
  • 12,430
  • 1
  • 10
  • 30
  • This is what I needed. Thank you so much, I will try it out. – Saiyam Shah Jan 03 '20 at 05:52
  • I had tried your solution, but I am facing some error. I am posting my solution link https://github.com/saiyamshah143/MaterialEntry. It also has the error screenshot which I am facing. – Saiyam Shah Jan 03 '20 at 08:19
  • @SaiyamShah Okey , I will check it . – Junior Jiang Jan 03 '20 at 08:22
  • @SaiyamShah From shared code , I just modify this line :`` it works . – Junior Jiang Jan 03 '20 at 08:41
  • It's working, but still not as expected - http://prntscr.com/qiu2l5 – Saiyam Shah Jan 03 '20 at 10:48
  • @SaiyamShah Eh , maybe your code has something different with mine . I tested your shared project , it worked as my shared screenshot . – Junior Jiang Jan 06 '20 at 01:30
  • @junior-jiang-msft Yeah, actually I had checked on Genymotion emulator, that's why it wasn't as expected, but when I run on an actual device, it was as expected. Thank you once again.. – Saiyam Shah Jan 06 '20 at 04:20
  • @SaiyamShah That's Great ! Remember to vote up answer when have time. *.^ – Junior Jiang Jan 06 '20 at 05:32
  • I am getting this error `JNI RegisterNativeMethods: attempt to register 0 native methods for crc643f46942d9dd1fff9.ViewRenderer [0:] Object reference not set to an instance of an object.: ERROR:` in this line `activity.LayoutInflater.Inflate(Resource.Layout.EntryLayout, this, false)` – Ghasan غسان Mar 26 '20 at 01:59
  • @Ghasan Okey , does it works before and occurs error recently in which device? – Junior Jiang Mar 26 '20 at 02:34
  • @JuniorJiang-MSFT, thanks. I just attempted it on Android emulator on Windows. I tried the repo posted by Saiyam, and it is working. Anyways, I have solved it in another way. Thank you :) – Ghasan غسان Mar 26 '20 at 10:20
  • Is there something like this for iOS part? Thanks – white.devils Apr 07 '20 at 20:06
  • Usually you want to set **label(hint)** depending on a bindable property, so make sure to do it on the `TextInputLayout`, not `EditText`, as stated at [material.io](https://material.io/develop/android/components/text-fields/) "Note: The android:hint should always be set on the TextInputLayout instead of on the EditText in order to avoid unintended behaviors." – Tomasz Dolny Jun 13 '20 at 22:05
0
<Grid Margin="20">
    <Frame  Padding="10"
            BorderColor="#570dff"
            HasShadow="False">
        <Entry Placeholder="Enter here"/>
    </Frame>
    <Label  Text=" UserName "
            FontSize="15"
            TextColor="#570dff"
            BackgroundColor="white"
            HorizontalOptions="Start"
            VerticalOptions="Start"
            Margin="20,-10,0,0"/>
</Grid>

This is great, it also helped me. I added a Margin of 20 to the grid to make it look better.

Grigory Zhadko
  • 1,484
  • 1
  • 19
  • 33
Ninad Kulkarni
  • 61
  • 1
  • 11