একটি কাস্টম ভিউ ইন্টারেক্টিভ করুন

রচনা পদ্ধতি চেষ্টা করুন
জেটপ্যাক কম্পোজ হল Android এর জন্য প্রস্তাবিত UI টুলকিট। কম্পোজে লেআউটের সাথে কীভাবে কাজ করবেন তা শিখুন।

একটি UI আঁকা একটি কাস্টম ভিউ তৈরির একটি অংশ মাত্র। আপনাকে আপনার দৃষ্টিভঙ্গি এমনভাবে ব্যবহারকারীর ইনপুটকে প্রতিক্রিয়া জানাতে হবে যা আপনি যে বাস্তব-বিশ্বের ক্রিয়াটি অনুকরণ করছেন তার সাথে সাদৃশ্যপূর্ণ।

আপনার অ্যাপের বস্তুগুলোকে বাস্তব বস্তুর মতো কাজ করুন। উদাহরণস্বরূপ, আপনার অ্যাপে থাকা চিত্রগুলিকে অস্তিত্ব থেকে পপ আউট হতে দেবেন না এবং অন্য কোথাও আবার প্রদর্শিত হতে দেবেন না, কারণ বাস্তব জগতের বস্তুগুলি তা করে না৷ পরিবর্তে, আপনার ছবিগুলি এক জায়গা থেকে অন্য জায়গায় সরান৷

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

এই পৃষ্ঠাটি আপনার কাস্টম ভিউতে এই বাস্তব-বিশ্বের আচরণগুলি যুক্ত করতে Android ফ্রেমওয়ার্কের বৈশিষ্ট্যগুলি কীভাবে ব্যবহার করতে হয় তা প্রদর্শন করে৷

আপনি ইনপুট ইভেন্ট ওভারভিউ এবং সম্পত্তি অ্যানিমেশন ওভারভিউতে অতিরিক্ত সম্পর্কিত তথ্য পেতে পারেন।

ইনপুট অঙ্গভঙ্গি পরিচালনা করুন

অন্যান্য অনেক UI ফ্রেমওয়ার্কের মতো, অ্যান্ড্রয়েড একটি ইনপুট ইভেন্ট মডেলকে সমর্থন করে। ব্যবহারকারীর ক্রিয়াকলাপগুলি ইভেন্টে পরিণত হয় যা কলব্যাকগুলিকে ট্রিগার করে এবং আপনার অ্যাপ ব্যবহারকারীকে কীভাবে প্রতিক্রিয়া জানায় তা কাস্টমাইজ করতে আপনি কলব্যাকগুলিকে ওভাররাইড করতে পারেন৷ অ্যান্ড্রয়েড সিস্টেমে সবচেয়ে সাধারণ ইনপুট ইভেন্ট হল টাচ , যা onTouchEvent(android.view.MotionEvent) ট্রিগার করে। ইভেন্ট পরিচালনা করতে এই পদ্ধতিটি ওভাররাইড করুন, নিম্নরূপ:

কোটলিন

override fun onTouchEvent(event: MotionEvent): Boolean {
    return super.onTouchEvent(event)
}

জাভা

@Override
   public boolean onTouchEvent(MotionEvent event) {
    return super.onTouchEvent(event);
   }

নিজেদের দ্বারা স্পর্শ ঘটনা বিশেষভাবে দরকারী নয়. আধুনিক স্পর্শ UI গুলি আলতো চাপানো, টানানো, ঠেলে দেওয়া, ফ্লিং করা এবং জুম করার মতো অঙ্গভঙ্গির ক্ষেত্রে মিথস্ক্রিয়াকে সংজ্ঞায়িত করে৷ কাঁচা স্পর্শ ইভেন্টগুলিকে অঙ্গভঙ্গিতে রূপান্তর করতে, Android GestureDetector প্রদান করে৷

GestureDetector.OnGestureListener প্রয়োগ করে এমন একটি ক্লাসের একটি উদাহরণ পাস করে একটি GestureDetector তৈরি করুন। আপনি যদি শুধুমাত্র কয়েকটি অঙ্গভঙ্গি প্রক্রিয়া করতে চান, তাহলে আপনি GestureDetector.OnGestureListener ইন্টারফেস প্রয়োগ করার পরিবর্তে GestureDetector.SimpleOnGestureListener প্রসারিত করতে পারেন। উদাহরণস্বরূপ, এই কোডটি একটি ক্লাস তৈরি করে যা GestureDetector.SimpleOnGestureListener প্রসারিত করে এবং onDown(MotionEvent) ওভাররাইড করে।

