অ্যান্ড্রয়েড: অ্যানিমেশন প্রসারিত / ধস


449

ধরা যাক আমার সাথে একটি উল্লম্ব রৈখিক লেআউট রয়েছে:

[v1]
[v2]

ডিফল্টরূপে v1 এর দৃশ্যমান = GONE রয়েছে। আমি একটি প্রসারিত অ্যানিমেশন সহ ভি 1 প্রদর্শন করতে এবং একই সাথে ভি 2 টিপতে চাই।

আমি এরকম কিছু চেষ্টা করেছি:

Animation a = new Animation()
{
    int initialHeight;

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        final int newHeight = (int)(initialHeight * interpolatedTime);
        v.getLayoutParams().height = newHeight;
        v.requestLayout();
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
        initialHeight = height;
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
};

তবে এই সমাধানটি সহ অ্যানিমেশন শুরু হওয়ার সাথে সাথে আমার একটি ঝলক দেখা যায়। আমি মনে করি এটি অ্যানিমেশন প্রয়োগ করার আগে পূর্ণ আকারের ভি 1 প্রদর্শন করার কারণে ঘটেছিল।

জাভাস্ক্রিপ্ট সহ, এটি jQuery এর এক লাইন! অ্যান্ড্রয়েড দিয়ে এটি করার কোনও সহজ উপায়?

উত্তর:


734

আমি দেখতে পাচ্ছি যে এই প্রশ্নটি জনপ্রিয় হয়ে উঠেছে তাই আমি আমার আসল সমাধানটি পোস্ট করি। মূল সুবিধাটি হ'ল অ্যানিমেশনটি প্রয়োগ করতে আপনাকে প্রসারিত উচ্চতা জানতে হবে না এবং একবার ভিউটি প্রসারিত হয়ে গেলে বিষয়বস্তু পরিবর্তন হলে উচ্চতাটি মানিয়ে যায়। এটি আমার জন্য খুব ভালো কাজ করছে।

public static void expand(final View v) {
    int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) v.getParent()).getWidth(), View.MeasureSpec.EXACTLY);
    int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    v.measure(matchParentMeasureSpec, wrapContentMeasureSpec);
    final int targetHeight = v.getMeasuredHeight();

    // Older versions of android (pre API 21) cancel animations for views with a height of 0.
    v.getLayoutParams().height = 1;
    v.setVisibility(View.VISIBLE);
    Animation a = new Animation()
    {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            v.getLayoutParams().height = interpolatedTime == 1
                    ? LayoutParams.WRAP_CONTENT
                    : (int)(targetHeight * interpolatedTime);
            v.requestLayout();
        }

        @Override
        public boolean willChangeBounds() {
            return true;
        }
    };

    // Expansion speed of 1dp/ms
    a.setDuration((int)(targetHeight / v.getContext().getResources().getDisplayMetrics().density));
    v.startAnimation(a);
}

public static void collapse(final View v) {
    final int initialHeight = v.getMeasuredHeight();

    Animation a = new Animation()
    {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            if(interpolatedTime == 1){
                v.setVisibility(View.GONE);
            }else{
                v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
                v.requestLayout();
            }
        }

        @Override
        public boolean willChangeBounds() {
            return true;
        }
    };

    // Collapse speed of 1dp/ms
    a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
    v.startAnimation(a);
}

মন্তব্যগুলিতে @ জেফারসন দ্বারা উল্লিখিত হিসাবে, আপনি অ্যানিমেশনের সময়কাল (এবং তাই গতি) পরিবর্তন করে একটি মসৃণ অ্যানিমেশন অর্জন করতে পারেন। বর্তমানে এটি 1 ডিপি / এমএস বেগে সেট করা হয়েছে


13
v.measure (MeasureSpec.makeMeasureSpec (LayoutParams.MATCH_PARENT, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec (লেআউটপ্যারামস। কিছু ক্ষেত্রে (আমার - লিস্টভিউ) এই অমিলটি ভুল টার্গেটহাইট মানের দিকে নিয়ে যায়
জনি দো

12
@ টম এস্তেরেজ এটি কার্যকরভাবে কাজ করে তবে খুব সহজেই হয় না। এটিকে সুচারুভাবে তৈরি করার জন্য কোনও অতিরিক্ত কাজ আছে?
acntwww

9
@acntwww আপনি 4 এর মতো কিছু কারণের দ্বারা সময়কালকে আরও সহজেই অ্যানিমেশন পেতে পারেনa.setDuration(((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density)) * 4)
জেফারসন হেনরিক সি। সোয়ারস

10
@ অলিও, আমদানি করুন অ্যান্ড্রয়েড.ভিউ.অ্যানিমেশন. ট্রান্সফর্মেশন;
জোমিয়া

5
দুর্দান্ত কাজ! আমি একটি নির্দিষ্ট ডিপি উপাদানকে প্রসারিত করতে চেয়ে আমার পরিমাপ করা উচ্চতা নিয়ে সমস্যা ছিল, তাই আমি পরিমাপটি পরিবর্তিত করেছি v.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));এবং v.getLayoutParams().height = interpolatedTime == 1 ? targetHeight : (int)(targetHeight * interpolatedTime);এটি আমার পক্ষে কাজ করেছে!
ভিসিস্লিকিনস

140

আমি যা বিশ্বাস করি এটি করার চেষ্টা করছিলাম যা একটি খুব অনুরূপ অ্যানিমেশন এবং একটি মার্জিত সমাধান খুঁজে পেয়েছি। এই কোডটি ধরে নিয়েছে যে আপনি সর্বদা 0-> h বা h-> 0 (h সর্বাধিক উচ্চতা হয়ে) থেকে যান। তিনটি কনস্ট্রাক্টর প্যারামিটার হ'ল ভিউ = অ্যানিমেটেড হওয়ার জন্য (আমার ক্ষেত্রে, একটি ওয়েবভিউ), টার্গেটহাইট = দর্শনটির সর্বাধিক উচ্চতা এবং নীচে = একটি বুলিয়ান যা দিকটি নির্দিষ্ট করে (সত্য = প্রসারণ, মিথ্যা = ভাঙ্গা)।

public class DropDownAnim extends Animation {
    private final int targetHeight;
    private final View view;
    private final boolean down;

    public DropDownAnim(View view, int targetHeight, boolean down) {
        this.view = view;
        this.targetHeight = targetHeight;
        this.down = down;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        int newHeight;
        if (down) {
            newHeight = (int) (targetHeight * interpolatedTime);
        } else {
            newHeight = (int) (targetHeight * (1 - interpolatedTime));
        }
        view.getLayoutParams().height = newHeight;
        view.requestLayout();
    }

    @Override
    public void initialize(int width, int height, int parentWidth,
            int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
}

5
কোডটিতে একটি টাইপ রয়েছে: "ইনিটালাইজ" পদ্ধতির নামটি "আরম্ভ" করা উচিত বা এটি কল হবে না। ;) আমি ভবিষ্যতে @ ওভাররাইড ব্যবহার করার পরামর্শ দিচ্ছি যাতে এই ধরণের টাইপো সংকলকটি ধরা পড়ে।
লর্ড লালিবার্তে

4
আমি নিম্নলিখিতটি করছি: "ড্রপডাউনআনিম এনিম = নতুন ড্রপডাউনআনিম (গ্রিড_টিটুলস_আচুয়াল, GRID_HEIGHT, সত্য); anim.setD अवधि (500); anim.start ();" কিন্তু এটি কাজ করে না আমি অ্যাপ্লিকেশন ট্রান্সফর্মেশনটিতে কিছু ব্রেকপয়েন্ট রেখেছি কিন্তু সেগুলি কখনই পৌঁছাচ্ছে না
পাওলো সিজার

5
ওপস, এটি কাজ করে ফেলেছে, দেখুন ভিউ স্টার্টএনিমেশন (ক) ... পারফরম্যান্স খুব ভাল নয়, তবে এটি কাজ করে :)
পাওলো সিজার

