Зміна кольору нижнього рядка EditText за допомогою appcompat v7


310

Я використовую appcompat v7, щоб отримати вигляд на Android 5 і менше. Це працює досить добре. Однак я не можу зрозуміти, як змінити нижній рядок і колір акценту для EditTexts. Це можливо?

Я спробував визначити спеціальний android:editTextStyle(див. Нижче), але мені вдалося змінити лише повний колір тла або колір тексту, але не нижню лінію та колір наголосу. Чи є конкретне значення властивості для використання? чи потрібно використовувати користувальницьке малювальне зображення через android:backgroundвластивість? чи не можна вказати колір у шестикутнику?

 <style name="Theme.App.Base" parent="Theme.AppCompat.Light.DarkActionBar">
     <item name="android:editTextStyle">@style/Widget.App.EditText</item>
 </style>

 <style name="Widget.App.EditText" parent="Widget.AppCompat.EditText">
     ???
 </style>

За даними джерел android API 21, начебто, користуються EditTexts з матеріальним дизайном colorControlActivatedі colorControlNormal. Тому я намагався змінити ці властивості у попередньому визначенні стилю, але це не впливає. Можливо, appcompat не використовує його. На жаль, я не можу знайти джерела для останньої версії програми з матеріальним дизайном.


визначте свою тему для редагування тексту
Meenal

Дякую за вашу пропозицію, але я це вже зробив. Я оновив своє запитання, щоб показати, що я вже намагався зробити. Моя проблема стосується атрибута, який потрібно використовувати в стилі теми для зміни кольору нижнього рядка редагування. В ідеалі я шукаю рішення, де я можу безпосередньо вказати колір у шестикутнику.
Лоран

Жодна з цих відповідей не працює для мене на 4.3. Чи є у вас робоче рішення?
Роберт Бейкер

Мені довелося продовжити AppCompatEditText, мабуть.
EpicPandaForce

Відповіді:


479

Нарешті я знайшов рішення. Він просто полягає у переосмисленні значення для colorControlActivated, colorControlHighlightа також colorControlNormalу визначенні теми вашого додатка, а не у стилі редагування тексту. Тоді подумайте використовувати цю тему для будь-якої діяльності, яку ви хочете. Нижче наведено приклад:

<style name="Theme.App.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="colorControlNormal">#c5c5c5</item>
    <item name="colorControlActivated">@color/accent</item>
    <item name="colorControlHighlight">@color/accent</item>
</style>

9
Я бачу, що колір гамбургера меню, кнопка "Назад" та смуга прокрутки змінилися на colorControlNormal.
ario

11
Це змінює колір нижнього рядка, але він також змінює всі інші елементи управління, такі як прапорці, перемикачі і т.д. Якщо ви хочете змінити нижній рядок одного EditText (як я), тоді вам слід змінити властивість android: background для цього EditText. Іншого шляху AFAIK немає.
Емануель Моклін

68
Якщо ви використовуєте бібліотеку підтримки v22 AppCompat, ви можете вказати тему в EditText як: android:theme="@style/Theme.App.Base. Це забезпечить, що стиль також не вплине на інші представлення у ваших макетах, які ви не хочете змінювати.
Алекс Локвуд

8
Не працював на Jelly Bean (4.2), але працював на Lollipop
Mangesh

3
Діяльність повинна успадковуватися від AppCompatActivity. Це не спрацює, якщо він успадкує від Activity.
Bharathwaaj

187

Я відчував, що на це потрібна відповідь у випадку, якщо хтось захоче змінити лише один редакційний текст. Я роблю це так:

editText.getBackground().mutate().setColorFilter(ContextCompat.getColor(context, R.color.your_color), PorterDuff.Mode.SRC_ATOP);

1
Але як я можу скинути фоновий режим за замовчуванням, у мене з’явилося багато помилок після виклику editText.getBackground (). ResetColorFilter () на Lollipop?
ультраон