কোটলিন

private val myListener =  object : GestureDetector.SimpleOnGestureListener() {
    override fun onDown(e: MotionEvent): Boolean {
        return true
    }
}

private val detector: GestureDetector = GestureDetector(context, myListener)

জাভা

class MyListener extends GestureDetector.SimpleOnGestureListener {
   @Override
   public boolean onDown(MotionEvent e) {
       return true;
   }
}
detector = new GestureDetector(getContext(), new MyListener());

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

আপনি GestureDetector.OnGestureListener প্রয়োগ করার পরে এবং GestureDetector এর একটি উদাহরণ তৈরি করার পরে, আপনি onTouchEvent() এ প্রাপ্ত টাচ ইভেন্টগুলি ব্যাখ্যা করতে আপনার GestureDetector ব্যবহার করতে পারেন৷

কোটলিন

override fun onTouchEvent(event: MotionEvent): Boolean {
    return detector.onTouchEvent(event).let { result ->
        if (!result) {
            if (event.action == MotionEvent.ACTION_UP) {
                stopScrolling()
                true
            } else false
        } else true
    }
}

জাভা

@Override
public boolean onTouchEvent(MotionEvent event) {
   boolean result = detector.onTouchEvent(event);
   if (!result) {
       if (event.getAction() == MotionEvent.ACTION_UP) {
           stopScrolling();
           result = true;
       }
   }
   return result;
}

আপনি যখন onTouchEvent() একটি স্পর্শ ইভেন্ট পাস করেন যা এটি একটি অঙ্গভঙ্গির অংশ হিসাবে স্বীকৃতি দেয় না, এটি false ফেরত দেয়। তারপর আপনি আপনার নিজস্ব কাস্টম অঙ্গভঙ্গি সনাক্তকরণ কোড চালাতে পারেন৷

শারীরিকভাবে যুক্তিযুক্ত গতি তৈরি করুন

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

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

কীভাবে একটি স্ক্রোল অঙ্গভঙ্গি অ্যানিমেট করতে হয় তার ডকুমেন্টেশন আপনার নিজের স্কোল আচরণ কীভাবে বাস্তবায়ন করতে হয় সে সম্পর্কে একটি বিশদ ব্যাখ্যা দেয়। কিন্তু একটি ফ্লাইহুইলের অনুভূতি অনুকরণ করা তুচ্ছ নয়। একটি ফ্লাইহুইল মডেল সঠিকভাবে কাজ করার জন্য প্রচুর পদার্থবিদ্যা এবং গণিতের প্রয়োজন। সৌভাগ্যবশত, অ্যান্ড্রয়েড এটি এবং অন্যান্য আচরণ অনুকরণ করতে সহায়ক ক্লাস প্রদান করে। Scroller ক্লাস হল ফ্লাইহুইল-স্টাইলের ফ্লিং অঙ্গভঙ্গি পরিচালনা করার ভিত্তি।

একটি ফ্লিং শুরু করতে, শুরুর বেগ এবং ফ্লিং-এর সর্বনিম্ন এবং সর্বাধিক x এবং y মান সহ fling() কল করুন। বেগের মানের জন্য, আপনি GestureDetector দ্বারা গণনা করা মান ব্যবহার করতে পারেন।

কোটলিন

fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
    scroller.fling(
            currentX,
            currentY,
            (velocityX / SCALE).toInt(),
            (velocityY / SCALE).toInt(),
            minX,
            minY,
            maxX,
            maxY
    )
    postInvalidate()
    return true
}

জাভা

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
   scroller.fling(currentX, currentY, velocityX / SCALE, velocityY / SCALE, minX, minY, maxX, maxY);
   postInvalidate();
    return true;
}

কল টু fling() ফ্লিং জেসচারের জন্য ফিজিক্স মডেল সেট আপ করে। তারপরে, নিয়মিত বিরতিতে Scroller.computeScrollOffset() কল করে Scroller আপডেট করুন। computeScrollOffset() বর্তমান সময় পড়ে এবং সেই সময়ে x এবং y অবস্থান গণনা করতে পদার্থবিদ্যা মডেল ব্যবহার করে Scroller অবজেক্টের অভ্যন্তরীণ অবস্থা আপডেট করে। এই মানগুলি পুনরুদ্ধার করতে getCurrX() এবং getCurrY() কল করুন।