3
@ আইমস্টালকার সেই পরিস্থিতিতে আপনার সম্ভবত দুটি ভেরিয়েবলের সাথে সূচনা করা উচিত, শুরু হাইট এবং শেষ হাইট। তারপরে পরিবর্তন করুন: যদি (নিচে) H নতুনহাইট = (ইনট) (((সমাপ্তি হাইট-স্টার্টিংহাইট) * ইন্টারপোল্টটাইম) + স্টার্টহাইট)); } অন্য {নতুনহাইট = (ইনট) (((এন্ডিংহাইট-স্টার্টিংহাইট)) ((1 - ইন্টারপোল্টটাইম)) + স্টার্টহাইট); }
শেঠ নেলসন

3
@ আমি মনে করি যে নিউহাইটটি কেবল (ইনট) ((টার্গেটহাইট -স্টার্টিংহাইট) * ইন্টারপোল্টটাইম) + স্টার্টহাইট) হতে পারে, দিকনির্দেশটি যতই গুরুত্বপূর্ণ নয়, যতক্ষণ না সূচনা হাইট আরম্ভকরণে সেট করা থাকে ()।
জর্গোস কাইলাফাস

138

আমি আজ একই সমস্যায় হোঁচট খেয়েছি এবং আমি অনুমান করি যে এই প্রশ্নের আসল সমাধান এটি

<LinearLayout android:id="@+id/container"
android:animateLayoutChanges="true"
...
 />

শিফটে জড়িত সমস্ত শীর্ষ লেআউটের জন্য আপনাকে এই সম্পত্তিটি সেট করতে হবে। আপনি যদি এখন একটি লেআউটের দৃশ্যমানতা GONE এ সেট করেন তবে অদৃশ্য হয়ে যাওয়া একটি এটি ছেড়ে দিচ্ছে বলে অন্যটি স্থানটি গ্রহণ করবে। এখানে একটি ডিফল্ট অ্যানিমেশন থাকবে যা একরকম "ফিডিং আউট", তবে আমি মনে করি আপনি এটি পরিবর্তন করতে পারেন - তবে শেষেরটি আমি আপাতত পরীক্ষা করি নি।


2
+1, এখন আমি গতি অনুসন্ধান করছি: অ্যানিমেট লেআউটচেঞ্জের সময়কাল
তুষার পান্ডে

9
অ্যানিমেটিং লেআউট পরিবর্তনগুলি: ডেভেলপার.অ্যান্ড্রয়েড
ট্রেনিং

ব্যাক বোতাম টিপে কাজ করে না। কোন পরামর্শ?
হাসান তারেক

4
এটি অ্যানিমেশন সম্প্রসারণের জন্য নিখুঁতভাবে কাজ করে, তবে পতনের জন্য প্যারেন্ট লেআউট সঙ্কুচিত হওয়ার পরে অ্যানিমেশনটি ঘটে।
shine_joseph

3
@ শাইন_জোসেফ হ্যাঁ আমি এটি একটি পুনর্ব্যবহারের ভিতরে ব্যবহার করছি এবং যখন ভেঙে ফেলা সত্যিই অদ্ভুত দেখাচ্ছে: /
আমিরজি

65

আমি @ লেনায়ান এর সমাধানটি নিয়েছিলাম যা আমার কাছে সঠিকভাবে কাজ করে না ( কারণ এটি ভেঙে যাওয়ার / / বা প্রসারণের আগে ভিউটিকে 0 উচ্চতার দৃশ্যে রূপান্তর করছিল ) এবং কিছু পরিবর্তন করেছি।

ভিউ এর আগের উচ্চতাটি গ্রহণ করে এবং এই আকারের সাথে প্রসারিত করা শুরু করে এখন এটি দুর্দান্ত কাজ করে । ভেঙে পড়া একই রকম।

আপনি কেবল নীচের কোডটি অনুলিপি এবং পেস্ট করতে পারেন:

public static void expand(final View v, int duration, int targetHeight) {

    int prevHeight  = v.getHeight();

    v.setVisibility(View.VISIBLE);
    ValueAnimator valueAnimator = ValueAnimator.ofInt(prevHeight, targetHeight);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            v.getLayoutParams().height = (int) animation.getAnimatedValue();
            v.requestLayout();
        }
    });
    valueAnimator.setInterpolator(new DecelerateInterpolator());
    valueAnimator.setDuration(duration);
    valueAnimator.start();
}

public static void collapse(final View v, int duration, int targetHeight) {
    int prevHeight  = v.getHeight();
    ValueAnimator valueAnimator = ValueAnimator.ofInt(prevHeight, targetHeight);
    valueAnimator.setInterpolator(new DecelerateInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            v.getLayoutParams().height = (int) animation.getAnimatedValue();
            v.requestLayout();
        }
    });
    valueAnimator.setInterpolator(new DecelerateInterpolator());
    valueAnimator.setDuration(duration);
    valueAnimator.start();
}

ব্যবহার:

//Expanding the View
   expand(yourView, 2000, 200);

// Collapsing the View     
   collapse(yourView, 2000, 100);

যথেষ্ট সহজ!

প্রাথমিক কোডের জন্য লেনায়ানকে ধন্যবাদ!


যদিও এটি কাজ করে, এটি বিকাশকারী সেটিংসের উপর নির্ভর করে (অ্যানিমেশন সময়কাল)। এটি অক্ষম থাকলে কোনও অ্যানিমেশন প্রদর্শিত হবে না।
কুলমাইন্ড

হ্যাঁ, তবে এটি সমস্যা হতে পারে বা নাও হতে পারে। আপনার আবেদনের উপর নির্ভর করে। উদাহরণস্বরূপ, আপনি সহজেই অ্যানিমেশনের সময়কালকে সাধারণ পরিবর্তনের সাথে প্রসারিত / ধসে পড়া আকারের সাথে আনুপাতিক করে তুলতে পারেন। স্থিরযোগ্য অ্যানিমেশন সময়কাল আপনাকে কিছুটা আরও স্বাধীনতা দেয়।
জেরাল্ডো নেট

অ্যানিমেশন কাজ না করে প্রসারণ করুন। এটি ধসের অ্যানিমেশনের মতো দেখাচ্ছে।
আহমাদুল্লাহ সৈকত

39

একটি বিকল্প হ'ল প্রসারণের জন্য নিম্নলিখিত স্কেলিং উপাদানগুলির সাথে স্কেল অ্যানিমেশন ব্যবহার করা:

ScaleAnimation anim = new ScaleAnimation(1, 1, 0, 1);

এবং ভাঙ্গার জন্য:

ScaleAnimation anim = new ScaleAnimation(1, 1, 1, 0);

অ্যানিমেশনটি কীভাবে শুরু করবেন .. View.startAnimation (anim); দেখে মনে হচ্ছে না
মহেন্দ্রন

আমি অ্যানিমেশনটি কীভাবে শুরু করব তা স্পষ্টই। অন্যান্য অ্যানিমেশনগুলি কি আপনার জন্য কাজ করে?
ক্রিস্টোফকে

1
এই পদ্ধতির সাথে গিয়েছে, একটি মোহন হিসাবে কাজ করে এবং ইতিমধ্যে বাস্তবায়িত হয়েছে যা বাস্তবায়নের প্রয়োজন হয় না।
এরজম্যান

15
এটি অ্যানিমেশন চলাকালীন তার নীচের মতামতগুলিকে চাপ দেয় না এবং এটি প্রদর্শিত হয় যেমন এটি 0 -> এইচ থেকে অ্যানিমেটেড ভিউটি প্রসারিত করছে।

5
বিটিডব্লিউ, দেখুন অ্যানিমেশনগুলি স্কেলিংয়ের জন্য দুর্দান্ত কাজ করে: oView.animate ()। স্কেলওয়াই (0) উল্লম্বভাবে পতন করতে; ওভিউ.আনিমেট ()। স্কেলওয়াই (1) খোলার জন্য (নোট করুন এটি কেবলমাত্র এসডিকে 12 এবং পরবর্তী উপলব্ধ)।

27

@ টম এস্তেরেজের উত্তর , তবে অ্যান্ড্রয়েড প্রতি সঠিকভাবে ভিউ.মিজার () ব্যবহার করার জন্য আপডেট হয়েছেমেজডহাইটটি ভুল মান দেয়!

    // http://easings.net/
    Interpolator easeInOutQuart = PathInterpolatorCompat.create(0.77f, 0f, 0.175f, 1f);

    public static Animation expand(final View view) {
        int matchParentMeasureSpec = View.MeasureSpec.makeMeasureSpec(((View) view.getParent()).getWidth(), View.MeasureSpec.EXACTLY);
        int wrapContentMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        view.measure(matchParentMeasureSpec, wrapContentMeasureSpec);
        final int targetHeight = view.getMeasuredHeight();

        // Older versions of android (pre API 21) cancel animations for views with a height of 0 so use 1 instead.
        view.getLayoutParams().height = 1;
        view.setVisibility(View.VISIBLE);

        Animation animation = new Animation() {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {

               view.getLayoutParams().height = interpolatedTime == 1
                    ? ViewGroup.LayoutParams.WRAP_CONTENT
                    : (int) (targetHeight * interpolatedTime);

            view.requestLayout();
        }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        animation.setInterpolator(easeInOutQuart);
        animation.setDuration(computeDurationFromHeight(view));
        view.startAnimation(animation);

        return animation;
    }

    public static Animation collapse(final View view) {
        final int initialHeight = view.getMeasuredHeight();

        Animation a = new Animation() {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                if (interpolatedTime == 1) {
                    view.setVisibility(View.GONE);
                } else {
                    view.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
                    view.requestLayout();
                }
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        a.setInterpolator(easeInOutQuart);

        int durationMillis = computeDurationFromHeight(view);
        a.setDuration(durationMillis);

        view.startAnimation(a);

        return a;
    }

    private static int computeDurationFromHeight(View view) {
        // 1dp/ms * multiplier
        return (int) (view.getMeasuredHeight() / view.getContext().getResources().getDisplayMetrics().density);
    }

1
অ্যাডহাইট এবং DURATION_MULTIPLIER কী?
মিডাসলফকো

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

1
দুর্দান্ত কাজ! টেক্সটভিউ ব্যবহারের সময় শেষ লাইনে কেবল একটি শব্দের সাথে একটি ছোট ব্যবধান ঘটে। এবং আপনি কী ব্যাখ্যা করতে পারেন যে প্যাথইন্টারপোলটার কী করে ..?
ইয়েনসারarah

EasyInOutQuart খুব স্বাভাবিক অনুভূতির জন্য প্রথমে অ্যানিমেশনটিকে ধীরে ধীরে, তারপরে দ্রুত, তারপরে ধীর করে তোলে। তারা এ বিষয়ে গভীরতার সাথে এ বিষয়ে এখানে কথা বলছেন ইজিংস.নেট
এরিক বি

1
আমি আপনার পদ্ধতিটি চেষ্টা করেছি কিন্তু যখনই অ্যানিমেশনটি শেষ হয় তখন আমার দৃশ্যটি আর দৃশ্যমান হয় না।
আমান ভার্মা

26

ঠিক আছে, আমি একটি খুব কুৎসিত সমাধান পেয়েছি:

public static Animation expand(final View v, Runnable onEnd) {
    try {
        Method m = v.getClass().getDeclaredMethod("onMeasure", int.class, int.class);
        m.setAccessible(true);
        m.invoke(
            v,
            MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
            MeasureSpec.makeMeasureSpec(((View)v.getParent()).getMeasuredHeight(), MeasureSpec.AT_MOST)
        );
    } catch (Exception e){
        Log.e("test", "", e);
    }
    final int initialHeight = v.getMeasuredHeight();
    Log.d("test", "initialHeight="+initialHeight);

    v.getLayoutParams().height = 0;
    v.setVisibility(View.VISIBLE);
    Animation a = new Animation()
    {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            final int newHeight = (int)(initialHeight * interpolatedTime);
            v.getLayoutParams().height = newHeight;
            v.requestLayout();
        }

        @Override
        public boolean willChangeBounds() {
            return true;
        }
    };
    a.setDuration(5000);
    v.startAnimation(a);
    return a;
}

আরও ভাল সমাধান প্রস্তাব নির্দ্বিধায়!


3
+1, এমনকি এটি কুৎসিত নামেও পরিচিত, এটি এমন দৃশ্যের জন্য কাজ করে যেখানে আমরা এর আকারটি এখনও জানি না (উদাহরণস্বরূপ আমরা যদি একটি নতুন তৈরি ভিউ (যার আকার FILL_PARENT হয়) পিতামাতার সাথে যুক্ত করি এবং প্রাণবন্ত করতে চাই এই প্রক্রিয়া, পিতামাতার আকার বৃদ্ধি অ্যানিমেট সহ)।
ভিট খুডেনকো

বিটিডাব্লু, দেখে মনে হচ্ছে View.onMeause(widthMeasureSpec, heightMeasureSpec)অনুরোধে কিছুটা ত্রুটি রয়েছে , সুতরাং প্রস্থ এবং উচ্চতার চশমাগুলিকে সরিয়ে নেওয়া উচিত।
ভিট খুডেনকো

22
public static void expand(final View v, int duration, int targetHeight) {
        v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        v.getLayoutParams().height = 0;
        v.setVisibility(View.VISIBLE);
        ValueAnimator valueAnimator = ValueAnimator.ofInt(0, targetHeight);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                v.getLayoutParams().height = (int) animation.getAnimatedValue();
                v.requestLayout();
            }
        });
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.setDuration(duration);
        valueAnimator.start();
    }
public static void collapse(final View v, int duration, int targetHeight) {
    ValueAnimator valueAnimator = ValueAnimator.ofInt(0, targetHeight);
    valueAnimator.setInterpolator(new DecelerateInterpolator());
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            v.getLayoutParams().height = (int) animation.getAnimatedValue();
            v.requestLayout();
        }
    });
    valueAnimator.setInterpolator(new DecelerateInterpolator());
    valueAnimator.setDuration(duration);
    valueAnimator.start();
}

1
আমার এই সমস্যাটি আছে ... সঙ্কুচিত দৃশ্যের ভিতরে থাকা সামগ্রীটি প্রসারণে অদৃশ্য হয়ে যাচ্ছে। আমার রিসাইক্লার ভিউ রয়েছে যা এই দর্শনটি প্রসারিত করতে অদৃশ্য হয়ে যায়। @ লেনায়ান
অক্ষয় মহাজন

21

আপনি যদি পুরোপুরি প্রসারিত বা ধসে যেতে না চান - এখানে একটি সরল হাইটঅ্যানিমেশন -

import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Transformation;

public class HeightAnimation extends Animation {
    protected final int originalHeight;
    protected final View view;
    protected float perValue;

    public HeightAnimation(View view, int fromHeight, int toHeight) {
        this.view = view;
        this.originalHeight = fromHeight;
        this.perValue = (toHeight - fromHeight);
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        view.getLayoutParams().height = (int) (originalHeight + perValue * interpolatedTime);
        view.requestLayout();
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
}

ব্যবহার:

HeightAnimation heightAnim = new HeightAnimation(view, view.getHeight(), viewPager.getHeight() - otherView.getHeight());
heightAnim.setDuration(1000);
view.startAnimation(heightAnim);

13

টম এস্তেরেজের দ্বারা বর্তমানে গৃহীত উত্তরটি আমি অভিযোজিত করেছি , যা কাজ করেছে তবে একটি চপি ছিল এবং খুব মসৃণ অ্যানিমেশন ছিল না। আমার সমাধানটি মূলত Animationক এর সাথে প্রতিস্থাপন করে ValueAnimator, যা Interpolatorবিভিন্ন প্রভাব যেমন যেমন ওভারশুট, বাউন্স, ত্বরান্বিত ইত্যাদি অর্জন করতে আপনার পছন্দসই একটিতে লাগানো যেতে পারে etc.

এই দ্রবণটি গতিশীল উচ্চতাযুক্ত (যেমন ব্যবহার করা WRAP_CONTENT) এমন দর্শনগুলির সাথে দুর্দান্ত কাজ করে কারণ এটি প্রথমে প্রকৃত প্রয়োজনীয় উচ্চতা পরিমাপ করে এবং তারপরে সেই উচ্চতায় অ্যানিমেট করে।

public static void expand(final View v) {
    v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
    final int targetHeight = v.getMeasuredHeight();

    // Older versions of android (pre API 21) cancel animations for views with a height of 0.
    v.getLayoutParams().height = 1;
    v.setVisibility(View.VISIBLE);

    ValueAnimator va = ValueAnimator.ofInt(1, targetHeight);
    va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            v.getLayoutParams().height = (Integer) animation.getAnimatedValue();
            v.requestLayout();
        }
    });
    va.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationEnd(Animator animation) {
            v.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
        }

        @Override public void onAnimationStart(Animator animation) {}
        @Override public void onAnimationCancel(Animator animation) {}
        @Override public void onAnimationRepeat(Animator animation) {}
    });
    va.setDuration(300);
    va.setInterpolator(new OvershootInterpolator());
    va.start();
}

public static void collapse(final View v) {
    final int initialHeight = v.getMeasuredHeight();

    ValueAnimator va = ValueAnimator.ofInt(initialHeight, 0);
    va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        public void onAnimationUpdate(ValueAnimator animation) {
            v.getLayoutParams().height = (Integer) animation.getAnimatedValue();
            v.requestLayout();
        }
    });
    va.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationEnd(Animator animation) {
            v.setVisibility(View.GONE);
        }

        @Override public void onAnimationStart(Animator animation) {}
        @Override public void onAnimationCancel(Animator animation) {}
        @Override public void onAnimationRepeat(Animator animation) {}
    });
    va.setDuration(300);
    va.setInterpolator(new DecelerateInterpolator());
    va.start();
}

আপনি তারপর কেবল কল expand( myView );বা collapse( myView );


ধন্যবাদ। ন্যূনতম উচ্চতা 0 না হলে আপনি এমন পরিস্থিতিও যুক্ত করতে পারেন
কুলমাইন্ড

আমি লিনিয়ারলআউট জন্য আমার জন্য কাজ করি
রজার

স্রেফ ব্যবহৃত প্যারামগুলি সংশোধন করে v.measure()এখন এটি নিখুঁতভাবে কাজ করছে। ধন্যবাদ!
শাহুদ উল হাসান

8

কোটলিন এক্সটেনশন ফাংশন ব্যবহার করা এটি পরীক্ষিত এবং সংক্ষিপ্ত উত্তর

যে কোনও ভিউতে কেবল অ্যানিমেটভিজিবিলিটি (প্রসারিত / পতন) কল করুন।

fun View.animateVisibility(setVisible: Boolean) {
    if (setVisible) expand(this) else collapse(this)
}

private fun expand(view: View) {
    view.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
    val initialHeight = 0
    val targetHeight = view.measuredHeight

    // Older versions of Android (pre API 21) cancel animations for views with a height of 0.
    //v.getLayoutParams().height = 1;
    view.layoutParams.height = 0
    view.visibility = View.VISIBLE

    animateView(view, initialHeight, targetHeight)
}

private fun collapse(view: View) {
    val initialHeight = view.measuredHeight
    val targetHeight = 0

    animateView(view, initialHeight, targetHeight)
}

private fun animateView(v: View, initialHeight: Int, targetHeight: Int) {
    val valueAnimator = ValueAnimator.ofInt(initialHeight, targetHeight)
    valueAnimator.addUpdateListener { animation ->
        v.layoutParams.height = animation.animatedValue as Int
        v.requestLayout()
    }
    valueAnimator.addListener(object : Animator.AnimatorListener {
        override fun onAnimationEnd(animation: Animator) {
            v.layoutParams.height = targetHeight
        }

        override fun onAnimationStart(animation: Animator) {}
        override fun onAnimationCancel(animation: Animator) {}
        override fun onAnimationRepeat(animation: Animator) {}
    })
    valueAnimator.duration = 300
    valueAnimator.interpolator = DecelerateInterpolator()
    valueAnimator.start()
}

একই উত্তর পোস্ট করতে চেয়েছিলেন :) খুব খারাপ এটি এখানে এত গভীরভাবে কবর দেওয়া হয়।
মুটিজেনফ্লো

@ ময়েটজেনফ্লো আরও বেশি লোক যদি উত্তরটি সমর্থন করে তবে তা সামনে আসবে। :)
রাজকিরণ

আমি এই সমাধানটি পছন্দ করেছি যতক্ষণ না আমি বুঝতে পেরেছি যদি র‌্যাপ_কন্টেন্টের উচ্চতা সহ একাধিক লাইনযুক্ত পাঠ্যদর্শন নেই, প্রসারিত হয়ে গেলে পাঠ্যদর্শনটি কেবল একটি লাইন দেখায় will আমি এখনই ঠিক করার চেষ্টা করছি
olearyj234

7

টম এস্তেরেজের দুর্দান্ত উত্তর এবং এরিক বি এর দুর্দান্ত আপডেটে যুক্ত করে আমি ভেবেছিলাম যে আমি নিজের নিজের পোস্টটি প্রসারিত করব এবং চুক্তি পদ্ধতিগুলিকে একের মধ্যে সংহত করে ফেলব । এইভাবে, আপনি উদাহরণস্বরূপ এর মত একটি ক্রিয়া থাকতে পারে ...

button.setOnClickListener(v -> expandCollapse(view));

... যা নীচের পদ্ধতিটিকে কল করে এবং প্রতিটি অন্লিক () এর পরে কী করতে হবে তা নির্ধারণ করে দেয় ...

public static void expandCollapse(View view) {

    boolean expand = view.getVisibility() == View.GONE;
    Interpolator easeInOutQuart = PathInterpolatorCompat.create(0.77f, 0f, 0.175f, 1f);

    view.measure(
        View.MeasureSpec.makeMeasureSpec(((View) view.getParent()).getWidth(), View.MeasureSpec.EXACTLY),
        View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
    );

    int height = view.getMeasuredHeight();
    int duration = (int) (height/view.getContext().getResources().getDisplayMetrics().density);

    Animation animation = new Animation() {
        @Override protected void applyTransformation(float interpolatedTime, Transformation t) {
            if (expand) {
                view.getLayoutParams().height = 1;
                view.setVisibility(View.VISIBLE);
                if (interpolatedTime == 1) {
                    view.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
                } else {
                    view.getLayoutParams().height = (int) (height * interpolatedTime);
                }
                view.requestLayout();
            } else {
                if (interpolatedTime == 1) {
                    view.setVisibility(View.GONE);
                } else {
                    view.getLayoutParams().height = height - (int) (height * interpolatedTime);
                    view.requestLayout();
                }
            }
        }
        @Override public boolean willChangeBounds() {
            return true;
        }
    };

    animation.setInterpolator(easeInOutQuart);
    animation.setDuration(duration);
    view.startAnimation(animation);

}

আমি এই কোডটি চেষ্টা করেছি তবে এটির জন্য একাধিক ভিউতে কাজ করতে হবে, আপনাকে স্ক্রোল করতে হবে। আমি কীভাবে এটি ঠিক করতে পারি কোনও ধারণা? stackoverflow.com/q/43916369/1009507
sammyukavi

@ উকাবি আমি একাধিক দর্শন সহ এটি ব্যবহার করছি এবং এটি একটি স্ক্রোলভিউয়ের মধ্যে দুর্দান্ত কাজ করে।
mjp66

একটি পুনর্ব্যবহারযোগ্য সম্পর্কে কি?
সম্ম্যুকাভী

@ উকবির এখনও এটি একটি পুনর্ব্যবহারযোগ্য দৃশ্যে ব্যবহার করার প্রয়োজন নেই তবে এটি কেন কাজ করবে না তা আমি দেখতে পাচ্ছি না। আপনাকে এটির জন্য নিজেই কিছুটা পরীক্ষা করতে হবে;)
mjp66

6

আমি উপরের খুব সহায়ক উত্তরে কিছু যুক্ত করতে চাই । আপনার মতামতগুলি যেহেতু আপনি উচ্চতাটি না জানেন তা শেষ না হয়ে গেলেই আপনার দর্শনগুলি .get হাইট () 0 প্রদান করে আপনি উচ্চতা পেতে নিম্নলিখিতটি করতে পারেন:

contentView.measure(DUMMY_HIGH_DIMENSION, DUMMY_HIGH_DIMENSION);
int finalHeight = view.getMeasuredHeight();

যেখানে DUMMY_HIGH_DIMENSIONS প্রস্থ / উচ্চতা (পিক্সেলগুলিতে) আপনার দৃষ্টিতে সীমাবদ্ধ রয়েছে ... যখন ভিউটি একটি স্ক্রোলভিউ দিয়ে আবদ্ধ করা হয় তখন এটির একটি বিশাল সংখ্যা যুক্তিযুক্ত।


6

এটি একটি স্নিপেট যা আমি অ্যানিমেশন সহ একটি দৃশ্যের (লিনিয়ারলআউট) প্রস্থের আকার পরিবর্তন করতাম।

কোডটি আকারের আকার অনুযায়ী প্রসারিত বা সঙ্কুচিত করার কথা। আপনি যদি একটি পূর্ণ_পরিচয় প্রস্থ চান, পতাকাটি সত্য হিসাবে সেট করার সময় আপনাকে প্যারেন্টটি .getMeasuredWidth টার্গেট প্রস্থ হিসাবে পাস করতে হবে।

আশা করি এটি আপনার কয়েকজনকে সহায়তা করবে।

public class WidthResizeAnimation extends Animation {
int targetWidth;
int originaltWidth;
View view;
boolean expand;
int newWidth = 0;
boolean fillParent;

public WidthResizeAnimation(View view, int targetWidth, boolean fillParent) {
    this.view = view;
    this.originaltWidth = this.view.getMeasuredWidth();
    this.targetWidth = targetWidth;
    newWidth = originaltWidth;
    if (originaltWidth > targetWidth) {
        expand = false;
    } else {
        expand = true;
    }
    this.fillParent = fillParent;
}

@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
    if (expand && newWidth < targetWidth) {
        newWidth = (int) (newWidth + (targetWidth - newWidth) * interpolatedTime);
    }

    if (!expand && newWidth > targetWidth) {
        newWidth = (int) (newWidth - (newWidth - targetWidth) * interpolatedTime);
    }
    if (fillParent && interpolatedTime == 1.0) {
        view.getLayoutParams().width = -1;

    } else {
        view.getLayoutParams().width = newWidth;
    }
    view.requestLayout();
}

@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
    super.initialize(width, height, parentWidth, parentHeight);
}

@Override
public boolean willChangeBounds() {
    return true;
}

}


এটি কাজ করার কোন কৌশল আছে? শ্রেণিটি সঠিক আসল এবং লক্ষ্য প্রস্থগুলি পেয়েছে, তবে আমার মতামতগুলির আকার পরিবর্তন হবে না। আমি ব্যবহার করছি resizeAnim.start()। এছাড়াও সঙ্গে এবং ছাড়া চেষ্টা করেছিsetFillAfter(true)
বেন কেনের

বুঝেছি. .startAnimation(resizeAnim)ভিউ কল করতে হয়েছিল।
বেন কেন

6

স্মুথ অ্যানিমেশনের জন্য দয়া করে রান পদ্ধতি সহ হ্যান্ডলারটি ব্যবহার করুন ..... এবং প্রসারিত / সঙ্কুচিত অ্যানিমেশন উপভোগ করুন

    class AnimUtils{

                 public void expand(final View v) {
                  int ANIMATION_DURATION=500;//in milisecond
        v.measure(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        final int targtetHeight = v.getMeasuredHeight();

        v.getLayoutParams().height = 0;
        v.setVisibility(View.VISIBLE);
        Animation a = new Animation()
        {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                v.getLayoutParams().height = interpolatedTime == 1
                        ? LayoutParams.WRAP_CONTENT
                        : (int)(targtetHeight * interpolatedTime);
                v.requestLayout();
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        // 1dp/ms
        a.setDuration(ANIMATION_DURATION);

      // a.setDuration((int)(targtetHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }



    public void collapse(final View v) {
        final int initialHeight = v.getMeasuredHeight();

        Animation a = new Animation()
        {
            @Override
            protected void applyTransformation(float interpolatedTime, Transformation t) {
                if(interpolatedTime == 1){
                    v.setVisibility(View.GONE);
                }else{
                    v.getLayoutParams().height = initialHeight - (int)(initialHeight * interpolatedTime);
                    v.requestLayout();
                }
            }

            @Override
            public boolean willChangeBounds() {
                return true;
            }
        };

        // 1dp/ms
        a.setDuration(ANIMATION_DURATION);
       // a.setDuration((int)(initialHeight / v.getContext().getResources().getDisplayMetrics().density));
        v.startAnimation(a);
    }
}

এবং এই কোডটি ব্যবহার করে কল করুন:

       private void setAnimationOnView(final View inactive ) {
    //I am applying expand and collapse on this TextView ...You can use your view 

    //for expand animation
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {

            new AnimationUtililty().expand(inactive);

        }
    }, 1000);


    //For collapse
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {

            new AnimationUtililty().collapse(inactive);
            //inactive.setVisibility(View.GONE);

        }
    }, 8000);

}

অন্যান্য সমাধানটি হ'ল:

               public void expandOrCollapse(final View v,String exp_or_colpse) {
    TranslateAnimation anim = null;
    if(exp_or_colpse.equals("expand"))
    {
        anim = new TranslateAnimation(0.0f, 0.0f, -v.getHeight(), 0.0f);
        v.setVisibility(View.VISIBLE);  
    }
    else{
        anim = new TranslateAnimation(0.0f, 0.0f, 0.0f, -v.getHeight());
        AnimationListener collapselistener= new AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
            v.setVisibility(View.GONE);
            }
        };

        anim.setAnimationListener(collapselistener);
    }

     // To Collapse
        //

    anim.setDuration(300);
    anim.setInterpolator(new AccelerateInterpolator(0.5f));
    v.startAnimation(anim);
}

5

@ টম এস্তেরেজ এবং @ জেরাল্ডো নেটোর কাছ থেকে সম্মিলিত সমাধান

public static void expandOrCollapseView(View v,boolean expand){

    if(expand){
        v.measure(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
        final int targetHeight = v.getMeasuredHeight();
        v.getLayoutParams().height = 0;
        v.setVisibility(View.VISIBLE);
        ValueAnimator valueAnimator = ValueAnimator.ofInt(targetHeight);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                v.getLayoutParams().height = (int) animation.getAnimatedValue();
                v.requestLayout();
            }
        });
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.setDuration(500);
        valueAnimator.start();
    }
    else
    {
        final int initialHeight = v.getMeasuredHeight();
        ValueAnimator valueAnimator = ValueAnimator.ofInt(initialHeight,0);
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                v.getLayoutParams().height = (int) animation.getAnimatedValue();
                v.requestLayout();
                if((int)animation.getAnimatedValue() == 0)
                    v.setVisibility(View.GONE);
            }
        });
        valueAnimator.setInterpolator(new DecelerateInterpolator());
        valueAnimator.setDuration(500);
        valueAnimator.start();
    }
}

//sample usage
expandOrCollapseView((Your ViewGroup),(Your ViewGroup).getVisibility()!=View.VISIBLE);

4

হ্যাঁ, আমি উপরের মন্তব্যের সাথে একমত হয়েছি। এবং প্রকৃতপক্ষে, এটি সঠিক (বা অন্তত সবচেয়ে সহজ?) কাজটি করা উচিত (এক্সএমএলে) "0px" এর প্রাথমিক বিন্যাসের উচ্চতা নির্দিষ্ট করা - এবং তারপরে আপনি "টো হাইট" এর জন্য অন্য কোনও যুক্তিতে পাস করতে পারেন ( আপনার পছন্দসই অ্যানিমেশন উপ-শ্রেণীর নির্মাণকারীর কাছে "চূড়ান্ত উচ্চতা") যেমন, উদাহরণস্বরূপ উপরের উদাহরণে এটি দেখতে এরকম কিছু দেখাবে:

    public DropDownAnim( View v, int toHeight ) { ... }

যাইহোক, আশা করি যে সাহায্য করে! :)


4

এখানে আমার সমাধান। আমি মনে করি এটি সহজ। এটি কেবলমাত্র দৃষ্টিভঙ্গি প্রসারিত করে তবে বাড়ানো সহজ।

public class WidthExpandAnimation extends Animation
{
    int _targetWidth;
    View _view;

    public WidthExpandAnimation(View view)
    {
        _view = view;
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t)
    {
        if (interpolatedTime < 1.f)
        {
            int newWidth = (int) (_targetWidth * interpolatedTime);

            _view.layout(_view.getLeft(), _view.getTop(),
                    _view.getLeft() + newWidth, _view.getBottom());
        }
        else
            _view.requestLayout();
    }

    @Override
    public void initialize(int width, int height, int parentWidth, int parentHeight)
    {
        super.initialize(width, height, parentWidth, parentHeight);

        _targetWidth = width;
    }

    @Override
    public boolean willChangeBounds() {
        return true;
    }
}

4

আমি মনে করি সবচেয়ে সহজ সমাধানটি android:animateLayoutChanges="true"আপনার সেট করা LinearLayoutএবং তারপরে দৃশ্যমানতা সেট করে কেবল দেখান / আড়াল করা। কবজির মতো কাজ করে তবে অ্যানিমেশন সময়কালে আপনার কোনও নিয়ন্ত্রণ নেই


3

তুমি কি সঠিক পথে আছো. অ্যানিমেশনটি শুরু হওয়ার আগে আপনার শূন্যের লেআউটের উচ্চতা ঠিক আছে কিনা তা নিশ্চিত করুন। অ্যানিমেশনটি শুরু করার আগে অ্যানিমেশনের প্রথম ফ্রেমের মতো দেখতে আপনার সেটআপটি শুরু করতে চান।


আমি সম্মত তবে আমি যদি এটি করি তবে কীভাবে প্রাথমিকহাইট (আমার অ্যানিমেশন দ্বারা প্রয়োজনীয়) পাবেন?
টম এস্তেরেজ

আপনি কি প্রথমে প্রারম্ভিক উচ্চতা সংরক্ষণের চেষ্টা করেছেন, সেখানে দৃশ্যটি দৃশ্যমান সেট করে এবং তারপরে v.getLayoutParams () উচ্চতা = 0 নির্ধারণ করেছেন; সরাসরি পরে, সব শুরু?
মাইকা হেইনলাইন

হ্যাঁ, যদি আমি এটি করি তবে প্রাথমিক পদ্ধতিটি উচ্চতা = 0 দিয়ে ডাকা হয়
টম এস্তেরেজ

3

এটা আমার সমাধান ছিল, আমার ImageViewথেকে বৃদ্ধি 100%করার জন্য 200%, এবং তার মূল আকার ফিরে ভিতরে দুই অ্যানিমেশন ফাইল ব্যবহার res/anim/ফোল্ডারের

anim_grow.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
 android:interpolator="@android:anim/accelerate_interpolator">
 <scale
  android:fromXScale="1.0"
  android:toXScale="2.0"
  android:fromYScale="1.0"
  android:toYScale="2.0"
  android:duration="3000"
  android:pivotX="50%"
  android:pivotY="50%"
  android:startOffset="2000" />
</set>

anim_shrink.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
 android:interpolator="@android:anim/accelerate_interpolator">
 <scale
  android:fromXScale="2.0"
  android:toXScale="1.0"
  android:fromYScale="2.0"
  android:toYScale="1.0"
  android:duration="3000"
  android:pivotX="50%"
  android:pivotY="50%"
  android:startOffset="2000" />
</set>

ImageViewআমার পদ্ধতিতে একটি প্রেরণ করুনsetAnimationGrowShrink()

ImageView img1 = (ImageView)findViewById(R.id.image1);
setAnimationGrowShrink(img1);

setAnimationGrowShrink() পদ্ধতি:

private void setAnimationGrowShrink(final ImageView imgV){
    final Animation animationEnlarge = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.anim_grow);
    final Animation animationShrink = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.anim_shrink);

    imgV.startAnimation(animationEnlarge);

    animationEnlarge.setAnimationListener(new AnimationListener() {         
        @Override
        public void onAnimationStart(Animation animation) {}

        @Override
        public void onAnimationRepeat(Animation animation) {}

        @Override
        public void onAnimationEnd(Animation animation) {
            imgV.startAnimation(animationShrink);
        }
    });

    animationShrink.setAnimationListener(new AnimationListener() {          
        @Override
        public void onAnimationStart(Animation animation) {}

        @Override
        public void onAnimationRepeat(Animation animation) {}

        @Override
        public void onAnimationEnd(Animation animation) {
            imgV.startAnimation(animationEnlarge);
        }
    });

}

3

এটি সঠিক কাজের সমাধান, আমি এটি পরীক্ষা করেছি:

Exapnd:

private void expand(View v) {
    v.setVisibility(View.VISIBLE);

    v.measure(View.MeasureSpec.makeMeasureSpec(PARENT_VIEW.getWidth(), View.MeasureSpec.EXACTLY),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

    final int targetHeight = v.getMeasuredHeight();

    mAnimator = slideAnimator(0, targetHeight);
    mAnimator.setDuration(800);
    mAnimator.start();
}

সঙ্কুচিত করুন:

private void collapse(View v) {
    int finalHeight = v.getHeight();

    mAnimator = slideAnimator(finalHeight, 0);

    mAnimator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {

        }

        @Override
        public void onAnimationEnd(Animator animator) {
            //Height=0, but it set visibility to GONE
            llDescp.setVisibility(View.GONE);
        }

        @Override
        public void onAnimationCancel(Animator animator) {

        }

        @Override
        public void onAnimationRepeat(Animator animator) {

        }
    });
    mAnimator.start();
}

মান অ্যানিম্যাটর:

private ValueAnimator slideAnimator(int start, int end) {
    ValueAnimator mAnimator = ValueAnimator.ofInt(start, end);

    mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            //Update Height
            int value = (Integer) valueAnimator.getAnimatedValue();
            ViewGroup.LayoutParams layoutParams = llDescp.getLayoutParams();
            layoutParams.height = value;
            v.setLayoutParams(layoutParams);
        }
    });
    return mAnimator;
}

অ্যানিমেটেড হওয়ার জন্য ভি ভি দেখুন P


2

এটি droidQuery সহ সত্যই সহজ । শুরু করার জন্য, এই বিন্যাসটি বিবেচনা করুন:

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
    <LinearLayout
        android:id="@+id/v1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:text="View 1" />
    </LinearLayout>
    <LinearLayout
        android:id="@+id/v2"
        android:layout_width="wrap_content"
        android:layout_height="0dp" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:text="View 2" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" 
            android:text="View 3" />
    </LinearLayout>
</LinearLayout>

আমরা উচ্চতাটি পছন্দসই মানটিতে অ্যানিমেট করতে পারি 100dp- বলুন - নিম্নলিখিত কোডটি ব্যবহার করে:

//convert 100dp to pixel value
int height = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());

তারপরে droidQueryঅ্যানিমেট করতে ব্যবহার করুন। সবচেয়ে সহজ উপায় এটি দিয়ে:

$.animate("{ height: " + height + "}", new AnimationOptions());

অ্যানিমেশনটিকে আরও আকর্ষণীয় করে তুলতে, একটি সহজকরণ যুক্ত করার বিষয়টি বিবেচনা করুন:

$.animate("{ height: " + height + "}", new AnimationOptions().easing($.Easing.BOUNCE));

আপনি পদ্ধতিটি AnimationOptionsব্যবহারের সময়কালও পরিবর্তন করতে পারেন duration()বা অ্যানিমেশনটি শেষ হওয়ার পরে কী ঘটে তা পরিচালনা করতে পারেন। একটি জটিল উদাহরণের জন্য, চেষ্টা করুন:

$.animate("{ height: " + height + "}", new AnimationOptions().easing($.Easing.BOUNCE)
                                                             .duration(1000)
                                                             .complete(new Function() {
                                                                 @Override
                                                                 public void invoke($ d, Object... args) {
                                                                     $.toast(context, "finished", Toast.LENGTH_SHORT);
                                                                 }
                                                             }));

2

দেখার সম্প্রসারণ / পতনের জন্য সেরা সমাধান:

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        View view = buttonView.getId() == R.id.tb_search ? fSearch : layoutSettings;
        transform(view, 200, isChecked
            ? ViewGroup.LayoutParams.WRAP_CONTENT
            : 0);
    }

    public static void transform(final View v, int duration, int targetHeight) {
        int prevHeight  = v.getHeight();
        v.setVisibility(View.VISIBLE);
        ValueAnimator animator;
        if (targetHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
            v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            animator = ValueAnimator.ofInt(prevHeight, v.getMeasuredHeight());
        } else {
            animator = ValueAnimator.ofInt(prevHeight, targetHeight);
        }
        animator.addUpdateListener(animation -> {
            v.getLayoutParams().height = (animation.getAnimatedFraction() == 1.0f)
                    ? targetHeight
                    : (int) animation.getAnimatedValue();
            v.requestLayout();
        });
        animator.setInterpolator(new LinearInterpolator());
        animator.setDuration(duration);
        animator.start();
    }

যদিও এটি কাজ করে, এটি বিকাশকারী সেটিংস (অ্যানিমেশন সময়কাল) এর উপরও নির্ভর করে। এবং আপনার কোডটি পোলিশ করুন, ল্যাম্বদা-ফাংশন এবং পুনরায় ফর্ম্যাট মুছুন onCheckedChanged
কুলমাইন্ড

ভি এর লেআউটপ্যারামগুলি পরিবর্তন করার পরে কেবলমাত্র ভিটিতে অনুরোধ লেআউটকে কল করা কেন যথেষ্ট? আমি ভেবেছিলাম ভি এর পিতামাতার কাছে অনুরোধটি কল করা দরকার হবে
ভ্লাজল

2

আপনি সামান্য মোচড় দিয়ে একটি ভিউপ্রোপার্টি অ্যানিম্যাটর ব্যবহার করতে পারেন। সঙ্কুচিত হতে, ভিউটি 1 পিক্সেলের উচ্চতায় স্কেল করুন, তারপরে এটি আড়াল করুন। প্রসারিত করতে, এটি দেখান, তারপরে এর উচ্চতায় প্রসারিত করুন।

private void collapse(final View view) {
    view.setPivotY(0);
    view.animate().scaleY(1/view.getHeight()).setDuration(1000).withEndAction(new Runnable() {
        @Override public void run() {
            view.setVisibility(GONE);
        }
    });
}

private void expand(View view, int height) {
    float scaleFactor = height / view.getHeight();

    view.setVisibility(VISIBLE);
    view.setPivotY(0);
    view.animate().scaleY(scaleFactor).setDuration(1000);
}

পিভটটি কোথা থেকে স্কেল করবেন সে দৃশ্যটি জানায়, ডিফল্ট মাঝখানে থাকে। সময়কাল alচ্ছিক (ডিফল্ট = 1000)। আপনি ইন্টারপোলটারটিও ব্যবহার করতে পছন্দ করতে পারেন, পছন্দ করুন.setInterpolator(new AccelerateDecelerateInterpolator())


1

আমি এমন সংস্করণ তৈরি করেছি যাতে আপনার লেআউটের উচ্চতা নির্দিষ্ট করার দরকার নেই, তাই এটি ব্যবহার করা অনেক সহজ এবং ক্লিনার। সমাধানটি হ'ল অ্যানিমেশনের প্রথম ফ্রেমে উচ্চতা পাওয়া (এটি এই মুহুর্তে পাওয়া যায়, কমপক্ষে আমার পরীক্ষার সময়)। এইভাবে আপনি একটি স্বেচ্ছাসেবী উচ্চতা এবং নীচের মার্জিন সহ একটি ভিউ সরবরাহ করতে পারেন।

কনস্ট্রাক্টরটিতে একটি ছোট্ট হ্যাকও রয়েছে - নীচের মার্জিনটি -10000 তে সেট করা হয়েছে যাতে রূপান্তরটির আগে দৃশ্যটি লুকানো থাকে (ঝাঁকুনি প্রতিরোধ করে)।

public class ExpandAnimation extends Animation {


    private View mAnimatedView;
    private ViewGroup.MarginLayoutParams mViewLayoutParams;
    private int mMarginStart, mMarginEnd;

    public ExpandAnimation(View view) {
        mAnimatedView = view;
        mViewLayoutParams = (ViewGroup.MarginLayoutParams) view.getLayoutParams();
        mMarginEnd = mViewLayoutParams.bottomMargin;
        mMarginStart = -10000; //hide before viewing by settings very high negative bottom margin (hack, but works nicely)
        mViewLayoutParams.bottomMargin = mMarginStart;
        mAnimatedView.setLayoutParams(mViewLayoutParams);
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        super.applyTransformation(interpolatedTime, t);
            //view height is already known when the animation starts
            if(interpolatedTime==0){
                mMarginStart = -mAnimatedView.getHeight();
            }
            mViewLayoutParams.bottomMargin = (int)((mMarginEnd-mMarginStart) * interpolatedTime)+mMarginStart;
            mAnimatedView.setLayoutParams(mViewLayoutParams);
    }
}

1

মান অ্যানিমেটার ব্যবহার করুন:

ValueAnimator expandAnimation = ValueAnimator.ofInt(mainView.getHeight(), 400);
expandAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(final ValueAnimator animation) {
        int height = (Integer) animation.getAnimatedValue();
        RelativeLayout.LayoutParams lp = (LayoutParams) mainView.getLayoutParams();
        lp.height = height;
    }
});


expandAnimation.setDuration(500);
expandAnimation.start();

আমার ক্ষেত্রে কিছু হয় না। এছাড়াও আপনি আপনার কোডটি সহজ করতে পারেন, এতে 2 টি লাইন ভেঙে পড়েছেন mainView.getLayoutParams().height = height
কুলমাইন্ড

1
public static void slide(View v, int speed, int pos) {
    v.animate().setDuration(speed);
    v.animate().translationY(pos);
    v.animate().start();
}

// slide down
slide(yourView, 250, yourViewHeight);
// slide up
slide(yourView, 250, 0);

1
/**
 * Animation that either expands or collapses a view by sliding it down to make
 * it visible. Or by sliding it up so it will hide. It will look like it slides
 * behind the view above.
 * 
 */
public class FinalExpandCollapseAnimation extends Animation
{
    private View mAnimatedView;
    private int mEndHeight;
    private int mType;
    public final static int COLLAPSE = 1;
    public final static int EXPAND = 0;
    private LinearLayout.LayoutParams mLayoutParams;
    private RelativeLayout.LayoutParams mLayoutParamsRel;
    private String layout;
    private Context context;

    /**
     * Initializes expand collapse animation, has two types, collapse (1) and
     * expand (0).
     * 
     * @param view
     *            The view to animate
     * @param type
     *            The type of animation: 0 will expand from gone and 0 size to
     *            visible and layout size defined in xml. 1 will collapse view
     *            and set to gone
     */
    public FinalExpandCollapseAnimation(View view, int type, int height, String layout, Context context)
    {
        this.layout = layout;
        this.context = context;
        mAnimatedView = view;
        mEndHeight = mAnimatedView.getMeasuredHeight();
        if (layout.equalsIgnoreCase("linear"))
            mLayoutParams = ((LinearLayout.LayoutParams) view.getLayoutParams());
        else
            mLayoutParamsRel = ((RelativeLayout.LayoutParams) view.getLayoutParams());
        mType = type;
        if (mType == EXPAND)
        {
            AppConstant.ANIMATED_VIEW_HEIGHT = height;
        }
        else
        {
            if (layout.equalsIgnoreCase("linear"))
                mLayoutParams.topMargin = 0;
            else
                mLayoutParamsRel.topMargin = convertPixelsIntoDensityPixels(36);
        }
        setDuration(600);
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t)
    {
        super.applyTransformation(interpolatedTime, t);
        if (interpolatedTime < 1.0f)
        {
            if (mType == EXPAND)
            {
                if (layout.equalsIgnoreCase("linear"))
                {
                    mLayoutParams.height = AppConstant.ANIMATED_VIEW_HEIGHT
                            + (-AppConstant.ANIMATED_VIEW_HEIGHT + (int) (AppConstant.ANIMATED_VIEW_HEIGHT * interpolatedTime));
                }
                else
                {
                    mLayoutParamsRel.height = AppConstant.ANIMATED_VIEW_HEIGHT
                            + (-AppConstant.ANIMATED_VIEW_HEIGHT + (int) (AppConstant.ANIMATED_VIEW_HEIGHT * interpolatedTime));
                }
                mAnimatedView.setVisibility(View.VISIBLE);
            }
            else
            {
                if (layout.equalsIgnoreCase("linear"))
                    mLayoutParams.height = mEndHeight - (int) (mEndHeight * interpolatedTime);
                else
                    mLayoutParamsRel.height = mEndHeight - (int) (mEndHeight * interpolatedTime);
            }
            mAnimatedView.requestLayout();
        }
        else
        {
            if (mType == EXPAND)
            {
                if (layout.equalsIgnoreCase("linear"))
                {
                    mLayoutParams.height = AppConstant.ANIMATED_VIEW_HEIGHT;
                    mLayoutParams.topMargin = 0;
                }
                else
                {
                    mLayoutParamsRel.height = AppConstant.ANIMATED_VIEW_HEIGHT;
                    mLayoutParamsRel.topMargin = convertPixelsIntoDensityPixels(36);
                }
                mAnimatedView.setVisibility(View.VISIBLE);
                mAnimatedView.requestLayout();
            }
            else
            {
                if (layout.equalsIgnoreCase("linear"))
                    mLayoutParams.height = 0;
                else
                    mLayoutParamsRel.height = 0;
                mAnimatedView.setVisibility(View.GONE);
                mAnimatedView.requestLayout();
            }
        }
    }

    private int convertPixelsIntoDensityPixels(int pixels)
    {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        return (int) metrics.density * pixels;
    }
}

ক্লাসটি নিম্নলিখিত উপায়ে বলা যেতে পারে

   if (findViewById(R.id.ll_specailoffer_show_hide).getVisibility() == View.VISIBLE) {
                        ((ImageView) findViewById(R.id.iv_specialhour_seemore)).setImageResource(R.drawable.white_dropdown_up);

                        FinalExpandCollapseAnimation finalExpandCollapseAnimation = new FinalExpandCollapseAnimation(
                                findViewById(R.id.ll_specailoffer_show_hide),
                                FinalExpandCollapseAnimation.COLLAPSE,
                                SpecialOfferHeight, "linear", this);
                        findViewById(R.id.ll_specailoffer_show_hide)
                                .startAnimation(finalExpandCollapseAnimation);
                        ((View) findViewById(R.id.ll_specailoffer_show_hide).getParent()).invalidate();
                    } else {
                        ((ImageView) findViewById(R.id.iv_specialhour_seemore)).setImageResource(R.drawable.white_dropdown);

                        FinalExpandCollapseAnimation finalExpandCollapseAnimation = new FinalExpandCollapseAnimation(
                                findViewById(R.id.ll_specailoffer_show_hide),
                                FinalExpandCollapseAnimation.EXPAND,
                                SpecialOfferHeight, "linear", this);
                        findViewById(R.id.ll_specailoffer_show_hide)
                                .startAnimation(finalExpandCollapseAnimation);
                        ((View) findViewById(R.id.ll_specailoffer_show_hide).getParent()).invalidate();
                    }

1

@ টম এস্তেরেজ এবং @ শেঠ নেলসনের (শীর্ষ 2) সমাধানগুলির উপর ভিত্তি করে আমি সেগুলি সিমলিফাই করেছি। মূল সমাধানের পাশাপাশি এটি বিকাশকারী বিকল্পগুলিতে (অ্যানিমেশন সেটিংস) উপর নির্ভর করে না।

private void resizeWithAnimation(final View view, int duration, final int targetHeight) {
    final int initialHeight = view.getMeasuredHeight();
    final int distance = targetHeight - initialHeight;

    view.setVisibility(View.VISIBLE);

    Animation a = new Animation() {
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            if (interpolatedTime == 1 && targetHeight == 0) {
                view.setVisibility(View.GONE);
            }
            view.getLayoutParams().height = (int) (initialHeight + distance * interpolatedTime);
            view.requestLayout();
        }

        @Override
        public boolean willChangeBounds() {
            return true;
        }
    };

    a.setDuration(duration);
    view.startAnimation(a);
}

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