Вариант из библиотеки android-autofittextview: масштабирование ведет к странному поведению

Итак, чтобы точно сказать вам, что происходит, позвольте мне сначала объяснить контекст.

Я следовал этому руководству: https://viksaaskool.wordpress.com/2014/11/16/using-auto-resize-to-fit-edittext-in-android/

который в основном представляет собой простой autoresizeEditText, основанный на библиотеке autoFitTextView ( https://github.com/grantland/android-autofittextview ).

Чего я хочу добиться: когда я нажимаю кнопку, весь макет увеличивается, и я имитирую щелчок на editText, чтобы пользователь мог ввести текст.

То, чего я достиг до сих пор: ну, почти все, за исключением того, что это работает только на некоторых устройствах, а не на других.

К вашему сведению, вот две анимированные картинки, которые иллюстрируют то, о чем я говорю:

ХОРОШЕЕ ПОВЕДЕНИЕ (Nexus 5 API 21): http://giphy.com/gifs/xTiTnH1hyuJzjnDl6w

ПЛОХОЕ ПОВЕДЕНИЕ (Nexus 6 API 22): http://giphy.com/gifs/3-1-2-3o85xDB4Wyve1jh0XK

Как вы можете видеть, масштабирование в порядке, а затем ввод текста в порядке, пока в некоторых случаях текст не появится после того, что кажется правой стороной немасштабированного editText. Но как только нужно изменить размер текста (или уменьшить масштаб), все возвращается на круги своя.

Итак, мой вопрос: у кого-нибудь есть идея, что может сделать это странное поведение? Кто-нибудь сталкивался с этой проблемой либо в autoFitTextView, либо в его расширении?

Заранее спасибо!

PS: я мог бы опубликовать некоторый код, но поскольку обе библиотеки + ссылки предоставлены и довольно длинны, я предпочитаю не публиковать их здесь, поскольку они в основном одинаковы. Что я могу предоставить, так это вызовы, сделанные для анимации представлений и отображения клавиатуры (даже если я не уверен, что это связано):

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    mView = inflater.inflate(R.layout.add_message_layout, null);
    mMessageEditText = (AutoResizeEditText) mView.findViewById(R.id.messageEditText);
    mMessageEditText.setEnabled(false);
    mMessageEditText.setEnableSizeCache(false);
    mMessageEditText.setMovementMethod(null);
    mMessageEditText.setInterface(this);
    mMessageEditText.setMinTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, MIN_SP_TEXT_SIZE, getResources().getDisplayMetrics()));
    mMessageEditText.setMaxHeight((int) DisplayUtils.convertDpToPixel(getActivity().getApplicationContext(), mMessageEditText.getMeasuredHeight()));
    mMessageEditText.setLines(MAX_LINES_COUNT);
    mMessageEditText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            mLastMessage = mMessageEditText.getText().toString();
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            if (mMessageEditText.getLineCount() > MAX_LINES_COUNT) {
                //If user tries to type more text than expected !
                mMessageEditText.setText(mLastMessage);
                mMessageEditText.setSelection(mLastMessage.length());
                Toast.makeText(getActivity().getApplicationContext(), "Limit Reached", Toast.LENGTH_SHORT).show();
            }
        }

        @Override
        public void afterTextChanged(Editable s) {
            mLastMessage = mMessageEditText.getText().toString();
            mMessageEditText.invalidate();
        }
    });

    mAddMessageButton = (RelativeLayout) mView.findViewById(R.id.rlAddMessage);
    mAddMessageButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            setupAnimations();
            animZoomIn();
        }
    });

    mCardLayout = (LinearLayout) mView.findViewById(R.id.rearMainCardLayout);
    return (mView);
}

private void setupAnimations() {
    mPivotX = mMessageEditText.getPivotX() / mCardLayout.getMeasuredHeight();
    mPivotY = mMessageEditText.getPivotY() / mCardLayout.getMeasuredWidth();

    mZoomIn = new ScaleAnimation(1.0f, 1.3f, 1.0f, 1.3f, mPivotX, mPivotY);
    mZoomIn.setDuration(1000);
    mZoomIn.setFillAfter(true);

    mSlideUp = new TranslateAnimation(0.0f, 100.0f, 0.0f, -100.0f);
    mSlideUp.setDuration(1000);
    mSlideUp.setFillAfter(true);

    mEnterAnimation = new AnimationSet(true);
    mEnterAnimation.setInterpolator(new LinearInterpolator());
    mEnterAnimation.addAnimation(mZoomIn);
    mEnterAnimation.addAnimation(mSlideUp);
    mEnterAnimation.setFillAfter(true);
    mEnterAnimation.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {

            mBeginX = mMessageEditText.getLeft();
            mBeginY = mMessageEditText.getTop();
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            mMessageEditText.setPressed(true);      //EditText will get highlighted
            mMessageEditText.setFocusable(true);
            mMessageEditText.setFocusableInTouchMode(true);
            mMessageEditText.setTextIsSelectable(true);
            mMessageEditText.requestFocus();
            mMessageEditText.invalidate();

            mMessageEditText.setEnabled(true);
            showKeyboard(getActivity().getApplicationContext(), mMessageEditText);
        }

        @Override
        public void onAnimationRepeat(Animation animation) {}
    });

    mZoomOut = new ScaleAnimation(1.3f, 1.0f, 1.3f, 1.0f, mPivotX, mPivotY);
    mZoomOut.setDuration(1000);
    mZoomOut.setFillAfter(true);

    mSlideDown = new TranslateAnimation(100.0f, 0.0f, -100.0f, 0.0f);
    mSlideDown.setDuration(1000);
    mSlideDown.setFillAfter(true);

    mExitAnimation = new AnimationSet(true);
    mExitAnimation.setInterpolator(new LinearInterpolator());
    mExitAnimation.addAnimation(mZoomOut);
    mExitAnimation.addAnimation(mSlideDown);
    mExitAnimation.setFillAfter(true);
    mExitAnimation.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {}

        @Override
        public void onAnimationEnd(Animation animation) {
            mMessageEditText.invalidate();
        }

        @Override
        public void onAnimationRepeat(Animation animation) {}
    });
}

