59
задан 17 August 2018 в 11:34

5 ответов

Это было просто зафиксировано в материальных компонентах для lib Android, см.: https://github.com/material-components/material-components-android/pull/358

7
ответ дан 1 November 2019 в 12:50

Я основывал свое решение на FixedTextInputEditText, как упомянуто в https://github.com/android-in-china/Compatibility/issues/11#issuecomment-427560370.

Прежде всего все я создал фиксированное TextInputEditText экземпляр:

public class MeizuTextInputEditText extends TextInputEditText {
    public MeizuTextInputEditText(Context context) {
        super(context);
    }

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

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

    @Override
    public CharSequence getHint() {
        try {
            return getMeizuHintHack();
        } catch (Exception e) {
            return super.getHint();
        }
    }

    private CharSequence getMeizuHintHack() throws NoSuchFieldException, IllegalAccessException {
        Field textView = TextView.class.getDeclaredField("mHint");
        textView.setAccessible(true);
        return (CharSequence) textView.get(this);
    }
}

, Но затем я должен был бы заменить весь мой TextInputEditText использования с MeizuTextInputEditText, который не является чем-то, что можно легко сделать на большей кодовой базе. Также, когда создание будущего просматривает Вас, всегда должен рассматривать использование MeizuTextInputEditText вместо 'поврежденного'. Упущение об этом легко представило бы производственные проблемы снова.

, Таким образом, заключительная фиксация состоит из пользовательского класса представления и вместе с библиотекой ViewPump ( https://github.com/InflationX/ViewPump), мы можем легко сделать это. Столь же объясненный в документах необходимо зарегистрировать пользовательский перехватчик, который похож на этого:

public class TextInputEditTextInterceptor implements Interceptor {
    @Override
    public InflateResult intercept(Chain chain) {
        InflateRequest request = chain.request();
        View view = inflateView(request.name(), request.context(), request.attrs());

        if (view != null) {
            return InflateResult.builder()
                    .view(view)
                    .name(view.getClass().getName())
                    .context(request.context())
                    .attrs(request.attrs())
                    .build();
        } else {
            return chain.proceed(request);
        }
    }

    @Nullable
    private View inflateView(String name, Context context, AttributeSet attrs) {
        if (name.endsWith("TextInputEditText")) {
            return new MeizuTextInputEditText(context, attrs);
        }
        return null;
    }
}

И регистрация, что пользовательский перехватчик сделан так же, как в документах путем установки ViewPump на onCreate действия:

@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    ViewPump.Builder viewPumpBuilder = ViewPump.builder();
    if (isMeizuDevice()) {
        viewPumpBuilder.addInterceptor(new TextInputEditTextInterceptor());
    }
    ViewPump.init(viewPumpBuilder.build());
}

, Как Вы видите, я только расширяюсь MeizuTextInputEditText, если устройство Meizu обнаруживается. Тем путем отражение не инициировано для устройств, которым не нужно оно. Также этот метод является основным классом Действия, который я имею, от которого любое действие расширяется в моем проекте так каждое действие, которое запускается в моем проекте И где устройством является Meizu, будет иметь фиксацию автоматически!

3
ответ дан 1 November 2019 в 12:50

Я использую Kotlin и Fragments и меня просто рекурсивно устраняющий все вводы текста в onViewCreated.

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    fixTextInputEditText(view) // call this in onViewCreated
}

private fun fixTextInputEditText(view: View) {
    val manufacturer = Build.MANUFACTURER.toUpperCase(Locale.US)
    if ("MEIZU" in manufacturer) {
        val views = getAllTextInputs(view)
        views.forEach(::hackFixHintsForMeizu)
    }
}

private fun getAllTextInputs(v: View): List<TextInputEditText> {
    if (v !is ViewGroup) {
        val editTexts = mutableListOf<TextInputEditText>()
        (v as? TextInputEditText)?.let {
            editTexts += it
        }
        return editTexts
    }

    val result = mutableListOf<TextInputEditText>()
    for (i in 0 until v.childCount) {
        val child = v.getChildAt(i)
        result += getAllTextInputs(child)
    }
    return result
}

