Android - تحريك TopMargin / bottomhargin / ETC في Linearlayout أو relativelayout

StackOverflow https://stackoverflow.com/questions/2239442

سؤال

أحاول إنشاء قائمة تنزلق من الأسفل. يبدأ عرض القائمة في القائمة مرئية فقط في أسفل الشاشة، ثم النقر فوقه يؤدي إلى تنزلقه. حاولت استخدام TranslateAnimation, ، ولكن على الرغم من أن تحرك البكسل، فإن المناطق الناجمة في القائمة في نفس الموقف كما كان من قبل. لذلك أعتقد أنه إذا استطعت ضبط هوامش القائمة بعد اكتمال الرسوم المتحركة، فسوف ينجز هذا ما أريد. ومع ذلك، لا أستطيع معرفة كيفية ضبط الهوامش.

لقد حاولت إنشاء LinearLayout.LayoutMargins كائن ثم قم بتعيين هوامشه وتطبيقه على عرض القائمة (وهو LinearLayout)، ولكن هذا لا يعمل.

أيه أفكار؟

هل كانت مفيدة؟

المحلول 2

كان الحل الخاص بي هو إنشاء اثنين من LINEARLAYOUTS، واحدة في حالة تشغيلها (تم تعيينها للاختهم) والآخر في حالة أسفل القائمة. ثم عند النقر فوق المستخدم على الزر لإحضار القائمة لأعلى، أسميه TranslateAnimation عرض الشريحة القائمة. لقد وضعت مستمعا على الرسوم المتحركة التي تسبب أن تكون الحالة المثيرة لمرئتها وذهبت الحالة الهبوطية عند انتهاء الرسوم المتحركة. لقد عكس هذا الإجراء "إغلاق".

ليس بالضبط الطريقة التي تخيلها في الأصل القيام بذلك، لكنها عملت.

نصائح أخرى

ما يلي عملت بالنسبة لي. أولا تحديد الهوامش السفلية (في الانخفاضات) للقائمة التي تواجهها (مرئية تماما) أو لأسفل (معظمها مخفي).

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

ثم، في oncom ():

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 ملء الشاشة. في بعض الإجراءات المستخدم، ينزلق WebView هذا إلى اليمين، حوالي 70٪ ويظهر WebView جديد من اليسار ويأخذ المساحة المتوفرة. النتيجة النهائية، ويغطي WebView جديد 70٪ (X-Axis) و WebView القديم الباقي. ساعدني حل آرني بشكل كبير، مما وضع الهامش على الرأي القديم بمجرد الانتهاء من الرسوم المتحركة. كود مزيف:

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

لكنني واجهت سلوك غريب، أعتقد أن بلدي WebView القديم (الذي يحتل الآن فضاء 30٪ فقط)، تم إعادة تهيئة محتوياته، قد يفكر في أن يتم تقلصها الآن إلى مساحة أصغر، بدلا من أن تتصرف كما لو انزلقت الصحيح. بمعنى آخر، بمجرد تعيين هذا الهامش، تم تغيير تخطيط HTML ل WebView. مرة أخرى، لم يكن لدي أي فكرة لماذا ولدي خمن هل يعتقد أنه تغير حجم النافذة الأصل. بناء على هذا الافتراض، أضفت خطا آخر من التعليمات البرمجية:

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

وهذا فعلت الخدعة، لا إعادة تهيئة محتويات HTML ويمكنني التفاعل مع كلا WebViews بالتوازي.

أقوم بنشر هذا ككبير شكرا لك على أرني للفكرة وأيضا للحصول على أي مدخلات للسلوك الذي رأيته وافتراضاتي لذلك. أنا في الواقع أحب الحل النهائي، مما يجعل الشعور المنطقي، لكن قد أكون مخطئا. وبعد وبعد أي أفكار ومدخلات موضع تقدير كبير. شكرا جزيلا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top