সম্পত্তি অ্যানিমেশন ওভারভিউ

কম্পোজ পদ্ধতিটি চেষ্টা করুন
জেটপ্যাক কম্পোজ অ্যান্ড্রয়েডের জন্য প্রস্তাবিত UI টুলকিট। কম্পোজে কীভাবে অ্যানিমেশন ব্যবহার করতে হয় তা জানুন।

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

প্রপার্টি অ্যানিমেশন সিস্টেম আপনাকে একটি অ্যানিমেশনের নিম্নলিখিত বৈশিষ্ট্যগুলো নির্ধারণ করতে দেয়:

  • সময়কাল: আপনি একটি অ্যানিমেশনের সময়কাল নির্দিষ্ট করে দিতে পারেন। এর ডিফল্ট দৈর্ঘ্য হলো ৩০০ মিলিসেকেন্ড।
  • সময় ইন্টারপোলেশন: অ্যানিমেশনের বর্তমান অতিবাহিত সময়ের ফাংশন হিসেবে প্রপার্টির মানগুলো কীভাবে গণনা করা হবে, তা আপনি নির্দিষ্ট করে দিতে পারেন।
  • পুনরাবৃত্তির সংখ্যা এবং আচরণ: একটি অ্যানিমেশন নির্দিষ্ট সময়কাল শেষে পৌঁছালে তা পুনরাবৃত্তি হবে কি না এবং কতবার পুনরাবৃত্তি হবে, তা আপনি নির্দিষ্ট করতে পারেন। আপনি অ্যানিমেশনটি উল্টোভাবে চালাতে চান কি না, তাও নির্দিষ্ট করতে পারেন। এটিকে 'রিভার্স' (বিপরীত) এ সেট করলে, পুনরাবৃত্তির সংখ্যা পূরণ না হওয়া পর্যন্ত অ্যানিমেশনটি বারবার সামনে-পেছনে চলতে থাকে।
  • অ্যানিমেটর সেট: আপনি অ্যানিমেশনগুলোকে যৌক্তিক সেটে ভাগ করতে পারেন, যেগুলো একসাথে, ক্রমানুসারে অথবা নির্দিষ্ট বিরতির পর প্লে হবে।
  • ফ্রেম রিফ্রেশ বিলম্ব: আপনি আপনার অ্যানিমেশনের ফ্রেমগুলো কত ঘন ঘন রিফ্রেশ হবে তা নির্দিষ্ট করে দিতে পারেন। ডিফল্টভাবে এটি প্রতি ১০ মিলিসেকেন্ডে রিফ্রেশ হওয়ার জন্য সেট করা থাকে, কিন্তু আপনার অ্যাপ্লিকেশনটি কত দ্রুত ফ্রেম রিফ্রেশ করতে পারবে তা শেষ পর্যন্ত নির্ভর করে সিস্টেমটি সামগ্রিকভাবে কতটা ব্যস্ত এবং সিস্টেমটি অন্তর্নিহিত টাইমারটিকে কত দ্রুত পরিষেবা দিতে পারে তার উপর।

প্রপার্টি অ্যানিমেশনের একটি পূর্ণাঙ্গ উদাহরণ দেখতে, গিটহাবে থাকা CustomTransition স্যাম্পলের ChangeColor ক্লাসটি দেখুন।

প্রপার্টি অ্যানিমেশন কীভাবে কাজ করে

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

চিত্র ১. একটি রৈখিক অ্যানিমেশনের উদাহরণ

আপনি অ্যানিমেশনে নন-লিনিয়ার ইন্টারপোলেশনও নির্দিষ্ট করে দিতে পারেন। চিত্র ২-এ একটি কাল্পনিক বস্তু দেখানো হয়েছে যা অ্যানিমেশনের শুরুতে গতি বাড়ায় এবং শেষে গতি কমায়। বস্তুটি তখনও ৪০ মিলিসেকেন্ডে ৪০ পিক্সেল দূরত্ব অতিক্রম করে, কিন্তু তা নন-লিনিয়ারভাবে। শুরুতে, এই অ্যানিমেশনটি অর্ধেক পথ পর্যন্ত গতি বাড়ায় এবং তারপর অর্ধেক পথ থেকে শেষ পর্যন্ত গতি কমায়। চিত্র ২-এ যেমন দেখানো হয়েছে, অ্যানিমেশনের শুরুতে এবং শেষে অতিক্রান্ত দূরত্ব মাঝখানের দূরত্বের চেয়ে কম।

চিত্র ২. একটি অরৈখিক অ্যানিমেশনের উদাহরণ

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

চিত্র ৩. কীভাবে অ্যানিমেশন গণনা করা হয়

ValueAnimator অবজেক্টটি আপনার অ্যানিমেশনের সময়কালের হিসাব রাখে, যেমন অ্যানিমেশনটি কতক্ষণ ধরে চলছে এবং যে প্রপার্টিটিকে এটি অ্যানিমেট করছে তার বর্তমান মান কত।

ValueAnimator মধ্যে একটি TimeInterpolator থাকে, যা অ্যানিমেশন ইন্টারপোলেশন নির্ধারণ করে, এবং একটি TypeEvaluator , যা অ্যানিমেট করা হচ্ছে এমন প্রপার্টির জন্য মান কীভাবে গণনা করতে হবে তা নির্ধারণ করে। উদাহরণস্বরূপ, চিত্র ২-এ, ব্যবহৃত TimeInterpolator হবে AccelerateDecelerateInterpolator এবং TypeEvaluator হবে IntEvaluator

একটি অ্যানিমেশন শুরু করতে, একটি ValueAnimator তৈরি করুন এবং যে প্রপার্টিটি আপনি অ্যানিমেট করতে চান তার শুরুর ও শেষের মান, সেইসাথে অ্যানিমেশনের সময়কাল নির্ধারণ করুন। যখন আপনি start() কল করবেন, অ্যানিমেশনটি শুরু হবে। পুরো অ্যানিমেশন চলাকালীন, ValueAnimator টি অ্যানিমেশনের সময়কাল এবং কত সময় অতিবাহিত হয়েছে তার উপর ভিত্তি করে ০ থেকে ১-এর মধ্যে একটি অতিবাহিত ভগ্নাংশ গণনা করে। অতিবাহিত ভগ্নাংশটি বোঝায় যে অ্যানিমেশনটি কত শতাংশ সময় ধরে সম্পন্ন হয়েছে, যেখানে ০ মানে ০% এবং ১ মানে ১০০%। উদাহরণস্বরূপ, চিত্র ১-এ, t = ১০ ms-এ অতিবাহিত ভগ্নাংশ হবে .২৫, কারণ মোট সময়কাল হলো t = ৪০ ms।

যখন ValueAnimator একটি অতিবাহিত ভগ্নাংশ গণনা করা শেষ করে, তখন এটি একটি ইন্টারপোলেটেড ভগ্নাংশ গণনা করার জন্য বর্তমানে সেট করা TimeInterpolator কল করে। একটি ইন্টারপোলেটেড ভগ্নাংশ, অতিবাহিত ভগ্নাংশটিকে এমন একটি নতুন ভগ্নাংশে রূপান্তরিত করে যা সেট করা টাইম ইন্টারপোলেশনকে বিবেচনায় রাখে। উদাহরণস্বরূপ, চিত্র ২-এ, যেহেতু অ্যানিমেশনটি ধীরে ধীরে ত্বরান্বিত হয়, তাই t = ১০ মিলিসেকেন্ডে ইন্টারপোলেটেড ভগ্নাংশ, প্রায় .১৫, অতিবাহিত ভগ্নাংশ, .২৫, থেকে কম। চিত্র ১-এ, ইন্টারপোলেটেড ভগ্নাংশ সর্বদা অতিবাহিত ভগ্নাংশের সমান।

