আমি কীভাবে ভিউ.সেটভিজিবিলিটি (জিওএন) অ্যানিমেট করব


84

আমি Animationযখন Viewএটির দৃশ্যমানতা সেট হয়ে যায় তখন তার জন্য একটি তৈরি করতে চাই GONE। কেবল অসন্তুষ্ট হওয়ার পরিবর্তে View'ধস' হওয়া উচিত। আমি এটি দিয়ে চেষ্টা করেছি ScaleAnimationতবে পরে Viewধস হচ্ছে, তবে বিন্যাসটি (বা তার আগে) Animationস্টপসের (বা শুরু) পরে কেবল তার স্থানটির আকার পরিবর্তন করবে ।

আমি কীভাবে এটি তৈরি করতে পারি Animationযাতে, অ্যানিমেট করার সময়, নীচের Viewগুলি ফাঁকা জায়গা না রেখে সরাসরি কন্টেন্টের নীচে থেকে যায়?


অ্যান্ডি এখানে যেমন আমার প্রসারিত অ্যানিমেশন উপস্থাপন করেছে তেমন কৌশলটি ব্যবহার করেছি: udinic.wordpress.com/2011/09/03/expanding-listview-items আমি স্কেল অ্যানিমেশনটি ব্যবহার করি নি, আমি একটি নতুন অ্যানিমেশন তৈরি করেছি ক্লাস যে জন্য।
উদিনিক

আমি এটি করার চেষ্টা করার সময় এটি খুব দরকারী ছিল। আপনাকে ধন্যবাদ
atraudes

দুর্দান্ত উদিনিক .. সত্যিই আমার সমস্যার সমাধান হয়েছে .. :) ধন্যবাদ
ইউসুফ কুরেশি

দুর্দান্ত, আমার সমস্যার সাথে খাপ খাইয়ে নেওয়া দরকার তবে শেষ পর্যন্ত এটি কার্যকর হয়। আমার জন্য এই উত্তরটি অন্য উত্তরের চেয়ে ভাল ছিল।
ডেরজু

উত্তর:


51

এটিআইপি-র মাধ্যমে করার সহজ উপায় বলে মনে হয় না, কারণ অ্যানিমেশনটি কেবলমাত্র আসলের আকারের পরিবর্তে দর্শনের রেন্ডারিং ম্যাট্রিক্সকে পরিবর্তন করে। তবে ভিউ আরও ছোট হচ্ছে এই ভেবে আমরা লিনিয়ারলআউটকে বোকা বানাতে নেতিবাচক মার্জিন সেট করতে পারি।

সুতরাং আমি স্কেলএনিমেশনের উপর ভিত্তি করে আপনার নিজস্ব অ্যানিমেশন ক্লাস তৈরি করার এবং নতুন মার্জিন সেট করতে এবং লেআউটটি আপডেট করার জন্য "অ্যাপ্লিকেশন ট্রান্সফর্মেশন" পদ্ধতিটি ওভাররাইড করার পরামর্শ দিচ্ছি। এটার মত...

public class Q2634073 extends Activity implements OnClickListener {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.q2634073);
        findViewById(R.id.item1).setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        view.startAnimation(new MyScaler(1.0f, 1.0f, 1.0f, 0.0f, 500, view, true));
    }

    public class MyScaler extends ScaleAnimation {

        private View mView;

        private LayoutParams mLayoutParams;

        private int mMarginBottomFromY, mMarginBottomToY;

        private boolean mVanishAfter = false;

        public MyScaler(float fromX, float toX, float fromY, float toY, int duration, View view,
                boolean vanishAfter) {
            super(fromX, toX, fromY, toY);
            setDuration(duration);
            mView = view;
            mVanishAfter = vanishAfter;
            mLayoutParams = (LayoutParams) view.getLayoutParams();
            int height = mView.getHeight();
            mMarginBottomFromY = (int) (height * fromY) + mLayoutParams.bottomMargin - height;
            mMarginBottomToY = (int) (0 - ((height * toY) + mLayoutParams.bottomMargin)) - height;
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);
            if (interpolatedTime < 1.0f) {
                int newMarginBottom = mMarginBottomFromY
                        + (int) ((mMarginBottomToY - mMarginBottomFromY) * interpolatedTime);
                mLayoutParams.setMargins(mLayoutParams.leftMargin, mLayoutParams.topMargin,
                    mLayoutParams.rightMargin, newMarginBottom);
                mView.getParent().requestLayout();
            } else if (mVanishAfter) {
                mView.setVisibility(View.GONE);
            }
        }

    }

}