Обережно! додавання цього може призвести до зміни кольору editText у ВСІЙ програмі. Тестовано на Nexus 5. OS 6.0.1.
Олексій Перевозчиков

1
@AlexPerevozchykov Ви можете мати рацію. Спробуйте додати .mutate () після .getBackground (). Це повинно це робити.
хордур

@hordurh так, це було, я отримав цю пропозицію трохи раніше, траверси поділяють один пул, тому перед зміною нам потрібно його мутувати
Алекс Перевозчиков

1
Якщо я використовую edittext, він працює, але цей метод не працює з програмою compat edittext для льодяника. чи знаєте ви, як я можу вирішити проблему?
Селін

145

У той час як рішення Laurents правильно, він приходить з деякими недоліками , як описано в коментарях , тому що не тільки в нижньому рядку EditTextотримує тоновані , але кнопка назад Toolbar, і CheckBoxesт.д. , а також.

На щастя , v22.1з appcompat-v7ввів деякі нові можливості. Тепер можна призначити певну тему лише одному виду. Прямо з журналу змін :

Вимкнене використання програми: тема для стилізації Панелі інструментів. Тепер ви можете використовувати android: тему для панелей інструментів на всіх пристроях API рівня 7 та вище та Android: підтримка теми для всіх віджетів на пристроях API рівня 11 та вище.

Тож замість того, щоб задати потрібний колір у глобальній темі, ми створимо новий і призначимо його лише EditText.

Приклад:

<style name="MyEditTextTheme">
    <!-- Used for the bottom line when not selected / focused -->
    <item name="colorControlNormal">#9e9e9e</item>
    <!-- colorControlActivated & colorControlHighlight use the colorAccent color by default -->
</style>

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/MyEditTextTheme"/>

1
Я не думаю, що це потрібно. colorControlNormalбез префікса андроїда використовується метод appcompat для підфарбовування віджетів, тоді як з префіксом він повертається до системного методу, і це доступно лише на пристроях API 21+.
reVerse

Хм, я перевірив на своєму льодяниковому пристрої, і він не відтіняє спеціальний колір, якщо ви не реалізуєте його у стилях v21 із простором імен Android.
користувач2968401

Я використовую 22.2.0версію AppCompat, але цей трюк не працює :(
Shajeel Afzal

1
використовуючи <item name = "colorAccent"> # 000000 </item> працював для мене замість colorControlNormal.
MikeOscarEcho

Ідеально для зміни лише одного редагування тексту в додатку! (Саме те, що мені потрібно! Спасибі)
Ромен Барб'є

99

Це можна змінити в XML, використовуючи:

Для Reference API> = 21 використовуйте сумісність:

android:backgroundTint="@color/blue"

Для зворотного API-сумісності <21 використовуйте:

app:backgroundTint="@color/blue"

10
Так, однак це працює лише для Android версій 21+ (kitkat & lolipop). Можливо, можна було б спробувати створити назад сумісне рішення.
DaMachk

12
Просто використовуйте backgroundTint="@color/blue"замість android:backgroundTint="@color/blue"зворотної сумісної підтримки
Kishan Vaghela

11
@KishanVaghela, замість використання android:backgroundTint="@color/blue", використовуйте app:backgroundTint="@color/blue"для підтримки пристроїв до Lollipop, дякую за ваш коментар!
blueware

2
@blueware Якщо ви хочете використовувати його в стилі, тоді нам не потрібно використовувати "додаток".
Кішань Вагела

додайте, tools:ignore="MissingPrefix"якщо червоний підкреслити поп підapp:backgroundTint="<your color>"
Мойсей Абріко

47

Ось рішення для API <21 і вище

Drawable drawable = yourEditText.getBackground(); // get current EditText drawable 
drawable.setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_ATOP); // change the drawable color

if(Build.VERSION.SDK_INT > 16) {
    yourEditText.setBackground(drawable); // set the new drawable to EditText
}else{
    yourEditText.setBackgroundDrawable(drawable); // use setBackgroundDrawable because setBackground required API 16
}

введіть тут опис зображення

Сподіваюся, це допоможе


@CoolMind вибачте за несвоєчасну відповідь. У мене перевірити цей код ще раз в бібліотеці підтримки 24.2.1, 25.1.1, 25.2.0для пристрою <21 і> 21 , і він все ще працює. Перевірте цей простий демо- диск.google.com/file/d/0B_poNaia6t8kSzU3bDFVazRSSDA/… . Я не знаю, чому цей код не працює для вас, тому, будь ласка, дайте мені знати. дякую
Фан Ван Лінь

@ Renjith вибачте за пізню відповідь, будь ласка, перевірте мій коментар вище
Фан Ван Лін

Як скинути колір за замовчуванням за допомогою цього коду?
Неф

35

Прийнята відповідь - це трохи більше на основі стилю, але найефективніше - додати атрибут colorAccent у вашому стилі AppTheme таким чином:

<style name="AppTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:editTextStyle">@style/EditTextStyle</item>
</style>

<style name="EditTextStyle" parent="Widget.AppCompat.EditText"/>

Атрибут colorAccent використовується для тонування віджетів у всьому додатку, тому його слід використовувати для послідовності


8
@Tomasz це не вимагає API 21+, тому що батьківська тема - це AppCompat, який переходить на API 7
TanmayP

Уххх. Дякую за це, я користувався name="android:colorAccent"помилково
Жюль,

29

Якщо ви користуєтесь, appcompat-v7:22.1.0+ви можете використовувати DravableCompat для тонування віджетів

    public static void tintWidget(View view, int color) {
        Drawable wrappedDrawable = DrawableCompat.wrap(view.getBackground());
        DrawableCompat.setTint(wrappedDrawable.mutate(), getResources().getColor(color));
        view.setBackgroundDrawable(wrappedDrawable);
    }

що це рятівник це дивовижно, ганьба це не добре знати
pt123

Будь ласка, рухайтесь вниз і дивіться мою відповідь щодо бібліотеки дизайну 23.2.0. Цей метод зараз марний.
ywwynm

21

Використання:

<EditText
    app:backgroundTint="@color/blue"/>

Це підтримуватиме пристрої до Lollipop не лише +21


@ Pow366, чи можете ви опублікувати основну тему додатка?
blueware

1
<style name = "AppTheme" parent = "Theme.AppCompat.Light.DarkActionBar">
Pow366

2
@ powder366, спробуйте це: <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">і це має спрацювати
blueware

19

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>

    <item name="colorControlNormal">@color/colorAccent</item>
    <item name="colorControlActivated">@color/colorAccent</item>
    <item name="colorControlHighlight">@color/colorAccent</item>

</style>


Це працює! Оскільки питання задає, чи слід вирішувати у стилі / темі, це має бути правильна відповідь.
Ніндзя

Я згоден. це має бути правильною відповіддю, оскільки це глобальне рішення
Сантакраб

Це незручно, якщо для різних елементів керування потрібні різні кольори.
Юлій

12

Одне швидке рішення вашої проблеми - шукати у yourappspackage / build / intermediates / exploded-aar / com.android.support / appcompat-v7 / res / dravable / для abc_edit_text_material.xml та скопіювати цей XML-файл у свою папку, що виводиться. Потім ви можете змінити колір 9 патч-файлів всередині цього селектора, щоб відповідати вашим уподобанням.


9

Дуже легко просто додати android:backgroundTintатрибут у свій EditText.

android:backgroundTint="@color/blue"
android:backgroundTint="#ffffff"
android:backgroundTint="@color/red"


 <EditText
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:backgroundTint="#ffffff"/>

2
backgroundTint над рівнем API 21
Ashwin H

ViewCompat.setBackgroundTintList (editText, ColorStateList.valueOf (Color.YELLOW))
Арст

1
app:backgroundTint="@color/blue"працює на всіх рівнях api .. хоча з будь-якої причини він все одно перетворюється на інший колір при
виборі

8

Ось частина вихідного коду TextInputLayoutбібліотеки підтримки підтримки ( ОНОВЛЕНО для версії 23.2.0 ), яка змінює EditTextколір нижнього рядка більш простим способом:

private void updateEditTextBackground() {
    ensureBackgroundDrawableStateWorkaround();

    final Drawable editTextBackground = mEditText.getBackground();
    if (editTextBackground == null) {
        return;
    }

    if (mErrorShown && mErrorView != null) {
        // Set a color filter of the error color
        editTextBackground.setColorFilter(
                AppCompatDrawableManager.getPorterDuffColorFilter(
                        mErrorView.getCurrentTextColor(), PorterDuff.Mode.SRC_IN));
    }
    ...
}

Здається, що все вищезазначене код стає непотрібним прямо зараз у 23.2.0, якщо ви хочете змінити колір програмно.

І якщо ви хочете підтримати всі платформи, ось мій метод:

/**
 * Set backgroundTint to {@link View} across all targeting platform level.
 * @param view the {@link View} to tint.
 * @param color color used to tint.
 */
public static void tintView(View view, int color) {
    final Drawable d = view.getBackground();
    final Drawable nd = d.getConstantState().newDrawable();
    nd.setColorFilter(AppCompatDrawableManager.getPorterDuffColorFilter(
            color, PorterDuff.Mode.SRC_IN));
    view.setBackground(nd);
}

Що таке AppCompatDravableManager? setBackground вимагає API 16.
CoolMind

8

Я теж занадто довго зациклювався на цій проблемі.

Мені потрібно було рішення, яке працювало для версій як вище, так і нижче v21.

Нарешті я виявив дуже просте, можливо, не ідеальне, але ефективне рішення: просто встановіть колір фону transparentу властивостях EditText.

<EditText
    android:background="@android:color/transparent"/>

Сподіваюся, це економить когось деякий час.


1
Це змінює весь колір фону, і ми хочемо змінити лише колір підкреслення.
шахзаїн алі

@shahzain ali Підкреслення EditText є фоном. Її немає, якщо встановити її на нуль. Ось чому backgroundTint буде працювати (але він не змінить колір при активації)
nyconing

7

Для мене я змінив і AppTheme, і значення кольорів.xml І colorControlNormal, і colorAccent допомогли мені змінити колір межі EditText. А також курсор і "|" коли всередині EditText.

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <!-- Customize your theme here. -->
    <item name="colorControlNormal">@color/yellow</item>
    <item name="colorAccent">@color/yellow</item>
</style>

Ось кольори.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="yellow">#B7EC2A</color>
</resources>

Я вийняв атрибут android: textCursorDravable до @null, який я розмістив всередині стилю editText. Коли я спробував це використовувати, кольори не змінилися.


2
Це має бути відповідь
Міна Самі

Працював як шарм. Спасибі
Däñish Shärmà

6

Ви можете встановити фон редагування прямокутника з мінусом прокладки зліва, справа і вгорі, щоб досягти цього. Ось приклад xml:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:top="-1dp"
        android:left="-1dp"
        android:right="-1dp"
        android:bottom="1dp"
        >
        <shape android:shape="rectangle">
            <stroke android:width="1dp" android:color="#6A9A3A"/>
        </shape>
    </item>
</layer-list>

Замініть фігуру селектором, якщо ви хочете надати різну ширину та колір для зосередженого редагування тексту.


5

У Activit.XML додайте код

<EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:ems="10"
        android:id="@+id/editText"
        android:hint="Informe o usuário"
        android:backgroundTint="@android:color/transparent"/>

Де BackgroundTint=colorпотрібний колір


5

Я використовую цей метод, щоб змінити колір лінії за допомогою PorterDuff, без іншого малювання.