যখন ইন্টারপোলেটেড ভগ্নাংশটি গণনা করা হয়, তখন ValueAnimator উপযুক্ত TypeEvaluator কল করে, যা ইন্টারপোলেটেড ভগ্নাংশ, অ্যানিমেশনের শুরুর মান এবং শেষের মানের উপর ভিত্তি করে আপনি যে প্রপার্টিটি অ্যানিমেট করছেন তার মান গণনা করে। উদাহরণস্বরূপ, চিত্র ২-এ, t = ১০ ms সময়ে ইন্টারপোলেটেড ভগ্নাংশটি ছিল .১৫, সুতরাং সেই সময়ে প্রপার্টিটির মান হবে .১৫ × (৪০ - ০), বা ৬।

প্রপার্টি অ্যানিমেশন এবং ভিউ অ্যানিমেশনের মধ্যে পার্থক্য

ভিউ অ্যানিমেশন সিস্টেমটি শুধুমাত্র View অবজেক্টগুলোকে অ্যানিমেট করার ক্ষমতা প্রদান করে, তাই আপনি যদি View বহির্ভূত কোনো অবজেক্ট অ্যানিমেট করতে চান, তবে তার জন্য আপনাকে নিজস্ব কোড প্রয়োগ করতে হবে। ভিউ অ্যানিমেশন সিস্টেমটি এই দিক থেকেও সীমাবদ্ধ যে, এটি একটি View অবজেক্টের শুধুমাত্র কয়েকটি দিক অ্যানিমেট করার সুযোগ দেয়, যেমন—ভিউ-এর স্কেলিং এবং রোটেশন, কিন্তু ব্যাকগ্রাউন্ড কালার নয়।

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

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

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

এপিআই ওভারভিউ

প্রপার্টি অ্যানিমেশন সিস্টেমের বেশিরভাগ এপিআই আপনি android.animation এ খুঁজে পাবেন। যেহেতু ভিউ অ্যানিমেশন সিস্টেম ইতিমধ্যেই android.view.animation এ অনেক ইন্টারপোলেটর সংজ্ঞায়িত করে রেখেছে, তাই আপনি সেই ইন্টারপোলেটরগুলো প্রপার্টি অ্যানিমেশন সিস্টেমেও ব্যবহার করতে পারেন। নিচের সারণিগুলোতে প্রপার্টি অ্যানিমেশন সিস্টেমের প্রধান উপাদানগুলো বর্ণনা করা হয়েছে।

Animator ক্লাসটি অ্যানিমেশন তৈরির জন্য মৌলিক কাঠামো প্রদান করে। সাধারণত এই ক্লাসটি সরাসরি ব্যবহার করা হয় না, কারণ এটি কেবল ন্যূনতম কার্যকারিতা প্রদান করে যা ভ্যালু অ্যানিমেট করার সম্পূর্ণ সমর্থনের জন্য এক্সটেন্ড করতে হয়। নিম্নলিখিত সাবক্লাসগুলো Animator এক্সটেন্ড করে:

সারণি ১. অ্যানিমেটরগণ

শ্রেণী বর্ণনা
ValueAnimator প্রপার্টি অ্যানিমেশনের প্রধান টাইমিং ইঞ্জিন, যা অ্যানিমেট করা হবে এমন প্রপার্টির জন্য মানগুলোও গণনা করে। এতে অ্যানিমেশন মান গণনা করার সমস্ত মূল কার্যকারিতা রয়েছে এবং প্রতিটি অ্যানিমেশনের টাইমিংয়ের বিবরণ, কোনো অ্যানিমেশন পুনরাবৃত্তি হবে কিনা সেই সম্পর্কিত তথ্য, আপডেট ইভেন্ট গ্রহণকারী লিসেনার এবং মূল্যায়নের জন্য কাস্টম টাইপ সেট করার ক্ষমতা অন্তর্ভুক্ত থাকে। প্রপার্টি অ্যানিমেট করার দুটি অংশ রয়েছে: অ্যানিমেটেড মানগুলো গণনা করা এবং যে অবজেক্ট ও প্রপার্টি অ্যানিমেট করা হচ্ছে, তার উপর সেই মানগুলো সেট করা। ValueAnimator দ্বিতীয় অংশটি সম্পাদন করে না, তাই আপনাকে ValueAnimator দ্বারা গণনা করা মানগুলোর আপডেটের জন্য লিসেন করতে হবে এবং আপনার নিজস্ব লজিক দিয়ে যে অবজেক্টগুলো অ্যানিমেট করতে চান, সেগুলোকে পরিবর্তন করতে হবে। আরও তথ্যের জন্য 'ভ্যালুঅ্যানিমেটর দিয়ে অ্যানিমেট করা' সম্পর্কিত বিভাগটি দেখুন।
ObjectAnimator ValueAnimator এর একটি সাবক্লাস যা আপনাকে অ্যানিমেট করার জন্য একটি টার্গেট অবজেক্ট এবং অবজেক্ট প্রপার্টি সেট করতে দেয়। এই ক্লাসটি অ্যানিমেশনের জন্য একটি নতুন মান গণনা করার সময় সেই অনুযায়ী প্রপার্টিটি আপডেট করে। বেশিরভাগ সময় আপনি ObjectAnimator ব্যবহার করতে চাইবেন, কারণ এটি টার্গেট অবজেক্টের মান অ্যানিমেট করার প্রক্রিয়াকে অনেক সহজ করে তোলে। তবে, কখনও কখনও আপনি সরাসরি ValueAnimator ব্যবহার করতে চাইতে পারেন, কারণ ObjectAnimator কিছু অতিরিক্ত সীমাবদ্ধতা রয়েছে, যেমন টার্গেট অবজেক্টে নির্দিষ্ট অ্যাক্সেসর মেথড উপস্থিত থাকার প্রয়োজন।
AnimatorSet অ্যানিমেশনগুলোকে একসাথে গ্রুপ করার একটি ব্যবস্থা প্রদান করে, যাতে সেগুলো একে অপরের সাপেক্ষে চলে। আপনি অ্যানিমেশনগুলোকে একসাথে, ক্রমানুসারে, বা একটি নির্দিষ্ট বিলম্বের পরে চালানোর জন্য সেট করতে পারেন। আরও তথ্যের জন্য অ্যানিমেটর সেট ব্যবহার করে একাধিক অ্যানিমেশন কোরিওগ্রাফ করা সম্পর্কিত বিভাগটি দেখুন।

ইভ্যালুয়েটররা প্রপার্টি অ্যানিমেশন সিস্টেমকে বলে দেয় যে একটি নির্দিষ্ট প্রপার্টির জন্য মানগুলো কীভাবে গণনা করতে হবে। এরা একটি Animator ক্লাস দ্বারা প্রদত্ত টাইমিং ডেটা, অ্যানিমেশনের শুরু এবং শেষের মান গ্রহণ করে এবং এই ডেটার উপর ভিত্তি করে প্রপার্টিটির অ্যানিমেটেড মানগুলো গণনা করে। প্রপার্টি অ্যানিমেশন সিস্টেম নিম্নলিখিত ইভ্যালুয়েটরগুলো সরবরাহ করে:

সারণি ২. মূল্যায়নকারীগণ

ক্লাস/ইন্টারফেস বর্ণনা
IntEvaluator int প্রপার্টিগুলোর মান গণনা করার জন্য ডিফল্ট ইভ্যালুয়েটর।
FloatEvaluator float প্রপার্টিগুলোর মান গণনা করার জন্য ডিফল্ট ইভ্যালুয়েটর।
ArgbEvaluator যেসব রঙের বৈশিষ্ট্য হেক্সাডেসিমাল মান হিসাবে উপস্থাপিত হয়, সেগুলোর মান গণনা করার জন্য ডিফল্ট মূল্যায়নকারী।
TypeEvaluator একটি ইন্টারফেস যা আপনাকে আপনার নিজস্ব ইভ্যালুয়েটর তৈরি করার সুযোগ দেয়। আপনি যদি এমন কোনো অবজেক্ট প্রপার্টি অ্যানিমেট করেন যা int , float , বা color নয় , তবে অবজেক্ট প্রপার্টির অ্যানিমেটেড মানগুলো কীভাবে গণনা করা হবে তা নির্দিষ্ট করার জন্য আপনাকে অবশ্যই TypeEvaluator ইন্টারফেসটি ইমপ্লিমেন্ট করতে হবে। আপনি int , float , এবং color মানগুলোর জন্যও একটি কাস্টম TypeEvaluator নির্দিষ্ট করতে পারেন, যদি আপনি ডিফল্ট আচরণের চেয়ে ভিন্নভাবে সেই টাইপগুলো প্রসেস করতে চান। একটি কাস্টম ইভ্যালুয়েটর কীভাবে লিখতে হয় সে সম্পর্কে আরও তথ্যের জন্য "Using a TypeEvaluator" বিভাগটি দেখুন।