বেশিরভাগ ভিউ Scroller অবজেক্টের x এবং y অবস্থানগুলিকে সরাসরি scrollTo() এ পাস করে। এই উদাহরণটি একটু ভিন্ন: এটি দৃশ্যের ঘূর্ণন কোণ সেট করতে বর্তমান স্ক্রোল x অবস্থান ব্যবহার করে।

কোটলিন

scroller.apply {
    if (!isFinished) {
        computeScrollOffset()
        setItemRotation(currX)
    }
}

জাভা

if (!scroller.isFinished()) {
    scroller.computeScrollOffset();
    setItemRotation(scroller.getCurrX());
}

Scroller ক্লাস আপনার জন্য স্ক্রোল পজিশন গণনা করে, কিন্তু এটি স্বয়ংক্রিয়ভাবে সেই পজিশনগুলি আপনার ভিউতে প্রয়োগ করে না। স্ক্রলিং অ্যানিমেশনকে মসৃণ দেখাতে প্রায়ই যথেষ্ট নতুন স্থানাঙ্ক প্রয়োগ করুন। এটি করার দুটি উপায় আছে:

  • fling() কল করার পরে postInvalidate() কল করে একটি পুনরায় আঁকা বাধ্যতামূলক করুন। এই কৌশলটির জন্য আপনাকে onDraw() এ স্ক্রোল অফসেটগুলি গণনা করতে হবে এবং প্রতিবার স্ক্রোল অফসেট পরিবর্তন করার সময় postInvalidate() কল করতে হবে।
  • ফ্লিংয়ের সময়কালের জন্য অ্যানিমেট করার জন্য একটি ValueAnimator সেট আপ করুন এবং addUpdateListener() কল করে অ্যানিমেশন আপডেট প্রক্রিয়া করার জন্য একজন শ্রোতাকে যোগ করুন। এই কৌশলটি আপনাকে একটি View এর বৈশিষ্ট্যগুলিকে অ্যানিমেট করতে দেয়।

আপনার পরিবর্তন মসৃণ করুন

ব্যবহারকারীরা আশা করে যে একটি আধুনিক UI রাজ্যগুলির মধ্যে মসৃণভাবে স্থানান্তরিত হবে: UI উপাদানগুলি উপস্থিত এবং অদৃশ্য হওয়ার পরিবর্তে বিবর্ণ হয়ে যাচ্ছে এবং গতি শুরু এবং হঠাৎ করে বন্ধ করার পরিবর্তে মসৃণভাবে শুরু এবং শেষ হচ্ছে। অ্যান্ড্রয়েড প্রপার্টি অ্যানিমেশন ফ্রেমওয়ার্ক মসৃণ রূপান্তরকে সহজ করে তোলে।

অ্যানিমেশন সিস্টেম ব্যবহার করার জন্য, যখনই একটি সম্পত্তি পরিবর্তন করে যা আপনার দৃশ্যের চেহারাকে প্রভাবিত করে, সরাসরি সম্পত্তি পরিবর্তন করবেন না। পরিবর্তে, পরিবর্তন করতে ValueAnimator ব্যবহার করুন। নিচের উদাহরণে, ভিউতে নির্বাচিত চাইল্ড কম্পোনেন্ট পরিবর্তন করলে সম্পূর্ণ রেন্ডার করা ভিউ ঘোরানো হয় যাতে সিলেকশন পয়েন্টার কেন্দ্রীভূত হয়। ValueAnimator নতুন ঘূর্ণন মান অবিলম্বে সেট করার পরিবর্তে, কয়েকশ মিলিসেকেন্ডের মধ্যে ঘূর্ণন পরিবর্তন করে।

কোটলিন

autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0).apply {
    setIntValues(targetAngle)
    duration = AUTOCENTER_ANIM_DURATION
    start()
}

জাভা

autoCenterAnimator = ObjectAnimator.ofInt(this, "Rotation", 0);
autoCenterAnimator.setIntValues(targetAngle);
autoCenterAnimator.setDuration(AUTOCENTER_ANIM_DURATION);
autoCenterAnimator.start();

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

কোটলিন

animate()
    .rotation(targetAngle)
    .duration = ANIM_DURATION
    .start()

জাভা

animate().rotation(targetAngle).setDuration(ANIM_DURATION).start();