private void animZoomIn() {
    mCardLayout.startAnimation(mEnterAnimation);
}

private void animZoomOut() {
    mCardLayout.startAnimation(mExitAnimation);
}

private static void closeKeyboard(Context c, IBinder windowToken) {
    InputMethodManager manager = (InputMethodManager)c.getSystemService(Context.INPUT_METHOD_SERVICE);
    manager.hideSoftInputFromWindow(windowToken, 0);
}

private static void showKeyboard(Context c, EditText text) {
    InputMethodManager manager = (InputMethodManager) c.getSystemService(Context.INPUT_METHOD_SERVICE);
    manager.showSoftInput(text, InputMethodManager.SHOW_IMPLICIT);
}

person NSimon    schedule 31.03.2015    source источник
comment
Я не уверен, что вижу в анимации (может быть, недостаточно гладкой?). Но пробовали ли вы другие способы анимации? Тот, который вы использовали, относится к старому API Android (до Honeycomb). Попробуйте использовать view.animate().... или даже попробуйте анимировать сам макет, если это необходимо (пример здесь: stackoverflow.com/a /19616416/878126 ). Причина, по которой я предлагаю это, заключается в том, что старый API на самом деле не меняет размер и/или положение представлений, а только то, как они выглядят.   -  person android developer    schedule 01.04.2015
comment
Это подход, о котором я не знал @androiddeveloper, я обязательно протестирую его завтра утром, и, надеюсь, это решит эту проблему. Казалось бы, по какой-то причине он фактически меняет размер/положение представлений на некоторых устройствах/API, но не на других. Я буду держать вас в курсе как можно скорее, но спасибо за совет!   -  person NSimon    schedule 01.04.2015
comment
Использование старого API никогда не должно изменять размер/положение представлений. Вы можете сделать POC, чтобы увидеть это поведение: сделайте кнопку, которая при нажатии будет показывать тост. установите анимацию, которая перемещает его из одного места в другое, и пусть оно остается там. попробуй нажать кнопку. Кнопка не может быть нажата в новой позиции, потому что на самом деле ее там нет. щелчок по исходному местоположению вызовет событие щелчка. То же самое произойдет, если вы попытаетесь изменить его размер, используя старую анимацию API.   -  person android developer    schedule 01.04.2015
comment
@androiddeveloper Ваше решение работает как шарм, я перешел на новую систему анимации с помощью animate(), и у меня больше нет проблем на любом устройстве! Не могли бы вы написать краткое изложение этого в качестве ответа, чтобы я мог его принять? Кстати, спасибо!   -  person NSimon    schedule 01.04.2015


Ответы (1)


Итак, спасибо разработчику @android, который указал на проблему, это было вызвано старой версией анимации, которую я использовал.

Итак, заменив

mZoomOut = new ScaleAnimation(1.3f, 1.0f, 1.3f, 1.0f, mPivotX, mPivotY);
mZoomOut.setDuration(1000);
mZoomOut.setFillAfter(true);

mSlideDown = new TranslateAnimation(100.0f, 0.0f, -100.0f, 0.0f);
mSlideDown.setDuration(1000);
mSlideDown.setFillAfter(true);

mExitAnimation = new AnimationSet(true);
mExitAnimation.setInterpolator(new LinearInterpolator());
mExitAnimation.addAnimation(mZoomOut);
mExitAnimation.addAnimation(mSlideDown);
mExitAnimation.setFillAfter(true);
mExitAnimation.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {}

    @Override
    public void onAnimationEnd(Animation animation) {
        mMessageEditText.invalidate();
    }

    @Override
    public void onAnimationRepeat(Animation animation) {}
});
mCardLayout.startAnimation(mEnterAnimation);

по новым:

mCardLayout.animate().translationX(0.0f).translationY(0.0f).scaleX(1.0f).scaleY(1.0f).setDuration(1000).withEndAction(new Runnable() {
                @Override
                public void run() {
                    mMessageEditText.invalidate();
                    mIsViewZoomed = false;
                }
            });

все решил.

person NSimon    schedule 02.04.2015
comment
Счастлив, что ты сделал это. Обратите внимание, что это будет работать только начиная с определенного API. Будет довольно сложно заставить его работать на старых версиях Android (например, API 10 и ниже). - person android developer; 12.04.2015