public void changeBottomColorSearchView(int color) {
    int searchPlateId = mSearchView.getContext().getResources().getIdentifier("android:id/search_plate", null, null);
    View searchPlate = mSearchView.findViewById(searchPlateId);
    searchPlate.getBackground().setColorFilter(color, PorterDuff.Mode.SRC_IN);
}

Чи існує подібний ідентифікатор для доступу до нижнього рядка простого EditText?
Rémi P

4

Якщо ви хочете змінити нижній рядок, не використовуючи кольори додатків, використовуйте ці рядки у своїй темі:

<item name="android:editTextStyle">@android:style/Widget.EditText</item>
<item name="editTextStyle">@android:style/Widget.EditText</item>

Я не знаю іншого рішення.


4

Я розробив робоче рішення цієї проблеми після 2-х днів боротьби, нижче рішення ідеально підходить для тих, хто хоче змінити лише кілька редагуючих текстів, змінити / переключити колір через java-код, і хочуть подолати проблеми різної поведінки у версіях ОС завдяки використанню методу setColorFilter ().

    import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatDrawableManager;
import android.support.v7.widget.AppCompatEditText;
import android.util.AttributeSet;
import com.newco.cooltv.R;

public class RqubeErrorEditText extends AppCompatEditText {

  private int errorUnderlineColor;
  private boolean isErrorStateEnabled;
  private boolean mHasReconstructedEditTextBackground;

  public RqubeErrorEditText(Context context) {
    super(context);
    initColors();
  }

  public RqubeErrorEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    initColors();
  }

  public RqubeErrorEditText(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    initColors();
  }

  private void initColors() {
    errorUnderlineColor = R.color.et_error_color_rule;

  }

  public void setErrorColor() {
    ensureBackgroundDrawableStateWorkaround();
    getBackground().setColorFilter(AppCompatDrawableManager.getPorterDuffColorFilter(
        ContextCompat.getColor(getContext(), errorUnderlineColor), PorterDuff.Mode.SRC_IN));
  }

  private void ensureBackgroundDrawableStateWorkaround() {
    final Drawable bg = getBackground();
    if (bg == null) {
      return;
    }
    if (!mHasReconstructedEditTextBackground) {
      // This is gross. There is an issue in the platform which affects container Drawables
      // where the first drawable retrieved from resources will propogate any changes
      // (like color filter) to all instances from the cache. We'll try to workaround it...
      final Drawable newBg = bg.getConstantState().newDrawable();
      //if (bg instanceof DrawableContainer) {
      //  // If we have a Drawable container, we can try and set it's constant state via
      //  // reflection from the new Drawable
      //  mHasReconstructedEditTextBackground =
      //      DrawableUtils.setContainerConstantState(
      //          (DrawableContainer) bg, newBg.getConstantState());
      //}
      if (!mHasReconstructedEditTextBackground) {
        // If we reach here then we just need to set a brand new instance of the Drawable
        // as the background. This has the unfortunate side-effect of wiping out any
        // user set padding, but I'd hope that use of custom padding on an EditText
        // is limited.
        setBackgroundDrawable(newBg);
        mHasReconstructedEditTextBackground = true;
      }
    }
  }

  public boolean isErrorStateEnabled() {
    return isErrorStateEnabled;
  }

  public void setErrorState(boolean isErrorStateEnabled) {
    this.isErrorStateEnabled = isErrorStateEnabled;
    if (isErrorStateEnabled) {
      setErrorColor();
      invalidate();
    } else {
      getBackground().mutate().clearColorFilter();
      invalidate();
    }
  }
}

Використовується в xml

<com.rqube.ui.widget.RqubeErrorEditText
            android:id="@+id/f_signup_et_referral_code"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_toEndOf="@+id/referral_iv"
            android:layout_toRightOf="@+id/referral_iv"
            android:ems="10"
            android:hint="@string/lbl_referral_code"
            android:imeOptions="actionNext"
            android:inputType="textEmailAddress"
            android:textSize="@dimen/text_size_sp_16"
            android:theme="@style/EditTextStyle"/>