একটি টাইম ইন্টারপোলেটর নির্ধারণ করে যে, একটি অ্যানিমেশনের নির্দিষ্ট মানগুলো সময়ের ফাংশন হিসেবে কীভাবে গণনা করা হবে। উদাহরণস্বরূপ, আপনি পুরো অ্যানিমেশন জুড়ে অ্যানিমেশনগুলোকে রৈখিকভাবে (linearly) ঘটার জন্য নির্দিষ্ট করতে পারেন, যার অর্থ হলো অ্যানিমেশনটি পুরো সময় ধরে সমানভাবে চলবে; অথবা আপনি অরৈখিক সময় (non-linear time) ব্যবহার করার জন্য নির্দিষ্ট করতে পারেন, যেমন—অ্যানিমেশনের শুরুতে গতি বাড়ানো এবং শেষে গতি কমানো। সারণি ৩-এ android.view.animation এর অন্তর্ভুক্ত ইন্টারপোলেটরগুলো বর্ণনা করা হয়েছে। যদি প্রদত্ত কোনো ইন্টারপোলেটরই আপনার প্রয়োজন মেটাতে না পারে, তবে TimeInterpolator ইন্টারফেসটি ইমপ্লিমেন্ট করুন এবং আপনার নিজের ইন্টারপোলেটর তৈরি করুন। কীভাবে একটি কাস্টম ইন্টারপোলেটর লিখতে হয় সে সম্পর্কে আরও তথ্যের জন্য "Using interpolators" দেখুন।

সারণি ৩. ইন্টারপোলেটর

ক্লাস/ইন্টারফেস বর্ণনা
AccelerateDecelerateInterpolator এমন একটি ইন্টারপোলেটর যার পরিবর্তনের হার শুরুতে ও শেষে ধীরগতিতে শুরু হলেও মাঝপথে ত্বরান্বিত হয়।
AccelerateInterpolator এমন একটি ইন্টারপোলেটর যার পরিবর্তনের হার প্রথমে ধীর থাকে এবং পরে ত্বরান্বিত হয়।
AnticipateInterpolator এমন একটি ইন্টারপোলেটর যার পরিবর্তন প্রথমে পেছন থেকে শুরু হয়ে তারপর সামনের দিকে ধাবিত হয়।
AnticipateOvershootInterpolator একটি ইন্টারপোলেটর যার পরিবর্তন পেছন থেকে শুরু হয়ে, হঠাৎ সামনের দিকে এগিয়ে যায় এবং লক্ষ্যমাত্রাকে অতিক্রম করে, তারপর অবশেষে চূড়ান্ত মানে ফিরে আসে।
BounceInterpolator এমন একটি ইন্টারপোলেটর যার পরিবর্তন শেষে বাউন্স করে।
CycleInterpolator একটি ইন্টারপোলেটর যার অ্যানিমেশন একটি নির্দিষ্ট সংখ্যক চক্রের জন্য পুনরাবৃত্ত হয়।
DecelerateInterpolator এমন একটি ইন্টারপোলেটর যার পরিবর্তনের হার প্রথমে দ্রুত থাকে এবং পরে কমে যায়।
LinearInterpolator এমন একটি ইন্টারপোলেটর যার পরিবর্তনের হার ধ্রুবক।
OvershootInterpolator একটি ইন্টারপোলেটর যার পরিবর্তন দ্রুত সামনে এগিয়ে গিয়ে শেষ মানটিকে অতিক্রম করে এবং তারপর ফিরে আসে।
TimeInterpolator একটি ইন্টারফেস যা আপনাকে আপনার নিজস্ব ইন্টারপোলেটর বাস্তবায়ন করার সুযোগ দেয়।

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

ValueAnimator ক্লাসটি আপনাকে int , float , বা color ভ্যালুর একটি সেট নির্দিষ্ট করে দিয়ে একটি অ্যানিমেশনের সময়কাল জুড়ে কোনো নির্দিষ্ট ধরনের ভ্যালুকে অ্যানিমেট করতে দেয়। আপনি এর ফ্যাক্টরি মেথডগুলোর (যেমন: ofInt() , ofFloat() , বা ofObject() যেকোনো একটি কল করে একটি ValueAnimator পেতে পারেন। উদাহরণস্বরূপ:

কোটলিন

ValueAnimator.ofFloat(0f, 100f).apply {
    duration = 1000
    start()
}

জাভা

ValueAnimator animation = ValueAnimator.ofFloat(0f, 100f);
animation.setDuration(1000);
animation.start();

এই কোডে, start() মেথডটি রান করার সময় ValueAnimator টি 1000 ms সময়কালের জন্য 0 থেকে 100-এর মধ্যে অ্যানিমেশনের মান গণনা করা শুরু করে।

এছাড়াও আপনি নিম্নলিখিত উপায়ে অ্যানিমেট করার জন্য একটি কাস্টম টাইপ নির্দিষ্ট করতে পারেন:

কোটলিন

ValueAnimator.ofObject(MyTypeEvaluator(), startPropertyValue, endPropertyValue).apply {
    duration = 1000
    start()
}

জাভা

ValueAnimator animation = ValueAnimator.ofObject(new MyTypeEvaluator(), startPropertyValue, endPropertyValue);
animation.setDuration(1000);
animation.start();

এই কোডে, start() মেথডটি রান করার সময়, ValueAnimator টি MyTypeEvaluator দ্বারা সরবরাহকৃত লজিক ব্যবহার করে startPropertyValue এবং endPropertyValue মধ্যবর্তী অ্যানিমেশনের মানগুলো ১০০০ মিলিসেকেন্ড সময় ধরে গণনা করা শুরু করে।

নিচের কোডে দেখানো অনুযায়ী, ValueAnimator অবজেক্টে একটি AnimatorUpdateListener যোগ করে আপনি অ্যানিমেশনের মানগুলো ব্যবহার করতে পারেন:

কোটলিন

ValueAnimator.ofObject(...).apply {
    ...
    addUpdateListener { updatedAnimation ->
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        textView.translationX = updatedAnimation.animatedValue as Float
    }
    ...
}

জাভা

animation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        // You can use the animated value in a property that uses the
        // same type as the animation. In this case, you can use the
        // float value in the translationX property.
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});

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

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

ObjectAnimator হলো ValueAnimator এর (যা পূর্ববর্তী বিভাগে আলোচনা করা হয়েছে) একটি সাবক্লাস। এটি ValueAnimator এর টাইমিং ইঞ্জিন ও ভ্যালু কম্পিউটেশনের সাথে একটি টার্গেট অবজেক্টের নামযুক্ত প্রপার্টিকে অ্যানিমেট করার ক্ষমতাকে একত্রিত করে। এর ফলে যেকোনো অবজেক্টকে অ্যানিমেট করা অনেক সহজ হয়ে যায়, কারণ আপনাকে আর ValueAnimator.AnimatorUpdateListener ইমপ্লিমেন্ট করতে হয় না, যেহেতু অ্যানিমেটেড প্রপার্টিটি স্বয়ংক্রিয়ভাবে আপডেট হয়ে যায়।

একটি ObjectAnimator ইনস্ট্যানশিয়েট করার পদ্ধতি একটি ValueAnimator মতোই, তবে এক্ষেত্রে আপনাকে অবজেক্টটি এবং সেই অবজেক্টের প্রপার্টির নাম (স্ট্রিং হিসেবে) উল্লেখ করতে হয়, সাথে যে ভ্যালুগুলোর মধ্যে অ্যানিমেট করতে চান সেগুলোও দিতে হয়:

কোটলিন

ObjectAnimator.ofFloat(textView, "translationX", 100f).apply {
    duration = 1000
    start()
}

জাভা

ObjectAnimator animation = ObjectAnimator.ofFloat(textView, "translationX", 100f);
animation.setDuration(1000);
animation.start();

ObjectAnimator প্রোপার্টিগুলো সঠিকভাবে আপডেট করার জন্য, আপনাকে নিম্নলিখিত কাজগুলো করতে হবে:

  • আপনি যে অবজেক্ট প্রপার্টিটি অ্যানিমেট করছেন, সেটিতে set<PropertyName>() ফর্ম্যাটে একটি সেটার ফাংশন (ক্যামেল কেসে) অবশ্যই থাকতে হবে। যেহেতু ObjectAnimator অ্যানিমেশনের সময় স্বয়ংক্রিয়ভাবে প্রপার্টিটি আপডেট করে, তাই এই সেটার মেথডের মাধ্যমে প্রপার্টিটি অ্যাক্সেস করার সুবিধা তার থাকতে হবে। উদাহরণস্বরূপ, যদি প্রপার্টির নাম foo হয়, তাহলে আপনার একটি setFoo() মেথড থাকা প্রয়োজন। যদি এই সেটার মেথডটি না থাকে, তবে আপনার কাছে তিনটি বিকল্প রয়েছে:
    • আপনার অধিকার থাকলে ক্লাসে সেটার মেথডটি যোগ করুন।
    • এমন একটি র‍্যাপার ক্লাস ব্যবহার করুন যা পরিবর্তন করার অধিকার আপনার আছে এবং সেই র‍্যাপারটি একটি বৈধ সেটার মেথডের মাধ্যমে ভ্যালুটি গ্রহণ করে মূল অবজেক্টে ফরোয়ার্ড করবে।
    • এর পরিবর্তে ValueAnimator ব্যবহার করুন।
  • যদি আপনি ObjectAnimator ফ্যাক্টরি মেথডগুলোর কোনো একটিতে values... প্যারামিটারের জন্য শুধুমাত্র একটি মান নির্দিষ্ট করেন, তবে ধরে নেওয়া হয় যে সেটিই অ্যানিমেশনের শেষ মান। সুতরাং, আপনি যে অবজেক্ট প্রপার্টিটি অ্যানিমেট করছেন, সেটিতে অবশ্যই একটি গেটার ফাংশন থাকতে হবে যা অ্যানিমেশনের শুরুর মান পেতে ব্যবহৃত হয়। গেটার ফাংশনটি অবশ্যই get<PropertyName>() আকারে হতে হবে। উদাহরণস্বরূপ, যদি প্রপার্টির নাম foo হয়, তাহলে আপনার একটি getFoo() মেথড থাকতে হবে।
  • আপনি যে প্রপার্টিটি অ্যানিমেট করছেন, তার গেটার (প্রয়োজন হলে) এবং সেটার মেথডগুলোকে অবশ্যই ObjectAnimator এ আপনার নির্দিষ্ট করা শুরুর এবং শেষের মানের মতো একই টাইপের উপর কাজ করতে হবে। উদাহরণস্বরূপ, যদি আপনি নিম্নলিখিত ObjectAnimator তৈরি করেন, তাহলে আপনার অবশ্যই targetObject.setPropName(float) এবং targetObject.getPropName() থাকতে হবে:
    ObjectAnimator.ofFloat(targetObject, "propName", 1f)
  • আপনি কোন প্রপার্টি বা অবজেক্ট অ্যানিমেট করছেন তার উপর নির্ভর করে, আপডেট করা অ্যানিমেটেড ভ্যালু দিয়ে স্ক্রিনকে পুনরায় আঁকতে বাধ্য করার জন্য আপনাকে একটি View-এর invalidate() মেথড কল করতে হতে পারে। আপনি এটি onAnimationUpdate() কলব্যাকে করে থাকেন। উদাহরণস্বরূপ, একটি Drawable অবজেক্টের color প্রপার্টি অ্যানিমেট করলে স্ক্রিনে কেবল তখনই আপডেট আসে যখন সেই অবজেক্টটি নিজেকে পুনরায় আঁকে। View-এর সমস্ত প্রপার্টি সেটার, যেমন setAlpha() এবং setTranslationX() , View-কে সঠিকভাবে invalidate করে, তাই নতুন ভ্যালু দিয়ে এই মেথডগুলো কল করার সময় আপনাকে View-কে invalidate করার প্রয়োজন নেই। লিসেনার সম্পর্কে আরও তথ্যের জন্য, অ্যানিমেশন লিসেনার সম্পর্কিত বিভাগটি দেখুন।

একটি AnimatorSet ব্যবহার করে একাধিক অ্যানিমেশন কোরিওগ্রাফ করুন।

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

নিম্নলিখিত কোড স্নিপেটটি নিম্নলিখিত Animator অবজেক্টগুলিকে নিম্নলিখিত পদ্ধতিতে প্লে করে:

  1. bounceAnim বাজায়।
  2. একই সাথে squashAnim1 , squashAnim2 , stretchAnim1 এবং stretchAnim2 প্লে করে।
  3. bounceBackAnim বাজায়।
  4. fadeAnim প্লে করে।

কোটলিন

val bouncer = AnimatorSet().apply {
    play(bounceAnim).before(squashAnim1)
    play(squashAnim1).with(squashAnim2)
    play(squashAnim1).with(stretchAnim1)
    play(squashAnim1).with(stretchAnim2)
    play(bounceBackAnim).after(stretchAnim2)
}
val fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply {
    duration = 250
}
AnimatorSet().apply {
    play(bouncer).before(fadeAnim)
    start()
}

জাভা

AnimatorSet bouncer = new AnimatorSet();
bouncer.play(bounceAnim).before(squashAnim1);
bouncer.play(squashAnim1).with(squashAnim2);
bouncer.play(squashAnim1).with(stretchAnim1);
bouncer.play(squashAnim1).with(stretchAnim2);
bouncer.play(bounceBackAnim).after(stretchAnim2);
ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.play(bouncer).before(fadeAnim);
animatorSet.start();

অ্যানিমেশন শ্রোতা

নিচে বর্ণিত লিসেনারগুলোর সাহায্যে আপনি একটি অ্যানিমেশন চলাকালীন গুরুত্বপূর্ণ ঘটনাগুলো শুনতে পারেন।

  • Animator.AnimatorListener
    • onAnimationStart() - অ্যানিমেশন শুরু হলে এই ফাংশনটি কল করা হয়।
    • onAnimationEnd() - অ্যানিমেশন শেষ হলে এই ফাংশনটি কল করা হয়।
    • onAnimationRepeat() - যখন অ্যানিমেশনটি পুনরাবৃত্তি হয় তখন এটি কল করা হয়।
    • onAnimationCancel() - অ্যানিমেশন বাতিল করা হলে এই ফাংশনটি কল করা হয়। একটি বাতিল হওয়া অ্যানিমেশন, কীভাবে শেষ করা হয়েছে তা নির্বিশেষে, onAnimationEnd() কল করে।
  • ValueAnimator.AnimatorUpdateListener
    • onAnimationUpdate() - অ্যানিমেশনের প্রতিটি ফ্রেমে কল করা হয়। অ্যানিমেশন চলাকালীন ValueAnimator দ্বারা তৈরি গণনাকৃত মানগুলি ব্যবহার করতে এই ইভেন্টটি শুনুন। মানটি ব্যবহার করার জন্য, ইভেন্টে পাঠানো ValueAnimator অবজেক্টের getAnimatedValue() মেথড দিয়ে বর্তমান অ্যানিমেটেড মানটি কোয়েরি করুন। আপনি যদি ValueAnimator ব্যবহার করেন তবে এই লিসেনারটি ইমপ্লিমেন্ট করা আবশ্যক।

      আপনি কোন প্রপার্টি বা অবজেক্ট অ্যানিমেট করছেন তার উপর নির্ভর করে, স্ক্রিনের ঐ অংশটিকে নতুন অ্যানিমেটেড মান দিয়ে পুনরায় আঁকতে বাধ্য করার জন্য আপনাকে একটি ভিউ-এর উপর invalidate() কল করতে হতে পারে। উদাহরণস্বরূপ, একটি Drawable অবজেক্টের color প্রপার্টি অ্যানিমেট করলে স্ক্রিনে কেবল তখনই আপডেট হয় যখন সেই অবজেক্টটি নিজেকে পুনরায় আঁকে। ভিউ-এর সমস্ত প্রপার্টি সেটার, যেমন setAlpha() এবং setTranslationX() , ভিউ-কে সঠিকভাবে invalidate করে, তাই নতুন মান দিয়ে এই মেথডগুলো কল করার সময় আপনাকে ভিউ-কে invalidate করার প্রয়োজন নেই।

আপনি যদি Animator.AnimatorListener ইন্টারফেসের সমস্ত মেথড ইমপ্লিমেন্ট করতে না চান, তাহলে Animator.AnimatorListener ইন্টারফেসটি ইমপ্লিমেন্ট করার পরিবর্তে AnimatorListenerAdapter ক্লাসটি এক্সটেন্ড করতে পারেন। AnimatorListenerAdapter ক্লাসটি মেথডগুলোর এম্পটি ইমপ্লিমেন্টেশন প্রদান করে, যেগুলো আপনি ওভাররাইড করার জন্য বেছে নিতে পারেন।

উদাহরণস্বরূপ, নিম্নলিখিত কোড স্নিপেটটি শুধুমাত্র onAnimationEnd() কলব্যাকের জন্য একটি AnimatorListenerAdapter তৈরি করে:

কোটলিন

ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f).apply {
    duration = 250
    addListener(object : AnimatorListenerAdapter() {
        override fun onAnimationEnd(animation: Animator) {
            balls.remove((animation as ObjectAnimator).target)
        }
    })
}

জাভা

ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
fadeAnim.setDuration(250);
fadeAnim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animation) {
    balls.remove(((ObjectAnimator)animation).getTarget());
}

ViewGroup অবজেক্টগুলিতে লেআউট পরিবর্তনগুলি অ্যানিমেট করুন

প্রপার্টি অ্যানিমেশন সিস্টেমটি ViewGroup অবজেক্টের পরিবর্তনগুলোকে অ্যানিমেট করার সক্ষমতা প্রদানের পাশাপাশি View অবজেক্টগুলোকেও সহজে অ্যানিমেট করার একটি উপায় সরবরাহ করে।

আপনি LayoutTransition ক্লাস ব্যবহার করে একটি ViewGroup-এর মধ্যে লেআউটের পরিবর্তনগুলোকে অ্যানিমেট করতে পারেন। একটি ViewGroup-এর ভেতরের ভিউগুলো আবির্ভূত ও অদৃশ্য হওয়ার অ্যানিমেশনের মধ্য দিয়ে যেতে পারে, যখন আপনি সেগুলোকে ViewGroup-এ যোগ করেন বা সরিয়ে দেন, অথবা যখন আপনি কোনো ভিউ-এর setVisibility() মেথডকে VISIBLE , INVISIBLE , বা GONE দিয়ে কল করেন। আপনি যখন ভিউ যোগ করেন বা সরিয়ে দেন, তখন ViewGroup-এর বাকি ভিউগুলোও তাদের নতুন অবস্থানে অ্যানিমেট হয়ে যেতে পারে। আপনি একটি LayoutTransition অবজেক্টে নিম্নলিখিত অ্যানিমেশনগুলো সংজ্ঞায়িত করতে পারেন setAnimator() কল করে এবং নিম্নলিখিত LayoutTransition কনস্ট্যান্টগুলোর মধ্যে একটিসহ একটি Animator অবজেক্ট পাস করার মাধ্যমে:

  • APPEARING - একটি ফ্ল্যাগ যা কন্টেইনারে প্রদর্শিত হতে থাকা আইটেমগুলোর উপর চালিত অ্যানিমেশনকে নির্দেশ করে।
  • CHANGE_APPEARING - একটি ফ্ল্যাগ যা কন্টেইনারে নতুন আইটেম যুক্ত হওয়ার কারণে পরিবর্তিত হওয়া আইটেমগুলোর উপর চালিত অ্যানিমেশনকে নির্দেশ করে।
  • DISAPPEARING - একটি ফ্ল্যাগ যা কন্টেইনার থেকে অদৃশ্য হয়ে যাওয়া আইটেমগুলোর উপর চালিত অ্যানিমেশনকে নির্দেশ করে।
  • CHANGE_DISAPPEARING - একটি ফ্ল্যাগ যা সেই অ্যানিমেশনকে নির্দেশ করে, যা কন্টেইনার থেকে কোনো আইটেম অদৃশ্য হয়ে যাওয়ার কারণে পরিবর্তিত হওয়া আইটেমগুলোর উপর চলে।

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

ViewGroup-এর জন্য android:animateLayoutchanges অ্যাট্রিবিউটটি true সেট করতে নিম্নলিখিত পদক্ষেপগুলি অনুসরণ করুন:

<LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:id="@+id/verticalContainer"
    android:animateLayoutChanges="true" />

এই অ্যাট্রিবিউটটি 'true' সেট করলে, ViewGroup-এ নতুন ভিউ যোগ করা বা সরানো হলে এবং ViewGroup-এর বাকি ভিউগুলোও স্বয়ংক্রিয়ভাবে অ্যানিমেট হয়।

StateListAnimator ব্যবহার করে ভিউয়ের অবস্থার পরিবর্তন অ্যানিমেট করুন

StateListAnimator ক্লাসটি আপনাকে এমন অ্যানিমেটর সংজ্ঞায়িত করার সুযোগ দেয় যা কোনো ভিউ-এর অবস্থা পরিবর্তিত হলে চলে। এই অবজেক্টটি একটি Animator অবজেক্টের র‍্যাপার হিসেবে কাজ করে এবং নির্দিষ্ট ভিউ-এর অবস্থা (যেমন "pressed" বা "focused") পরিবর্তিত হলেই সেই অ্যানিমেশনটিকে কল করে।

StateListAnimator একটি XML রিসোর্সে একটি রুট <selector> এলিমেন্ট এবং তার চাইল্ড <item> এলিমেন্টগুলোর মাধ্যমে সংজ্ঞায়িত করা যেতে পারে, যেখানে প্রতিটি <item> এলিমেন্ট StateListAnimator ক্লাস দ্বারা সংজ্ঞায়িত একটি ভিন্ন ভিউ স্টেট নির্দিষ্ট করে। প্রতিটি <item> একটি প্রপার্টি 'অ্যানিমেশন সেট'- এর সংজ্ঞা থাকে।

উদাহরণস্বরূপ, নিম্নলিখিত ফাইলটি একটি স্টেট লিস্ট অ্যানিমেটর তৈরি করে যা চাপ দিলে ভিউটির x এবং y স্কেল পরিবর্তন করে:

res/xml/animate_scale.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- the pressed state; increase x and y size to 150% -->
    <item android:state_pressed="true">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1.5"
                android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1.5"
                android:valueType="floatType"/>
        </set>
    </item>
    <!-- the default, non-pressed state; set x and y size to 100% -->
    <item android:state_pressed="false">
        <set>
            <objectAnimator android:propertyName="scaleX"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1"
                android:valueType="floatType"/>
            <objectAnimator android:propertyName="scaleY"
                android:duration="@android:integer/config_shortAnimTime"
                android:valueTo="1"
                android:valueType="floatType"/>
        </set>
    </item>
</selector>

কোনো ভিউতে স্টেট লিস্ট অ্যানিমেটর সংযুক্ত করতে, নিচের মতো করে android:stateListAnimator অ্যাট্রিবিউটটি যোগ করুন:

<Button android:stateListAnimator="@xml/animate_scale"
        ... />

এখন এই বাটনটির অবস্থা পরিবর্তন হলে animate_scale.xml এ সংজ্ঞায়িত অ্যানিমেশনগুলো ব্যবহৃত হয়।

অথবা এর পরিবর্তে আপনার কোডে কোনো ভিউতে একটি স্টেট লিস্ট অ্যানিমেটর অ্যাসাইন করতে, AnimatorInflater.loadStateListAnimator() মেথডটি ব্যবহার করুন এবং View.setStateListAnimator() মেথডের মাধ্যমে অ্যানিমেটরটিকে আপনার ভিউতে অ্যাসাইন করুন।

অথবা ভিউ-এর প্রোপার্টিগুলো অ্যানিমেট করার পরিবর্তে, আপনি AnimatedStateListDrawable ব্যবহার করে স্টেট পরিবর্তনের মাঝে একটি ড্রয়েবল অ্যানিমেশন চালাতে পারেন। অ্যান্ড্রয়েড ৫.০-এর কিছু সিস্টেম উইজেট ডিফল্টভাবে এই অ্যানিমেশনগুলো ব্যবহার করে। নিচের উদাহরণটিতে দেখানো হয়েছে কিভাবে একটি AnimatedStateListDrawable XML রিসোর্স হিসেবে সংজ্ঞায়িত করতে হয়:

<!-- res/drawable/myanimstatedrawable.xml -->
<animated-selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <!-- provide a different drawable for each state-->
    <item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
        android:state_pressed="true"/>
    <item android:id="@+id/focused" android:drawable="@drawable/drawableF"
        android:state_focused="true"/>
    <item android:id="@id/default"
        android:drawable="@drawable/drawableD"/>

    <!-- specify a transition -->
    <transition android:fromId="@+id/default" android:toId="@+id/pressed">
        <animation-list>
            <item android:duration="15" android:drawable="@drawable/dt1"/>
            <item android:duration="15" android:drawable="@drawable/dt2"/>
            ...
        </animation-list>
    </transition>
    ...
</animated-selector>

একটি TypeEvaluator ব্যবহার করুন

আপনি যদি অ্যান্ড্রয়েড সিস্টেমের কাছে অজানা কোনো টাইপকে অ্যানিমেট করতে চান, তাহলে TypeEvaluator ইন্টারফেসটি ইমপ্লিমেন্ট করে নিজের ইভ্যালুয়েটর তৈরি করতে পারেন। অ্যান্ড্রয়েড সিস্টেমের কাছে পরিচিত টাইপগুলো হলো int , float বা color, যেগুলোকে IntEvaluator , FloatEvaluator এবং ArgbEvaluator টাইপ ইভ্যালুয়েটরগুলো সাপোর্ট করে।

TypeEvaluator ইন্টারফেসে ইমপ্লিমেন্ট করার জন্য শুধুমাত্র একটিই মেথড আছে, সেটি হলো evaluate() মেথড। এটি আপনার ব্যবহৃত অ্যানিমেটরকে অ্যানিমেশনের বর্তমান পর্যায়ে আপনার অ্যানিমেটেড প্রপার্টির জন্য একটি উপযুক্ত মান রিটার্ন করতে সাহায্য করে। FloatEvaluator ক্লাসটি দেখায় যে এটি কীভাবে করতে হয়:

কোটলিন

private class FloatEvaluator : TypeEvaluator<Any> {

    override fun evaluate(fraction: Float, startValue: Any, endValue: Any): Any {
        return (startValue as Number).toFloat().let { startFloat ->
            startFloat + fraction * ((endValue as Number).toFloat() - startFloat)
        }
    }

}

জাভা

public class FloatEvaluator implements TypeEvaluator {

    public Object evaluate(float fraction, Object startValue, Object endValue) {
        float startFloat = ((Number) startValue).floatValue();
        return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
    }
}

দ্রষ্টব্য: যখন ValueAnimator (বা ObjectAnimator ) চলে, তখন এটি অ্যানিমেশনের বর্তমান অতিবাহিত ভগ্নাংশ (০ থেকে ১-এর মধ্যে একটি মান) গণনা করে এবং তারপরে আপনার ব্যবহৃত ইন্টারপোলেটরের উপর নির্ভর করে সেটির একটি ইন্টারপোলেটেড সংস্করণ গণনা করে। এই ইন্টারপোলেটেড ভগ্নাংশটিই আপনার TypeEvaluator fraction প্যারামিটারের মাধ্যমে গ্রহণ করে, তাই অ্যানিমেটেড মান গণনা করার সময় আপনাকে ইন্টারপোলেটরটি বিবেচনায় নিতে হয় না।

ইন্টারপোলেটর ব্যবহার করুন

একটি ইন্টারপোলেটর নির্ধারণ করে যে, একটি অ্যানিমেশনের নির্দিষ্ট মানগুলো সময়ের ফাংশন হিসেবে কীভাবে গণনা করা হবে। উদাহরণস্বরূপ, আপনি পুরো অ্যানিমেশন জুড়ে অ্যানিমেশনটিকে রৈখিকভাবে ঘটার জন্য নির্দিষ্ট করতে পারেন, যার অর্থ হলো অ্যানিমেশনটি সম্পূর্ণ সময় ধরে সমানভাবে চলবে; অথবা আপনি অ্যানিমেশনটিকে অরৈখিক সময় ব্যবহার করার জন্য নির্দিষ্ট করতে পারেন, যেমন—অ্যানিমেশনের শুরুতে বা শেষে ত্বরণ বা মন্দন ব্যবহার করা।

অ্যানিমেশন সিস্টেমের ইন্টারপোলেটরগুলো অ্যানিমেটরদের কাছ থেকে একটি ভগ্নাংশ গ্রহণ করে, যা অ্যানিমেশনটির অতিবাহিত সময়কে নির্দেশ করে। ইন্টারপোলেটরগুলো যে ধরনের অ্যানিমেশন প্রদান করতে চায়, তার সাথে সামঞ্জস্য রেখে এই ভগ্নাংশটিকে পরিবর্তন করে। অ্যান্ড্রয়েড সিস্টেম android.view.animation package কিছু সাধারণ ইন্টারপোলেটর সরবরাহ করে। যদি এগুলোর কোনোটিই আপনার প্রয়োজন মেটাতে না পারে, তবে আপনি TimeInterpolator ইন্টারফেসটি ইমপ্লিমেন্ট করে নিজের ইন্টারপোলেটর তৈরি করতে পারেন।

উদাহরণস্বরূপ, ডিফল্ট ইন্টারপোলেটর AccelerateDecelerateInterpolator এবং LinearInterpolator কীভাবে ইন্টারপোলেটেড ভগ্নাংশ গণনা করে, তা নিচে তুলনা করা হলো। অতিবাহিত ভগ্নাংশের উপর LinearInterpolator কোনো প্রভাব নেই। AccelerateDecelerateInterpolator অ্যানিমেশনের মধ্যে গতি বাড়ায় এবং এর বাইরে গতি কমায়। নিম্নলিখিত মেথডগুলো এই ইন্টারপোলেটরগুলোর লজিক নির্ধারণ করে:

ত্বরণ মন্দন ইন্টারপোলেটর

কোটলিন

override fun getInterpolation(input: Float): Float =
        (Math.cos((input + 1) * Math.PI) / 2.0f).toFloat() + 0.5f

জাভা

@Override
public float getInterpolation(float input) {
    return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
}

লিনিয়ার ইন্টারপোলেটর

কোটলিন

override fun getInterpolation(input: Float): Float = input

জাভা

@Override
public float getInterpolation(float input) {
    return input;
}

নিম্নলিখিত সারণিতে ১০০০ মিলিসেকেন্ড স্থায়ী একটি অ্যানিমেশনের জন্য এই ইন্টারপোলেটরগুলো দ্বারা গণনাকৃত আনুমানিক মানগুলো উপস্থাপন করা হয়েছে:

মিলিসেকেন্ড অতিবাহিত হয়েছে অতিক্রান্ত ভগ্নাংশ/অন্তর্বর্তী ভগ্নাংশ (রৈখিক) ইন্টারপোলেটেড ভগ্নাংশ (ত্বরণ/মন্থরকরণ)
২০০ .২ .1
৪০০ .৪ .৩৪৫
৬০০ .৬ .654
৮০০ .8 .৯
১০০০

সারণিতে যেমন দেখানো হয়েছে, LinearInterpolator একই গতিতে মান পরিবর্তন করে, যা প্রতি ২০০ মিলিসেকেন্ড অতিবাহিত হওয়ার সাথে সাথে ০.২ হারে ঘটে। AccelerateDecelerateInterpolator ২০০ মিলিসেকেন্ড থেকে ৬০০ মিলিসেকেন্ডের মধ্যে LinearInterpolator চেয়ে দ্রুত এবং ৬০০ মিলিসেকেন্ড থেকে ১০০০ মিলিসেকেন্ডের মধ্যে ধীর গতিতে মান পরিবর্তন করে।

কীফ্রেম নির্দিষ্ট করুন

একটি Keyframe অবজেক্ট একটি সময়/মান জোড়া নিয়ে গঠিত, যা আপনাকে একটি অ্যানিমেশনের নির্দিষ্ট সময়ে একটি নির্দিষ্ট অবস্থা নির্ধারণ করতে দেয়। প্রতিটি কীফ্রেমের নিজস্ব ইন্টারপোলেটরও থাকতে পারে, যা পূর্ববর্তী কীফ্রেমের সময় এবং এই কীফ্রেমের সময়ের মধ্যবর্তী ব্যবধানে অ্যানিমেশনের আচরণ নিয়ন্ত্রণ করে।

একটি Keyframe অবজেক্ট ইনস্ট্যানশিয়েট করতে, আপনাকে অবশ্যই ofInt() , ofFloat() , বা ofObject() ফ্যাক্টরি মেথডগুলোর মধ্যে যেকোনো একটি ব্যবহার করে উপযুক্ত ধরনের Keyframe পেতে হবে। এরপর, একটি PropertyValuesHolder অবজেক্ট পাওয়ার জন্য আপনাকে ofKeyframe() ফ্যাক্টরি মেথডটি কল করতে হবে। অবজেক্টটি পেয়ে গেলে, আপনি PropertyValuesHolder অবজেক্ট এবং যে অবজেক্টটি অ্যানিমেট করতে চান তা পাস করে একটি অ্যানিমেটর পেতে পারেন। নিচের কোড স্নিপেটটি দেখায় কিভাবে এটি করতে হয়:

কোটলিন

val kf0 = Keyframe.ofFloat(0f, 0f)
val kf1 = Keyframe.ofFloat(.5f, 360f)
val kf2 = Keyframe.ofFloat(1f, 0f)
val pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2)
ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation).apply {
    duration = 5000
}

জাভা

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation);
rotationAnim.setDuration(5000);

দৃশ্যগুলিকে অ্যানিমেট করুন

প্রপার্টি অ্যানিমেশন সিস্টেম ভিউ অবজেক্টের সুবিন্যস্ত অ্যানিমেশনের সুযোগ দেয় এবং ভিউ অ্যানিমেশন সিস্টেমের তুলনায় কয়েকটি সুবিধা প্রদান করে। ভিউ অ্যানিমেশন সিস্টেম ভিউ অবজেক্টগুলোকে তাদের অঙ্কনের পদ্ধতি পরিবর্তন করে রূপান্তর করত। এই কাজটি প্রতিটি ভিউ-এর কন্টেইনারে সম্পন্ন হতো, কারণ ভিউটির নিজের পরিবর্তন করার মতো কোনো প্রপার্টি ছিল না। এর ফলে ভিউটি অ্যানিমেটেড হলেও, ভিউ অবজেক্টটির নিজের মধ্যে কোনো পরিবর্তন ঘটত না। এতে এমন আচরণ দেখা যেত যে, স্ক্রিনের অন্য কোনো স্থানে অঙ্কন করা হলেও অবজেক্টটি তার মূল অবস্থানেই থেকে যেত। অ্যান্ড্রয়েড ৩.০-তে এই অসুবিধাটি দূর করার জন্য নতুন প্রপার্টি এবং সংশ্লিষ্ট গেটার ও সেটার মেথড যুক্ত করা হয়।

প্রপার্টি অ্যানিমেশন সিস্টেম, ভিউ অবজেক্টের প্রকৃত প্রপার্টিগুলো পরিবর্তন করার মাধ্যমে স্ক্রিনের ভিউগুলোকে অ্যানিমেট করতে পারে। এছাড়াও, ভিউ-এর প্রপার্টি পরিবর্তিত হলে এটি স্ক্রিন রিফ্রেশ করার জন্য স্বয়ংক্রিয়ভাবে invalidate() মেথড কল করে। View ক্লাসের যে নতুন প্রপার্টিগুলো প্রপার্টি অ্যানিমেশনকে সহজতর করে, সেগুলো হলো:

  • translationX এবং translationY : এই প্রোপার্টিগুলো নিয়ন্ত্রণ করে যে, ভিউটি তার লেআউট কন্টেইনার দ্বারা নির্ধারিত বাম এবং উপরের স্থানাঙ্ক থেকে ডেল্টা হিসেবে কোথায় অবস্থিত হবে।
  • rotation , rotationX , এবং rotationY : এই প্রোপার্টিগুলো পিভট পয়েন্টের চারপাশে 2D ( rotation প্রোপার্টি) এবং 3D ঘূর্ণন নিয়ন্ত্রণ করে।
  • scaleX এবং scaleY : এই প্রোপার্টিগুলো একটি ভিউ-এর পিভট পয়েন্টকে কেন্দ্র করে তার দ্বি-মাত্রিক স্কেলিং নিয়ন্ত্রণ করে।
  • pivotX এবং pivotY : এই প্রোপার্টিগুলো পিভট পয়েন্টের অবস্থান নিয়ন্ত্রণ করে, যার চারপাশে ঘূর্ণন এবং স্কেলিং ট্রান্সফর্মগুলো ঘটে। ডিফল্টরূপে, পিভট পয়েন্টটি অবজেক্টের কেন্দ্রে অবস্থিত থাকে।
  • x এবং y : এগুলো হলো দুটি সাধারণ ইউটিলিটি প্রপার্টি, যা কন্টেইনারের মধ্যে ভিউটির চূড়ান্ত অবস্থান বর্ণনা করে। এটি হলো left ও top ভ্যালু এবং translationX ও translationY ভ্যালুগুলোর যোগফল।
  • alpha : ভিউ-এর আলফা স্বচ্ছতা নির্দেশ করে। ডিফল্টরূপে এর মান ১ (অস্বচ্ছ), এবং ০ মানটি সম্পূর্ণ স্বচ্ছতা (অদৃশ্য) বোঝায়।

একটি ভিউ অবজেক্টের কোনো প্রপার্টি, যেমন তার রঙ বা ঘূর্ণন মান, অ্যানিমেট করতে হলে আপনাকে শুধু একটি প্রপার্টি অ্যানিমেটর তৈরি করতে হবে এবং যে ভিউ প্রপার্টিটি অ্যানিমেট করতে চান তা নির্দিষ্ট করে দিতে হবে। উদাহরণস্বরূপ:

কোটলিন

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f)

জাভা

ObjectAnimator.ofFloat(myView, "rotation", 0f, 360f);

অ্যানিমেটর তৈরি করার বিষয়ে আরও তথ্যের জন্য, ValueAnimator এবং ObjectAnimator ব্যবহার করে অ্যানিমেট করার বিভাগগুলো দেখুন।

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