সাধারণ ক্যাভিয়েট প্রযোজ্য: যেহেতু আমরা একটি সুরক্ষিত পদ্ধতি (প্রয়োগ ট্রান্সফর্মেশন) ওভাররাইড করছি, এটি Android এর ভবিষ্যতের সংস্করণগুলিতে কাজ করার গ্যারান্টিযুক্ত নয়।


4
আমি কেন এটা ভাবিনি ?! ধন্যবাদ. এছাড়াও আমি এইটি পাই না: "সাধারণ ক্যাভ্যাটটি প্রযোজ্য: কারণ আমরা একটি সুরক্ষিত পদ্ধতি (প্রয়োগ ট্রান্সফর্মেশন) ওভাররাইড করছি, এটি Android এর ভবিষ্যতের সংস্করণগুলিতে কাজ করার গ্যারান্টিযুক্ত নয়" " - সুরক্ষিত ফাংশনগুলি এপিআই সংস্করণগুলির মধ্যে কেন পার্থক্য করবে? এগুলি লুকানো নেই এবং সুরক্ষিত প্রয়োগ করা হয়েছে যাতে আপনি সেগুলি ওভাররাইড করতে পারেন (অন্যথায় তারা প্যাকেজটি বাদ দেওয়া হবে)।
মিঃস্বনফ্লেক

আপনি সম্ভবত সুরক্ষিত পদ্ধতি সম্পর্কে সঠিক। আমি একটি এপিআইতে তাদের অ্যাক্সেস সম্পর্কে অতিরিক্ত সতর্ক হতে চাই।
অ্যান্ডি

4
এটি আমার জন্য দুর্দান্ত কাজ করেছে, "সঙ্কুচিত" কাজ করতে (ওয়াই = 0.0f থেকে, টুওয়াই = 1.0f) বাদে, আমাকে গণনায় 0 - থাকা অপসারণ করতে হয়েছিল marginBottomToY
dmon

4
আমি জেনেরিক টাইপটি MarginLayoutParamsনির্দিষ্ট LayoutParamধরণের castালাইয়ের পরিবর্তে ব্যবহার করার পরামর্শ দেব ।
পল ল্যামার্টসমা

4
ধরুন আমাকে টগল অ্যানিমেশন করতে হবে, তবে বিপরীতে কীভাবে এটি করা যায়। আপনার পরামর্শ দিন.
उमेश

99

ভিউটি যদি কোনও লেআউটে না রাখে এবং android:animateLayoutChanges="true"সেই বিন্যাসের জন্য সেট করুন ।


4
ন্যূনতম এপিআই প্রয়োজনীয় 11 বা তারও বেশি! নিম্ন সংস্করণের জন্য এই পদ্ধতিটি ব্যবহার করতে পারবেন না।
নাগরাজ আলাগুসুদারাম

4
এটি সর্বাধিক আন্ডাররেটেড লেআউট বৈশিষ্ট্য ... ধন্যবাদ!
আন্দ্রেস সান্তিয়াগো 21

7

আমি এখানে অ্যান্ডির মতো একই কৌশলটি ব্যবহার করেছি। আমি তার জন্য আমার নিজের অ্যানিমেশন ক্লাসটি লিখেছি, যা মার্জিনের মান অ্যানিমেট করে, আইটেমটির প্রভাব অদৃশ্য হয়ে যায় / উপস্থিত হয়। দেখে মনে হচ্ছে:

public class ExpandAnimation extends Animation {

// Initializations...

@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    super.applyTransformation(interpolatedTime, t);

    if (interpolatedTime < 1.0f) {

        // Calculating the new bottom margin, and setting it
        mViewLayoutParams.bottomMargin = mMarginStart
                + (int) ((mMarginEnd - mMarginStart) * interpolatedTime);

        // Invalidating the layout, making us seeing the changes we made
        mAnimatedView.requestLayout();
    }
}
}

আমার একটি সম্পূর্ণ উদাহরণ রয়েছে যা আমার ব্লগ পোস্টে http://udinic.wordpress.com/2011/09/03/expanding-listview-items/ এ কাজ করে


2

আমি এখানে অ্যান্ডির মতো একই কৌশলটি ব্যবহার করেছি এবং এটি পরিমার্জন করেছি যাতে এটি বিস্কুট ছাড়াই প্রসারণ এবং ধসে পড়ার জন্য এবং এখানে বর্ণিত একটি প্রযুক্তি ব্যবহার করেও ব্যবহার করা যায়: https://stackoverflow.com/a/11426510/1317564

import android.view.View;
import android.view.ViewTreeObserver;
import android.view.animation.ScaleAnimation;
import android.view.animation.Transformation;
import android.widget.LinearLayout;

class LinearLayoutVerticalScaleAnimation extends ScaleAnimation {
    private final LinearLayout view;
    private final LinearLayout.LayoutParams layoutParams;

    private final float beginY;
    private final float endY;
    private final int originalBottomMargin;

    private int expandedHeight;
    private boolean marginsInitialized = false;
    private int marginBottomBegin;
    private int marginBottomEnd;

    private ViewTreeObserver.OnPreDrawListener preDrawListener;

    LinearLayoutVerticalScaleAnimation(float beginY, float endY,
            LinearLayout linearLayout) {
        super(1f, 1f, beginY, endY);

        this.view = linearLayout;
        this.layoutParams = (LinearLayout.LayoutParams) linearLayout.getLayoutParams();

        this.beginY = beginY;
        this.endY = endY;
        this.originalBottomMargin = layoutParams.bottomMargin;

        if (view.getHeight() != 0) {
            expandedHeight = view.getHeight();
            initializeMargins();
        }
    }

    private void initializeMargins() {
        final int beginHeight = (int) (expandedHeight * beginY);
        final int endHeight = (int) (expandedHeight * endY);

        marginBottomBegin = beginHeight + originalBottomMargin - expandedHeight;
        marginBottomEnd = endHeight + originalBottomMargin - expandedHeight;
        marginsInitialized = true;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);     

        if (!marginsInitialized && preDrawListener == null) {                       
            // To avoid glitches, don't draw until we've initialized everything.
            preDrawListener = new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {                    
                    if (view.getHeight() != 0) {
                        expandedHeight = view.getHeight();
                        initializeMargins();
                        adjustViewBounds(0f);
                        view.getViewTreeObserver().removeOnPreDrawListener(this);                               
                    }

                    return false;
                }
            };

            view.getViewTreeObserver().addOnPreDrawListener(preDrawListener);                   
        }

        if (interpolatedTime < 1.0f && view.getVisibility() != View.VISIBLE) {          
            view.setVisibility(View.VISIBLE);           
        }

        if (marginsInitialized) {           
            if (interpolatedTime < 1.0f) {
                adjustViewBounds(interpolatedTime);
            } else if (endY <= 0f && view.getVisibility() != View.GONE) {               
                view.setVisibility(View.GONE);
            }
        }
    }

    private void adjustViewBounds(float interpolatedTime) {
        layoutParams.bottomMargin = 
                marginBottomBegin + (int) ((marginBottomEnd - marginBottomBegin) * interpolatedTime);       

        view.getParent().requestLayout();
    }
}

এটি ব্যবহার করে কী কোনও বিদ্যমান লিনিয়ারলআউটকে প্রথমে ভেঙে ফেলা এবং তার পরে আবার একই লিনিয়ারলাউটটি প্রসারিত করা সম্ভব? যখন আমি এটি করার চেষ্টা করি তখন এটি কেবল ধসে পড়ে এবং আবার প্রসারিত হবে না (সম্ভবত দর্শনের উচ্চতা এখন 0 বা এর মতো কিছু হয়)।
আহাহর

আমি দেখতে পেয়েছি যে লিনিয়ার লেআউটে একাধিক ভিউ থাকায় এটি আরও নির্ভরযোগ্যভাবে কাজ করে। যদি এটিতে কেবল একটি ভিউ থাকে তবে এটি সর্বদা প্রসারিত হবে না।
ওপেনজিএল ইএস শিখুন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.