0

Can You Change Buttons color onfocused like yout do in TextField In Nativescript/Angular.. It works in TextField but not in BUTTON Does someone knows some other solution, im trying to build a tvapp i need to change the color when is focused in Button or Label

HTML File

<Page loaded="onPageLoaded($event)">
    <StackLayout>
        <Button  text="My Button 2"  class="my_button_2" >  </Button>
        <TextField class="input-field"> </TextField>
    </StackLayout>
</Page>
CSS File
.my_button_2:focus{
    background:olive;
    border-color: red;
    border: 2;
    border-width: 2;
}

.my_button_2:active{
    background:olive;
    border-color: red;
    border: 2;
    border-width: 2;
}


.input-field:focus {
border-bottom-color: red;
Edin.A
  • 21
  • 5

3 Answers3

0

According to the nativescript's UI & Styling docs, nativescript currently supports only the :highlighed pseudo selector on Button.

You should use it like this:

.my_button_2:highlighted {
    background:olive;
    border-color: red;
    border: 2;
    border-width: 2;
}

Note: by default on Android, the Button element is not focusable. So if you want to enable focus on an Android Button element, you need to first add modifications to its native component (android.widget.Button) using the following:

Add a 'loaded' eventlistener:

<Button (loaded)="onButtonLoaded($event)" text="My Button 2"  class="my_button_2"></Button>

Then, when the element is loaded, enable focus:

import { Button } from "@nativescript/core";

export class AppComponent {
    onButtonLoaded(event: TapGestureEventData) {
        const btn = event.object as Button;

        const androidButton = btn.android;
        androidButton.setFocusableInTouchMode(true); // make Button focusable
    }
}

This makes the Button focusable, and you can focus on it manually like so:

import { Component, ElementRef, ViewChild } from "@angular/core";
import { Button } from "@nativescript/core";

export class AppComponent {
    @ViewChild("btn") btn: ElementRef<Button>;

    focusBtn() {
        const isFocused = this.btn.nativeElement.focus();
        console.log(`did focus? ${isFocused}`);
    }
}

Note: You still can't use the button:focus css pseudo-selector due to the framework limitation to :highlighted as described above.

However, to solve your case, as a work around if your scenario is to set the focus manually, then you can use the following to achieve a focus-similar behavior (works on both Android and iOS):

CSS:

.focus {
    background:yellow;
    border-color: red;
    border: 2;
    border-width: 2;
}

.html template:

<Button (loaded)="onButtonLoaded($event)" text="My Button 2"  class="my_button_2" [ngClass]="{ 'focus': buttonIsFocused }"></Button>

.ts:

export class AppComponent {
    buttonIsFocused = false;

    focusOnButton() {
        // call this when you wish to add focus styling to the button
        this.buttonIsFocused = true;
    }

    defocusButton() {
        // call this when you wish to remove the focus styling
        this.buttonIsFocused = false;
    }
}

Check this to read more about nativescript styling. Check this and this to read more about the native iOS focusing.

Lorraine R.
  • 1,545
  • 1
  • 14
  • 39
  • The Problem is im not trying to get focus in touch,Im bulind an TV APP i need to navigate with DPAD so it needs to get focus automatically before i touch.By the way i solved it in android for ios i have sitll no idea im going to post the solution – Edin.A Jan 01 '22 at 21:35
  • Got it. Check my third link at the end, It is about the Focus system on tvOS. Hope that will help. – Lorraine R. Jan 01 '22 at 22:26
0

Here is the solution in Android onloaded event

HTML

<Button #myButton1 text="My Button 1" (tap)="OnTapButton_1($event)" (loaded)="onButtonLoaded_1($event)" class="button_style"></Button>

Component.ts File

public onButtonLoaded_1(args) {
    let btn = args.object as Button;
    let androidButton = btn.android;

    androidButton.setOnFocusChangeListener(new android.view.View.OnFocusChangeListener({
      onFocusChange:(view, hasFocus) => {
          if(hasFocus === true){
            btn.addPseudoClass("focus")
          }
          else {
            btn.deletePseudoClass("focus")

          }
        }
      }))
}

CSS

.button_style {
    android-elevation: 0;
    android-dynamic-elevation-offset: 0;
    background: rgba(190, 138, 17, 0.315);
    border-width: 0.3;
    border-color: rgba(190, 138, 17, 0.671);

}

.button_style:focus{
    android-elevation: 0;
    android-dynamic-elevation-offset: 0;
    background: rgba(190, 138, 17, 0.856);
    border-width: 0.3;
    border-color: rgba(116, 84, 11, 0.856);
}

Disbaling in it

androidButton.setOnFocusChangeListener(null)
Mad Physicist
  • 107,652
  • 25
  • 181
  • 264
Edin.A
  • 21
  • 5
0

Here it is the same solution for android but as Angular Directive

######## HTML #####################

<Button #myButton1 text="My Button 1" class="button_style" focusable (focusChange)="onFocusChange($event)"></Button>

Directive.ts File

import {Directive, ElementRef,EventEmitter,Output} from '@angular/core'

@Directive({
    selector: '[focusable]'
  })
  export class FocusableDirective {
    @Output('focusChange') focusChange = new EventEmitter<any>();
    constructor(private el: ElementRef<any>) {
      el.nativeElement.once('loaded', () => {
        el.nativeElement.android.setOnFocusChangeListener(new android.view.View.OnFocusChangeListener({
          onFocusChange: (view, hasFocus) => {
              this.focusChange.emit(hasFocus);
             }
         }));
        })
      }
  }

Component.ts File

  public onFocusChange(hasFocus){
    const mybtn = <Label>this.myButton.nativeElement
    if(hasFocus === true){
      mybtn.addPseudoClass("focus")
    }
    else {
      mybtn.deletePseudoClass("focus")

    }
  };

######## CSS #############

.button_style {
    android-elevation: 0;
    android-dynamic-elevation-offset: 0;
    background: rgba(190, 138, 17, 0.315);
    border-width: 0.3;
    border-color: rgba(190, 138, 17, 0.671);

}

.button_style:focus{
    android-elevation: 0;
    android-dynamic-elevation-offset: 0;
    background: rgba(190, 138, 17, 0.856);
    border-width: 0.3;
    border-color: rgba(116, 84, 11, 0.856);
}
Edin.A
  • 21
  • 5