ViewPropertyAnimator একটিমাত্র Animator অবজেক্ট ব্যবহার করে একটি View -এর একাধিক প্রপার্টিকে সমান্তরালভাবে অ্যানিমেট করার একটি সহজ উপায় প্রদান করে। এটি অনেকটা ObjectAnimator মতোই আচরণ করে, কারণ এটি ভিউ-এর প্রপার্টিগুলোর প্রকৃত মান পরিবর্তন করে, কিন্তু একসাথে অনেকগুলো প্রপার্টি অ্যানিমেট করার ক্ষেত্রে এটি আরও বেশি কার্যকর। এছাড়াও, ViewPropertyAnimator ব্যবহারের কোড অনেক বেশি সংক্ষিপ্ত এবং সহজে পাঠযোগ্য। নিচের কোড স্নিপেটগুলোতে একটি ভিউ-এর x এবং y প্রপার্টি একই সাথে অ্যানিমেট করার ক্ষেত্রে একাধিক ObjectAnimator অবজেক্ট, একটিমাত্র ObjectAnimator এবং ViewPropertyAnimator ব্যবহারের পার্থক্যগুলো দেখানো হয়েছে।

একাধিক ObjectAnimator অবজেক্ট

কোটলিন

val animX = ObjectAnimator.ofFloat(myView, "x", 50f)
val animY = ObjectAnimator.ofFloat(myView, "y", 100f)
AnimatorSet().apply {
    playTogether(animX, animY)
    start()
}

জাভা

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();

একটি অবজেক্ট অ্যানিমেটর

কোটলিন

val pvhX = PropertyValuesHolder.ofFloat("x", 50f)
val pvhY = PropertyValuesHolder.ofFloat("y", 100f)
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start()

জাভা

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvhY).start();

ভিউপ্রপার্টিঅ্যানিমেটর

কোটলিন

myView.animate().x(50f).y(100f)

জাভা

myView.animate().x(50f).y(100f);

ViewPropertyAnimator সম্পর্কে আরও বিস্তারিত তথ্যের জন্য, সংশ্লিষ্ট অ্যান্ড্রয়েড ডেভেলপারস ব্লগ পোস্টটি দেখুন।

XML-এ অ্যানিমেশন ঘোষণা করুন

প্রপার্টি অ্যানিমেশন সিস্টেম আপনাকে প্রোগ্রাম্যাটিকভাবে করার পরিবর্তে XML-এর মাধ্যমে প্রপার্টি অ্যানিমেশন ঘোষণা করার সুযোগ দেয়। XML-এ আপনার অ্যানিমেশনগুলো সংজ্ঞায়িত করার মাধ্যমে, আপনি একাধিক অ্যাক্টিভিটিতে সহজেই সেগুলোর পুনঃব্যবহার করতে পারেন এবং অ্যানিমেশন সিকোয়েন্স আরও সহজে সম্পাদনা করতে পারেন।

অ্যান্ড্রয়েড ৩.১ থেকে শুরু করে, নতুন প্রপার্টি অ্যানিমেশন এপিআই ব্যবহার করা অ্যানিমেশন ফাইলগুলোকে পুরোনো ভিউ অ্যানিমেশন ফ্রেমওয়ার্ক ব্যবহার করা ফাইলগুলো থেকে আলাদা করার জন্য, প্রপার্টি অ্যানিমেশনের এক্সএমএল ফাইলগুলো res/animator/ ডিরেক্টরিতে সেভ করতে হবে।

নিম্নলিখিত প্রপার্টি অ্যানিমেশন ক্লাসগুলিতে নিম্নলিখিত XML ট্যাগগুলির সাথে XML ডিক্লারেশন সাপোর্ট রয়েছে:

আপনার XML ডিক্লারেশনে ব্যবহারযোগ্য অ্যাট্রিবিউটগুলো খুঁজে পেতে, অ্যানিমেশন রিসোর্সেস দেখুন। নিম্নলিখিত উদাহরণটি অবজেক্ট অ্যানিমেশনের দুটি সেট ক্রমানুসারে প্লে করে, যেখানে প্রথম নেস্টেড সেটটি দুটি অবজেক্ট অ্যানিমেশন একসাথে প্লে করে:

<set android:ordering="sequentially">
    <set>
        <objectAnimator
            android:propertyName="x"
            android:duration="500"
            android:valueTo="400"
            android:valueType="intType"/>
        <objectAnimator
            android:propertyName="y"
            android:duration="500"
            android:valueTo="300"
            android:valueType="intType"/>
    </set>
    <objectAnimator
        android:propertyName="alpha"
        android:duration="500"
        android:valueTo="1f"/>
</set>

এই অ্যানিমেশনটি চালানোর জন্য, আপনাকে অবশ্যই আপনার কোডে XML রিসোর্সগুলোকে একটি AnimatorSet অবজেক্টে ইনফ্লেট করতে হবে এবং তারপর অ্যানিমেশন সেটটি শুরু করার আগে সমস্ত অ্যানিমেশনের জন্য টার্গেট অবজেক্টগুলো সেট করতে হবে। সুবিধার জন্য, setTarget() কল করলে AnimatorSet এর সমস্ত চাইল্ডের জন্য একটিমাত্র টার্গেট অবজেক্ট সেট হয়ে যায়। নিচের কোডটিতে দেখানো হয়েছে কীভাবে এটি করতে হয়:

কোটলিন

(AnimatorInflater.loadAnimator(myContext, R.animator.property_animator) as AnimatorSet).apply {
    setTarget(myObject)
    start()
}

জাভা

AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,
    R.animator.property_animator);
set.setTarget(myObject);
set.start();

আপনি XML-এও একটি ValueAnimator ঘোষণা করতে পারেন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

<animator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:valueType="floatType"
    android:valueFrom="0f"
    android:valueTo="-100f" />

আপনার কোডে পূর্ববর্তী ValueAnimator ব্যবহার করতে হলে, আপনাকে অবশ্যই অবজেক্টটি ইনফ্লেট করতে হবে, একটি AnimatorUpdateListener যোগ করতে হবে, আপডেট হওয়া অ্যানিমেশন ভ্যালুটি নিতে হবে এবং আপনার ভিউগুলোর কোনো একটির প্রপার্টিতে তা ব্যবহার করতে হবে, যেমনটি নিচের কোডে দেখানো হয়েছে:

কোটলিন

(AnimatorInflater.loadAnimator(this, R.animator.animator) as ValueAnimator).apply {
    addUpdateListener { updatedAnimation ->
        textView.translationX = updatedAnimation.animatedValue as Float
    }

    start()
}

জাভা

ValueAnimator xmlAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(this,
        R.animator.animator);
xmlAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator updatedAnimation) {
        float animatedValue = (float)updatedAnimation.getAnimatedValue();
        textView.setTranslationX(animatedValue);
    }
});

xmlAnimator.start();

প্রপার্টি অ্যানিমেশন নির্ধারণের XML সিনট্যাক্স সম্পর্কে জানতে, অ্যানিমেশন রিসোর্স দেখুন।

UI পারফরম্যান্সের উপর সম্ভাব্য প্রভাব

যেসব অ্যানিমেটর UI আপডেট করে, সেগুলো অ্যানিমেশন চলার প্রতিটি ফ্রেমে অতিরিক্ত রেন্ডারিংয়ের কাজ তৈরি করে। এই কারণে, রিসোর্স-ইনটেনসিভ অ্যানিমেশন ব্যবহার করা আপনার অ্যাপের পারফরম্যান্সের ওপর নেতিবাচক প্রভাব ফেলতে পারে।

আপনার UI অ্যানিমেট করার জন্য প্রয়োজনীয় কাজটি রেন্ডারিং পাইপলাইনের অ্যানিমেশন স্টেজে যুক্ত করা হয়। আপনার অ্যানিমেশনগুলো আপনার অ্যাপের পারফরম্যান্সে প্রভাব ফেলছে কিনা তা জানতে, আপনি প্রোফাইল জিপিইউ রেন্ডারিং (Profile GPU Rendering) চালু করে অ্যানিমেশন স্টেজটি পর্যবেক্ষণ করতে পারেন। আরও তথ্যের জন্য, প্রোফাইল জিপিইউ রেন্ডারিং ওয়াকথ্রু (Profile GPU rendering walkthrough ) দেখুন।