private fun hackFixHintsForMeizu(editText: TextInputEditText) {
    if (editText.hint != null) {
        editText.setHintTextColor(Color.TRANSPARENT)
        editText.hint = editText.hint
    }
}
1
ответ дан 1 November 2019 в 12:50

Эта фиксация теперь включена в новый выпуск материальных компонентов здесь: https://github.com/material-components/material-components-android/releases/tag/1.1.0-alpha09

1
ответ дан 1 November 2019 в 12:50

Ни один из вариантов выше обработанного для меня без модификаций.

Мое приложение использует фрагменты, TextInputEditText, иногда используясь без TextInputLayout, обновляя до последнего AndroidX не был опцией в это время, заменение TextInputEditText было также не опцией в это время.

Моя версия (на основе тех решение и фиксация Google):

import android.os.Build
import java.util.*
import android.content.Context
import android.support.design.widget.TextInputEditText
import android.util.AttributeSet
import android.widget.TextView
import android.support.design.widget.TextInputLayout
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputConnection
import java.lang.reflect.Field
import java.lang.reflect.Method
import android.support.design.R

class MyInputEditText(context: Context?, attrs: AttributeSet?,defStyleAttr:Int) : TextInputEditText(context, attrs,defStyleAttr){

    constructor(context: Context?, attrs: AttributeSet?):this(context,attrs,R.attr.editTextStyle)
    constructor(context: Context?):this(context,null,R.attr.editTextStyle)


    private val buggyMeizu = ("meizu") in Build.MANUFACTURER.toLowerCase(Locale.US)

    private lateinit var getTextInputLayoutMethod:Method
    private lateinit var providesHintMethod:Method
    private lateinit var mHintField:Field

    init {
        if (buggyMeizu) {
            getTextInputLayoutMethod=TextInputEditText::class.java.getDeclaredMethod("getTextInputLayout")
            getTextInputLayoutMethod.isAccessible=true

            providesHintMethod=TextInputLayout::class.java.getDeclaredMethod("isProvidingHint")
            providesHintMethod.isAccessible=true

            mHintField=TextView::class.java.getDeclaredField("mHint")
            mHintField.isAccessible=true
        }
    }


    private fun getTILProvidesHint():Boolean {
        val layout=getTIL()
        if (layout!=null) {
            val result=providesHintMethod.invoke(layout) as Boolean
            return result;
        } else {
            return false
        }
    }

    private fun getTIL():TextInputLayout? = getTextInputLayoutMethod.invoke(this) as TextInputLayout?

    private fun getBaseHint():CharSequence? = mHintField.get(this) as CharSequence?

    override fun getHint(): CharSequence? {
        if (!buggyMeizu) {
            return super.getHint()
        } else {
            val layout=getTIL()
            return if (layout != null && (getTILProvidesHint()) ) 
                layout.hint
            else 
                provideHintWrapped()
        }
    }


    override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection? {
        val needHint=(outAttrs.hintText==null)
        val ic = super.onCreateInputConnection(outAttrs)
        if (buggyMeizu) {
            if (ic != null && needHint) {
                outAttrs.hintText = this.provideHintWrapped()
            }
        }
        return ic
    }

    private fun provideHintWrapped():CharSequence? {

        val hintFromLayout=getHintFromLayoutMine()
        if (hintFromLayout!=null) {
            return hintFromLayout
        } else {
            val baseHint=getBaseHint()
            if (baseHint!=null) {
                return baseHint
            } else {
                return null
            }
        }

    }
    private fun getHintFromLayoutMine(): CharSequence? {
        val layout = getTIL()
        return layout?.hint
    }

    override fun onAttachedToWindow() {

        if (buggyMeizu) {

            val baseHint=getBaseHint()

            if (getTIL() != null
                    && getTILProvidesHint()
                    && baseHint == null) {
                this.hint=""
            }
        }

        super.onAttachedToWindow()
    }
}

После этого находят и заменяют TextInputEditText с MyInputEditText во всем расположении и файлах кода.

0
ответ дан 1 November 2019 в 12:50

Другие вопросы по тегам:

Похожие вопросы: