Вопрос

Я пытаюсь создать меню, которое скользит снизу. Он начинается с представления меню, только видного в нижней части экрана, а затем нажимать на него заставляет его скользить. Я попытался использовать TranslateAnimation, но хотя пиксели движутся, участки попаданий меню находятся в том же положении, что и раньше. Поэтому я думаю, что если я смогу отрегулировать маржу меню после завершения анимации, это достигнет того, что я хочу. Тем не менее, я не могу понять, как отрегулировать маржу.

Я пытался создать LinearLayout.LayoutMargins объект, а затем установите свою прибыль и примените его к взгляду на меню (который LinearLayout), но это не работает.

Любые идеи?

Это было полезно?

Решение 2

Мое решение состояло в том, чтобы создать две линейные, один в его состоянии (установлено, чтобы уйти), а другой в состоянии меню. Затем, когда пользователь нажимает кнопку, чтобы сдвинуть меню, я вызываю TranslateAnimation показывая меню, скользит. Я положил слушателя в анимацию, которая заставляет состояние UP было видимым, а состояние вниз будет исчезнуть, когда анимация заканчивается. Я изменил это для «закрытия» действия.

Не совсем то, как я изначально себе представил, но это сработало.

Другие советы

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

private static final int BOTTOM_MARGIN_UP = -50; // My menu view is a bit too tall.
private static final int BOTTOM_MARGIN_DOWN = -120;

Затем в Oncreate ():

menuLinearLayout = (LinearLayout)findViewById(R.id.menuLinearLayout);
setBottomMargin(menuLinearLayout, BOTTOM_MARGIN_DOWN);

upAnimation = makeAnimation(BOTTOM_MARGIN_DOWN, BOTTOM_MARGIN_UP);
downAnimation = makeAnimation(BOTTOM_MARGIN_UP, BOTTOM_MARGIN_DOWN);

Button toggleMenuButton = (Button)findViewById(R.id.toggleMenuButton);
toggleMenuButton.setOnTouchListener(new View.OnTouchListener()
{
    public boolean onTouch(View view, MotionEvent motionEvent)
    {
        if (motionEvent.getAction() != MotionEvent.ACTION_DOWN) return false;
        ViewGroup.MarginLayoutParams layoutParams =
            (ViewGroup.MarginLayoutParams)menuLinearLayout.getLayoutParams();
        boolean isUp = layoutParams.bottomMargin == dipsToPixels(BOTTOM_MARGIN_UP);
        menuLinearLayout.startAnimation(isUp ? downAnimation : upAnimation);
        return true;
    }
});

А вот входит секретный соус ;-)

private TranslateAnimation makeAnimation(final int fromMargin, final int toMargin)
{
    TranslateAnimation animation = 
        new TranslateAnimation(0, 0, 0, dipsToPixels(fromMargin - toMargin));
    animation.setDuration(250);
    animation.setAnimationListener(new Animation.AnimationListener()
    {
        public void onAnimationEnd(Animation animation)
        {
            // Cancel the animation to stop the menu from popping back.
            menuLinearLayout.clearAnimation();

            // Set the new bottom margin.
            setBottomMargin(menuLinearLayout, toMargin);
        }

        public void onAnimationStart(Animation animation) {}

        public void onAnimationRepeat(Animation animation) {}
    });
    return animation;
}

Я использую две функции утилиты:

private void setBottomMargin(View view, int bottomMarginInDips)
{
    ViewGroup.MarginLayoutParams layoutParams =    
        (ViewGroup.MarginLayoutParams)view.getLayoutParams();
    layoutParams.bottomMargin = dipsToPixels(bottomMarginInDips);
    view.requestLayout();
}

private int dipsToPixels(int dips)
{
    final float scale = getResources().getDisplayMetrics().density;
    return (int)(dips * scale + 0.5f);
}

Вуаля!

Использовать ViewPropertyAnimator:

if (view.getY() != margin) {
    view.animate().y(margin).setDuration(150).start();
}

Я чувствую, что это немного меньше взлома. По сути, это делает ваш собственный аниматор. Ниже настройка только для изменения topMargin в RelativeLayout, но было бы не сложно обобщить это.

import java.util.Calendar;

import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.RelativeLayout.LayoutParams;

public class MarginAnimation extends Thread {
    final String TAG = "MarginAnimation";
    long mStartTime;
    long mTotalTime;
    Interpolator mI;

    int mStartMargin;
    int mEndMargin;

    View mV;
    Activity mA;
    public MarginAnimation(Activity a, View v, 
            int startMargin, int endMargin, int totaltime,
            Interpolator i) {
        mV = v;
        mStartMargin = startMargin;
        mEndMargin = endMargin;
        mTotalTime = totaltime;
        mI = i;
        mA = a;
    }

    @Override
    public void run() {
        mStartTime = Calendar.getInstance().getTimeInMillis();
        while(!this.isInterrupted() && 
                Calendar.getInstance().getTimeInMillis() - mStartTime < mTotalTime) {

            mA.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(MarginAnimation.this.isInterrupted())
                        return;
                    long cur_time = Calendar.getInstance().getTimeInMillis();
                    float perc_done = 1.0f*(cur_time-mStartTime)/mTotalTime;

                    final int new_margin = (int)(1.0f*(mEndMargin-mStartMargin)*mI.getInterpolation(perc_done)) + mStartMargin;
                    LayoutParams p = (LayoutParams) mV.getLayoutParams();
                    Log.v(TAG, String.format("Setting Margin to %d", new_margin));
                    p.topMargin = new_margin;
                    mV.setLayoutParams(p);                  
                }
            });

            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                return;
            }
        }
    }

}

Этот пост помог мне заставить мою анимацию работать. В моем случае у меня есть полный экран WebView. В некоторых пользовательских действиях этот веб -просмотр скользит вправо, около 70%, а новый веб -просмотр появляется слева и занимает доступное пространство. Конечный результат, новый веб-просмотр охватывает 70% (оси X) и старый веб-просмотр остальных. Решение Арне очень помогло мне, настроив маржу для старого взгляда, как только анимация будет сделана. Псевдод:

       marginParams.leftMargin = 336; //(70% of 480px)

Но я столкнулся с странным поведением, я думаю, что мой старый веб -просвист (который теперь занимает только 30% пространства), переформатировал свое содержание, возможно, думал, что теперь он втиснут в меньшее пространство, а не ведут себя так, как будто он просто скользил к Правильно. Другими словами, как только я установил этот запас, HTML -макет изменился. Опять же, я понятия не имел, почему и мой предполагать Считается ли он, что его родительский размер окна изменился. Основываясь на этом предположении, я добавил еще одну строку кода:

      marginParams.rightMargin = -336; //(same amount, but negative margin!)

И это сделало свое дело, не было переформатирования содержимого HTML, и я могу общаться с обоими просмотрами параллельно.

Я публикую это как большое спасибо Арне за эту идею, а также за то, чтобы получить какие -либо вклад в поведение, которое я видел, и мои предположения для этого. Мне действительно нравится конечное решение, имеет логический смысл, но я могу ошибаться. Анкет Анкет Любые мысли и вклад были бы очень оценены. Большое спасибо.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top