Додайте лінії в стилі

<style name="EditTextStyle" parent="android:Widget.EditText">
    <item name="android:textColor">@color/txt_color_change</item>
    <item name="android:textColorHint">@color/et_default_color_text</item>
    <item name="colorControlNormal">@color/et_default_color_rule</item>
    <item name="colorControlActivated">@color/et_engagged_color_rule</item>
  </style>

java-код для перемикання кольору

myRqubeEditText.setErrorState(true);
myRqubeEditText.setErrorState(false);

2

Мене абсолютно збентежила ця проблема. Я спробував усе в цій темі та в інших, але що б я не робив, я не міг змінити колір підкреслення ні на що, крім синього за замовчуванням.

Нарешті я зрозумів, що відбувається. Я (неправильно) використовував android.widget.EditTextпід час створення нового примірника (але решта моїх компонентів були з бібліотеки appcompat). Я повинен був використати android.support.v7.widget.AppCompatEditText. Я замінив new EditText(this)з , new AppCompatEditText(this) і проблема була вирішена миттєво. Виявляється, якщо ви насправді використовуєте AppCompatEditText, він буде просто враховувати тему accentColorвід вашої теми (як зазначено в декількох коментарях вище), і додаткові налаштування не потрібні.


2

Це найпростіший та найефективніший / багаторазовий / працює на всіх API-програмах.
Створіть спеціальний клас EditText на зразок:

public class EditText extends android.widget.EditText {
    public EditText(Context context) {
        super(context);
        init();
    }

    public EditText(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public EditText(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        getBackground().mutate().setColorFilter(ContextCompat.getColor(getContext(), R.color.colorAccent), PorterDuff.Mode.SRC_ATOP);
    }
}

Потім використовуйте його так:

 <company.com.app.EditText
        android:layout_width="200dp"
        android:layout_height="wrap_content"/>

2

Щоб динамічно змінити фон EditText, ви можете використовувати ColorStateList .

int[][] states = new int[][] {
    new int[] { android.R.attr.state_enabled}, // enabled
    new int[] {-android.R.attr.state_enabled}, // disabled
    new int[] {-android.R.attr.state_checked}, // unchecked
    new int[] { android.R.attr.state_pressed}  // pressed
};

int[] colors = new int[] {
    Color.BLACK,
    Color.RED,
    Color.GREEN,
    Color.BLUE
};

ColorStateList colorStateList = new ColorStateList(states, colors);

Кредити: Ця відповідь про ColorStateList є приголомшливою .


І який метод використовувати? setBackgroundTintList? Для нього потрібен API 21.
CoolMind

setSupportBackgroundTintList для старих версій API.
Анкіт Поплі

0

Додайте app:backgroundTintнижче рівень api 21. Інакше використовуйте android:backgroundTint.

Для нижнього рівня api 21.

<EditText
     android:id="@+id/edt_name"
     android:layout_width="300dp"
     android:layout_height="wrap_content"
     android:textColor="#0012ff"
     app:backgroundTint="#0012ff"/>

Для вищого, ніж рівень api 21.

<EditText
     android:id="@+id/edt_name"
     android:layout_width="300dp"
     android:layout_height="wrap_content"
     android:textColor="#0012ff"
     android:backgroundTint="#0012ff"/>

-2

Будь ласка, модифікуйте цей метод відповідно до ваших потреб. Це працювало для мене!

  private boolean validateMobilenumber() {
        if (mobilenumber.getText().toString().trim().isEmpty() || mobilenumber.getText().toString().length() < 10) {
            input_layout_mobilenumber.setErrorEnabled(true);
            input_layout_mobilenumber.setError(getString(R.string.err_msg_mobilenumber));
           // requestFocus(mobilenumber);
            return false;
        } else {
            input_layout_mobilenumber.setError(null);
            input_layout_mobilenumber.setErrorEnabled(false);
            mobilenumber.setBackground(mobilenumber.getBackground().getConstantState().newDrawable());
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.