উন্নত লেখনী বৈশিষ্ট্য

Android এবং ChromeOS বিভিন্ন ধরনের API প্রদান করে যা আপনাকে এমন অ্যাপ তৈরি করতে সাহায্য করে যা ব্যবহারকারীদের একটি ব্যতিক্রমী স্টাইলাস অভিজ্ঞতা প্রদান করে। MotionEvent ক্লাস স্ক্রিনের সাথে স্টাইলাসের ইন্টার‍্যাকশন সম্পর্কে তথ্য প্রকাশ করে, যার মধ্যে স্টাইলাসের চাপ, ওরিয়েন্টেশন, টিল্ট, হোভার ও পাম শনাক্তকরণ অন্তর্ভুক্ত। কম লেটেন্সি গ্রাফিক্স ও মোশন প্রেডিকশন লাইব্রেরি স্টাইলাস অন-স্ক্রিন রেন্ডারিং উন্নত করে যাতে স্বাভাবিক, পেন-ও-কাগজের মতো অভিজ্ঞতা প্রদান করা যায়।

MotionEvent

MotionEvent ক্লাস ব্যবহারকারীর ইনপুট ইন্টার‍্যাকশন দেখায়, যেমন স্ক্রিনে টাচ পয়েন্টারের পজিশন ও মুভমেন্ট। স্টাইলাস ইনপুটের জন্য, MotionEvent এছাড়াও প্রেসার, ওরিয়েন্টেশন, টিল্ট ও হোভার ডেটা প্রকাশ করে।

ইভেন্ট ডেটা

স্টাইলাস MotionEvent অবজেক্ট অ্যাক্সেস করতে, ড্রয়িং সারফেসে pointerInteropFilter মডিফায়ার যোগ করুন। এমন একটি পদ্ধতি সহ ViewModel ক্লাস প্রয়োগ করুন যা মোশন ইভেন্ট প্রসেস করে; pointerInteropFilter মডিফায়ারের onTouchEvent ল্যাম্বডা হিসেবে পদ্ধতিটি পাস করুন:

@Composable
@OptIn(ExperimentalComposeUiApi::class)
fun DrawArea(modifier: Modifier = Modifier) {
    Canvas(
        modifier = modifier
            .clipToBounds()
            .pointerInteropFilter {
                viewModel.processMotionEvent(it)
            }

    ) {
        // Drawing code here.
    }
}

MotionEvent অবজেক্ট UI ইভেন্টের নিম্নলিখিত দিক সম্পর্কিত ডেটা প্রদান করে:

  • অ্যাকশন: ডিভাইসের সাথে ফিজিক্যাল ইন্ট্যার‍্যাকশন—স্ক্রিন টাচ করা, স্ক্রিনের সারফেসের উপর পয়েন্টার সরানো, স্ক্রিনের সারফেসের উপর পয়েন্টার হোভার করা
  • পয়েন্টার: স্ক্রিনের সাথে ইন্টার‍্যাক্ট করা অবজেক্টের শনাক্তকারী—আঙুল, স্টাইলাস, মাউস
  • অ্যাক্সিস: ডেটার ধরন—x ও y কোঅর্ডিনেট, প্রেসার, টিল্ট, ওরিয়েন্টেশন ও হোভার (দূরত্ব)

অ্যাকশন

স্টাইলাস সাপোর্ট প্রয়োগ করতে, ব্যবহারকারী কী অ্যাকশন পারফর্ম করছেন তা আপনাকে বুঝতে হবে।

MotionEvent-এ বিভিন্ন ধরনের ACTION কনস্ট্যান্ট থাকে যা মোশন ইভেন্ট সংজ্ঞায়িত করে। স্টাইলাসের জন্য সবচেয়ে গুরুত্বপূর্ণ অ্যাকশনের মধ্যে নিম্নলিখিতগুলি অন্তর্ভুক্ত:

অ্যাকশন বর্ণনা
ACTION_DOWN
ACTION_POINTER_DOWN
পয়েন্টার স্ক্রিনের সাথে কানেক্ট করেছে।
ACTION_MOVE স্ক্রিনে পয়েন্টার নড়াচড়া করছে।
ACTION_UP
ACTION_POINTER_UP
পয়েন্টার আর স্ক্রিনের সাথে কানেক্ট করা নেই
ACTION_CANCEL আগের বা বর্তমান মোশন সেট কখন বাতিল করা উচিত।

আপনার অ্যাপ ACTION_DOWN হলে নতুন স্ট্রোক শুরু করা, ACTION_MOVE,-এর মাধ্যমে স্ট্রোক আঁকা এবং ACTION_UP ট্রিগার হলে স্ট্রোক শেষ করার মতো টাস্ক পারফর্ম করতে পারে।

নির্দিষ্ট পয়েন্টারের জন্য ACTION_DOWN থেকে ACTION_UP পর্যন্ত MotionEventটি অ্যাকশনের সেটকে মোশন সেট বলা হয়।

পয়েন্টার

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

পয়েন্টার ইনডেক্সের রেঞ্জ শূন্য থেকে শুরু করে MotionEvent#pointerCount() দ্বারা রিটার্ন করা পয়েন্টারের সংখ্যা থেকে ১ বিয়োগ করে পাওয়া সংখ্যা পর্যন্ত হয়।

getAxisValue(axis, pointerIndex) পদ্ধতির মাধ্যমে পয়েন্টারের অক্ষের ভ্যালু অ্যাক্সেস করা যাবে। পয়েন্টার ইনডেক্স বাদ দেওয়া হলে, সিস্টেম প্রথম পয়েন্টার, পয়েন্টার শূন্য (0)-এর জন্য ভ্যালু রিটার্ন করে।

MotionEvent অবজেক্টে ব্যবহার করা পয়েন্টারের ধরন সম্পর্কে তথ্য থাকে। আপনি পয়েন্টার ইনডেক্স ইটারেট করে এবং getToolType(pointerIndex) মেথড কল করে পয়েন্টারের ধরন জানতে পারবেন।

পয়েন্টার সম্পর্কে আরও জানতে, মাল্টি-টাচ জেসচার ম্যানেজ করুন দেখুন।

স্টাইলাস ইনপুট

আপনি TOOL_TYPE_STYLUS-এর মাধ্যমে স্টাইলাস ইনপুট ফিল্টার করতে পারবেন:

val isStylus = TOOL_TYPE_STYLUS == event.getToolType(pointerIndex)

স্টাইলাসটি TOOL_TYPE_ERASER-এর সাথে ইরেজার হিসেবে ব্যবহার করা হয়েছে বলেও রিপোর্ট করতে পারে:

val isEraser = TOOL_TYPE_ERASER == event.getToolType(pointerIndex)

স্টাইলাস অ্যাক্সিস ডেটা

ACTION_DOWN এবং ACTION_MOVE স্টাইলাস সম্পর্কে অক্ষ ডেটা প্রদান করে, যেমন x এবং y কোঅর্ডিনেট, প্রেসার, ওরিয়েন্টেশন, টিল্ট এবং হোভার।

এই ডেটা অ্যাক্সেস করার সুবিধা চালু করতে, MotionEvent API getAxisValue(int) প্রদান করে, যেখানে প্যারামিটারটি নিম্নলিখিত যেকোনও অক্ষ শনাক্তকারী:

অক্ষ getAxisValue()-এর রিটার্ন ভ্যালু
AXIS_X মোশন ইভেন্টের X কোঅর্ডিনেট।
AXIS_Y মোশন ইভেন্টের Y কোঅর্ডিনেট।
AXIS_PRESSURE টাচস্ক্রিন বা টাচপ্যাডের ক্ষেত্রে, আঙুল, স্টাইলাস বা অন্য কোনও পয়েন্টার দিয়ে প্রয়োগ করা চাপ। মাউস বা ট্র্যাকবলের ক্ষেত্রে, প্রাইমারি বোতাম প্রেস করা হলে ১, অন্যথায় ০।
AXIS_ORIENTATION টাচস্ক্রিন বা টাচপ্যাডের জন্য, ডিভাইসের উল্লম্ব প্লেনের সাপেক্ষে আঙুল, স্টাইলাস বা অন্য পয়েন্টারের ওরিয়েন্টেশন।
AXIS_TILT রেডিয়ানে স্টাইলাসের টিল্ট অ্যাঙ্গেল।
AXIS_DISTANCE স্ক্রিন থেকে স্টাইলাসের দূরত্ব।

যেমন, MotionEvent.getAxisValue(AXIS_X) প্রথম পয়েন্টারের জন্য x কোঅর্ডিনেট ফেরত পাঠায়।

এছাড়াও, মাল্টি-টাচ জেসচার ম্যানেজ করা দেখুন।

অবস্থান

আপনি নিম্নলিখিত কলগুলির মাধ্যমে একটি পয়েন্টারের x এবং y স্থানাঙ্কগুলি পুনরুদ্ধার করতে পারেন:

স্ক্রিনে স্টাইলাস দিয়ে আঁকা, যেখানে x ও y কোঅর্ডিনেট ম্যাপ করা আছে।
ছবি ১. স্টাইলাস পয়েন্টারের x এবং y স্ক্রিন কোঅর্ডিনেট।

চাপ

আপনি MotionEvent#getAxisValue(AXIS_PRESSURE) বা প্রথম পয়েন্টারের জন্য, MotionEvent#getPressure()-এর মাধ্যমে পয়েন্টার প্রেসার রিট্রিভ করতে পারবেন।

টাচস্ক্রিন বা টাচপ্যাডের জন্য প্রেসার ভ্যালু হল ০ (কোনও প্রেসার নেই) এবং ১-এর মধ্যে একটি মান, তবে স্ক্রিন ক্যালিব্রেশনের উপর নির্ভর করে আরও বেশি মান রিটার্ন করা যেতে পারে।

স্টাইলাস স্ট্রোক যা কম থেকে বেশি চাপের ধারাবাহিকতা দেখায়। বাঁদিকে স্ট্রোকটি সরু ও হালকা, যা কম চাপের ইঙ্গিত দেয়। স্ট্রোকটি বাঁদিক থেকে ডানদিকে আরও চওড়া এবং গাঢ় হতে থাকে যতক্ষণ না এটি সবচেয়ে ডানদিকে সবচেয়ে চওড়া এবং গাঢ় হয়, যা সর্বোচ্চ চাপ নির্দেশ করে।
ছবি ২. চাপের উপস্থাপনা—বাঁদিকে কম চাপ, ডানদিকে বেশি চাপ।

সজ্জা

স্টাইলাস কোন দিকে পয়েন্ট করছে তা ওরিয়েন্টেশন থেকে বোঝা যায়।

getAxisValue(AXIS_ORIENTATION) বা getOrientation() (প্রথম পয়েন্টারের জন্য) ব্যবহার করে পয়েন্টারের ওরিয়েন্টেশন ফিরিয়ে আনা যাবে।

স্টাইলাসের ক্ষেত্রে, ঘড়ির কাঁটার দিকে ০ থেকে পাই (𝛑) অথবা ঘড়ির কাঁটার বিপরীতে ০ থেকে -পাই-এর মধ্যে রেডিয়ান ভ্যালু হিসেবে ওরিয়েন্টেশন দেখানো হয়।

ওরিয়েন্টেশন আপনাকে বাস্তব জীবনের ব্রাশ প্রয়োগ করতে দেয়। যেমন, স্টাইলাস যদি ফ্ল্যাট ব্রাশের মতো কাজ করে, তাহলে ফ্ল্যাট ব্রাশের প্রস্থ স্টাইলাসের ওরিয়েন্টেশনের উপর নির্ভর করে।

ছবি ৩. স্টাইলাস বাঁদিকে প্রায় মাইনাস .৫৭ রেডিয়ানে পয়েন্ট করছে।

ঝোকানো

স্ক্রিনের সাপেক্ষে স্টাইলাসের ইনক্লিনেশন টিল্ট পরিমাপ করে।

টিল্ট স্টাইলাসের পজিটিভ কোণ রেডিয়ানে দেখায়, যেখানে শূন্য হল স্ক্রিনের সাথে লম্ব এবং 𝛑/২ হল সারফেসের সাথে সমান্তরাল।

getAxisValue(AXIS_TILT) ব্যবহার করে টিল্ট অ্যাঙ্গেল পুনরুদ্ধার করা যাবে (প্রথম পয়েন্টারের জন্য কোনও শর্টকাট নেই)।

বাস্তব জীবনের টুল যতটা সম্ভব কাছাকাছি পুনরুৎপাদন করতে টিল্ট ব্যবহার করা যেতে পারে, যেমন একটি কাত করা পেন্সিল দিয়ে শেডিং অনুকরণ করা।

স্ক্রিনের সারফেস থেকে স্টাইলাস প্রায় ৪০ ডিগ্রি কোণে হেলানো আছে।
ছবি ৪. স্টাইলাস প্রায় .৭৮৫ রেডিয়ান বা লম্ব থেকে ৪৫ ডিগ্রি টিল্ট করা হয়েছে।

উপরে নিয়ে যাওয়া

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

ব্রাশের সাইজের প্রিভিউ দেখতে বা কোনও বোতাম বেছে নেওয়া হচ্ছে তা বোঝাতে স্টাইলাস হোভার ব্যবহার করা যেতে পারে।

ছবি ৫. স্ক্রিনের উপর স্টাইলাস হোভার করছে। স্টাইলাস স্ক্রিনের সারফেস স্পর্শ না করলেও অ্যাপ প্রতিক্রিয়া দেখায়।

মনে রাখবেন: Compose এমন মডিফায়ার প্রদান করে যা UI এলিমেন্টের ইন্টার‍্যাক্টিভ অবস্থাকে প্রভাবিত করে:

  • hoverable: পয়েন্টার এন্টার ও এক্সিট ইভেন্ট ব্যবহার করে হোভার করা যায় এমন কম্পোনেন্ট কনফিগার করুন।
  • indication: ইন্টার‍্যাকশন হলে এই কম্পোনেন্টের জন্য ভিজ্যুয়াল এফেক্ট ড্র করে।

পাম রিজেকশন, নেভিগেশন ও অবাঞ্ছিত ইনপুট

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

ফলস্বরূপ, আপনাকে অবশ্যই ব্যবহারকারীর ইনপুটের ইতিহাস রাখতে হবে যাতে স্ক্রিন থেকে অবাঞ্ছিত টাচ সরানো যায় এবং বৈধ ব্যবহারকারীর ইনপুট আবার রেন্ডার করা যায়।

ACTION_CANCEL এবং FLAG_CANCELED

ACTION_CANCEL এবং FLAG_CANCELED, উভয়কেই ডিজাইন করা হয়েছে যাতে আপনাকে জানানো যায় যে আগের MotionEvent সেটটি শেষ ACTION_DOWN থেকে বাতিল করা উচিত, যাতে আপনি, উদাহরণস্বরূপ, কোনও নির্দিষ্ট পয়েন্টারের জন্য ড্রয়িং অ্যাপের শেষ স্ট্রোকটি আগের অবস্থায় ফিরিয়ে আনতে পারেন।

ACTION_CANCEL

Android 1.0 (API লেভেল ১)-এ যোগ করা হয়েছে

ACTION_CANCEL থেকে বোঝা যায় যে মোশন ইভেন্টের আগের সেট বাতিল করতে হবে।

নিচে উল্লেখ করা যেকোনও একটি শনাক্ত করা হলে ACTION_CANCEL ট্রিগার করা হয়:

  • নেভিগেশন জেসচার
  • পাম রিজেকশন

ACTION_CANCEL ট্রিগার করা হলে, আপনাকে getPointerId(getActionIndex())-এর মাধ্যমে অ্যাক্টিভ পয়েন্টার শনাক্ত করতে হবে। তারপর ইনপুট ইতিহাস থেকে সেই পয়েন্টার দিয়ে তৈরি করা স্ট্রোক সরিয়ে দিন এবং দৃশ্যটি আবার রেন্ডার করুন।

FLAG_CANCELED

Android 13 (API লেভেল 33)-এ যোগ করা হয়েছে

FLAG_CANCELED পয়েন্টার উপরে যাওয়ার অর্থ হল ব্যবহারকারী অনিচ্ছাকৃতভাবে টাচ করেছেন। ব্যবহারকারী ভুলবশত স্ক্রিন টাচ করলে, যেমন ডিভাইসটি ধরে থাকার সময় বা স্ক্রিনে হাতের তালু রাখলে, সাধারণত এই ফ্ল্যাগ সেট করা হয়।

আপনি নিম্নলিখিত উপায়ে ফ্ল্যাগ ভ্যালু অ্যাক্সেস করতে পারবেন:

val cancel = (event.flags and FLAG_CANCELED) == FLAG_CANCELED

ফ্ল্যাগ সেট করা থাকলে, আপনাকে এই পয়েন্টার থেকে শেষ ACTION_DOWN-এর মধ্যে থেকে শেষ MotionEvent সেট আগের অবস্থায় ফিরিয়ে আনতে হবে।

ACTION_CANCEL-এর মতো, getPointerId(actionIndex)-এর সাথে পয়েন্টার পাওয়া যাবে।

ছবি ৬. স্টাইলাস স্ট্রোক ও পাম টাচ MotionEvent সেট তৈরি করে। পাম টাচ বাতিল করা হয়েছে এবং ডিসপ্লে আবার রেন্ডার করা হয়েছে।

ফুল স্ক্রিন, এজ-টু-এজ ও নেভিগেশন জেসচার

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

ছবি ৭. কোনও অ্যাপ ব্যাকগ্রাউন্ডে সরানোর জন্য সোয়াইপ জেসচার।

আপনার অ্যাপে অবাঞ্ছিত টাচ ট্রিগার করা থেকে জেসচারকে আটকাতে, আপনি ইনসেট এবং ACTION_CANCEL-এর সুবিধা নিতে পারেন।

এছাড়াও, পাম রিজেকশন, নেভিগেশন ও অবাঞ্ছিত ইনপুট বিভাগ দেখুন।

অবাঞ্ছিত টাচ ইভেন্ট থেকে নেভিগেশন জেসচার প্রতিরোধ করতে WindowInsetsController-এর setSystemBarsBehavior() পদ্ধতি এবং BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE ব্যবহার করুন:

// Configure the behavior of the hidden system bars.
windowInsetsController.systemBarsBehavior =
    WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE

ইনসেট ও জেসচার ম্যানেজমেন্ট সম্পর্কে আরও জানতে, দেখুন:

কম লেটেন্সি

ব্যবহারকারীর ইনপুট প্রসেস ও রেন্ডার করতে হার্ডওয়্যার, সিস্টেম ও অ্যাপ্লিকেশনের যে সময় লাগে, তাকে লেটেন্সি বলা হয়।

লেটেন্সি = হার্ডওয়্যার ও OS ইনপুট প্রসেসিং + অ্যাপ প্রসেসিং + সিস্টেম কম্পোজিটিং

  • হার্ডওয়্যার রেন্ডারিং
লেটেন্সির কারণে রেন্ডার করা স্ট্রোক স্টাইলাসের পজিশনের থেকে পিছিয়ে থাকে। স্ট্রোক রেন্ডার করা এবং স্টাইলাসের পজিশনের মধ্যে যে ব্যবধান থাকে তা লেটেন্সি হিসেবে দেখানো হয়।
ছবি ৮. লেটেন্সির কারণে রেন্ডার করা স্ট্রোক স্টাইলাসের পজিশনের থেকে পিছিয়ে থাকে।

লেটেন্সির সোর্স

  • টাচস্ক্রিনের (হার্ডওয়্যার) সাথে স্টাইলাস রেজিস্টার করা: প্রাথমিক ওয়্যারলেস কানেকশন যখন স্টাইলাস এবং OS রেজিস্টার এবং সিঙ্ক করার জন্য কমিউনিকেট করে।
  • টাচ স্যাম্পলিং রেট (হার্ডওয়্যার): প্রতি সেকেন্ডে যতবার টাচস্ক্রিন চেক করে দেখে যে কোনও পয়েন্টার সারফেস টাচ করছে কিনা, এটি ৬০ থেকে ১০০০Hz পর্যন্ত হতে পারে।
  • ইনপুট প্রসেসিং (অ্যাপ): ব্যবহারকারীর ইনপুটে রঙ, গ্রাফিক এফেক্ট ও ট্রান্সফর্মেশন প্রয়োগ করা।
  • গ্রাফিক রেন্ডারিং (OS + হার্ডওয়্যার): বাফার সোয়াপিং, হার্ডওয়্যার প্রসেসিং।

লো-লেটেন্সি গ্রাফিক্স

Jetpack লো-লেটেন্সি গ্রাফিক্স লাইব্রেরি ব্যবহারকারীর ইনপুট ও অন-স্ক্রিন রেন্ডারিংয়ের মধ্যে প্রসেসিংয়ের সময় কমায়।

লাইব্রেরি মাল্টি-বাফার রেন্ডারিং এড়িয়ে প্রসেসিংয়ের সময় কমায় এবং ফ্রন্ট-বাফার রেন্ডারিং টেকনিকের সুবিধা নেয়, যার অর্থ হল সরাসরি স্ক্রিনে লেখা।

ফ্রন্ট-বাফার রেন্ডারিং

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

অ্যাপ স্ক্রিন বাফারে লেখে এবং স্ক্রিন বাফার থেকে পড়ে।
ছবি ৯. ফ্রন্ট-বাফার রেন্ডারিং।
অ্যাপ মাল্টি-বাফারে লেখে, যা স্ক্রিন বাফারের সাথে অদলবদল করে। অ্যাপ স্ক্রিন বাফার থেকে পড়ে।
ছবি ১০. মাল্টি-বাফার রেন্ডারিং।

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

Android 10 (API লেভেল ২৯) ও তার পরবর্তী ভার্সনে এবং Android 10 (API লেভেল ২৯) ও তার পরবর্তী ভার্সনে চলা ChromeOS ডিভাইসে লো-লেটেন্সি লাইব্রেরি উপলভ্য।

ডিপেন্ডেন্সি

কম-লেটেন্সি লাইব্রেরি ফ্রন্ট-বাফার রেন্ডারিং প্রয়োগের জন্য কম্পোনেন্ট প্রদান করে। অ্যাপের মডিউল build.gradle ফাইলে লাইব্রেরিটি ডিপেন্ডেন্সি হিসেবে যোগ করা হয়েছে:

dependencies {
    implementation "androidx.graphics:graphics-core:1.0.0-alpha03"
}

GLFrontBufferRenderer কলব্যাক

কম-লেটেন্সি লাইব্রেরিতে GLFrontBufferRenderer.Callback ইন্টারফেস অন্তর্ভুক্ত থাকে, যা নিম্নলিখিত পদ্ধতিগুলি সংজ্ঞায়িত করে:

GLFrontBufferRenderer-এর সাথে আপনি যে ধরনের ডেটা ব্যবহার করেন, লো-লেটেন্সি লাইব্রেরি সেই সম্পর্কে কোনও মতামত দেয় না।

তবে, লাইব্রেরি ডেটা পয়েন্টের শত শত স্ট্রিম হিসেবে ডেটা প্রসেস করে; তাই, মেমরির ব্যবহার ও অ্যালোকেশন অপ্টিমাইজ করার জন্য আপনার ডেটা ডিজাইন করুন।

কলব্যাক

রেন্ডারিং কলব্যাক চালু করতে, GLFrontBufferedRenderer.Callback প্রয়োগ করুন এবং onDrawFrontBufferedLayer() ও onDrawDoubleBufferedLayer() ওভাররাইড করুন। GLFrontBufferedRenderer আপনার ডেটা সবচেয়ে অপ্টিমাইজ করা উপায়ে রেন্ডার করার জন্য কলব্যাক ব্যবহার করে।

val callback = object: GLFrontBufferedRenderer.Callback<DATA_TYPE> {
   override fun onDrawFrontBufferedLayer(
       eglManager: EGLManager,
       bufferInfo: BufferInfo,
       transform: FloatArray,
       param: DATA_TYPE
   ) {
       // OpenGL for front buffer, short, affecting small area of the screen.
   }
   override fun onDrawMultiDoubleBufferedLayer(
       eglManager: EGLManager,
       bufferInfo: BufferInfo,
       transform: FloatArray,
       params: Collection<DATA_TYPE>
   ) {
       // OpenGL full scene rendering.
   }
}
GLFrontBufferedRenderer-এর একটি ইনস্ট্যান্স ঘোষণা করুন

SurfaceView এবং আপনার আগে তৈরি করা কলব্যাক প্রদান করে GLFrontBufferedRenderer প্রস্তুত করুন। GLFrontBufferedRenderer আপনার কলব্যাক ব্যবহার করে ফ্রন্ট ও ডবল বাফারে রেন্ডারিং অপ্টিমাইজ করে:

var glFrontBufferRenderer = GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks)
রেন্ডার করা হচ্ছে

আপনি renderFrontBufferedLayer() মেথড কল করলে ফ্রন্ট-বাফার রেন্ডারিং শুরু হয়, যা onDrawFrontBufferedLayer() কলব্যাক ট্রিগার করে।

আপনি commit() ফাংশন কল করলে ডবল-বাফার রেন্ডারিং আবার শুরু হয়, যা onDrawMultiDoubleBufferedLayer() কলব্যাক ট্রিগার করে।

নিচের উদাহরণে, ব্যবহারকারী স্ক্রিনে আঁকা শুরু করলে (ACTION_DOWN) এবং পয়েন্টারটি চারপাশে সরালে (ACTION_MOVE) প্রসেসটি ফ্রন্ট বাফারে রেন্ডার করে (দ্রুত রেন্ডারিং)। পয়েন্টারটি স্ক্রিনের সারফেস থেকে সরে গেলে (ACTION_UP) প্রসেসটি ডবল বাফারে রেন্ডার করে।

আপনি requestUnbufferedDispatch() ব্যবহার করে ইনপুট সিস্টেমকে বলতে পারেন যে মোশন ইভেন্ট ব্যাচ না করে, সেগুলি উপলভ্য হওয়ার সাথে সাথেই ডেলিভার করতে:

when (motionEvent.action) {
   MotionEvent.ACTION_DOWN -> {
       // Deliver input events as soon as they arrive.
       view.requestUnbufferedDispatch(motionEvent)
       // Pointer is in contact with the screen.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE)
   }
   MotionEvent.ACTION_MOVE -> {
       // Pointer is moving.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE)
   }
   MotionEvent.ACTION_UP -> {
       // Pointer is not in contact in the screen.
       glFrontBufferRenderer.commit()
   }
   MotionEvent.CANCEL -> {
       // Cancel front buffer; remove last motion set from the screen.
       glFrontBufferRenderer.cancel()
   }
}

রেন্ডারিং সংক্রান্ত করণীয় ও বর্জনীয়

✓ করবেন

স্ক্রিনের ছোট অংশ, হাতের লেখা, ড্রয়িং, স্কেচিং।

✗ করবেন না

ফুলস্ক্রিন আপডেট, প্যানিং, জুমিং। ছিঁড়ে যেতে পারে।

ছিঁড়ে ফেলা

স্ক্রিন বাফার একই সময়ে পরিবর্তন করা হলে স্ক্রিন রিফ্রেশ করার সময় টিয়ারিং হয়। স্ক্রিনের একটি অংশে নতুন ডেটা এবং অন্য অংশে পুরনো ডেটা দেখা যায়।

স্ক্রিন রিফ্রেশ করার সময় টিয়ারিংয়ের কারণে Android ছবির উপরের ও নিচের অংশ মিসঅ্যালাইন হয়ে গেছে।
ছবি ১১. স্ক্রিন উপর থেকে নিচে রিফ্রেশ হওয়ার সময় টিয়ারিং।

মোশন প্রেডিকশন

Jetpack মোশন প্রেডিকশন লাইব্রেরি ব্যবহারকারীর স্ট্রোক পাথ অনুমান করে এবং রেন্ডারারকে সাময়িক, কৃত্রিম পয়েন্ট প্রদান করে অনুভূত লেটেন্সি কমায়।

মোশন প্রেডিকশন লাইব্রেরি MotionEvent অবজেক্ট হিসেবে আসল ব্যবহারকারীর ইনপুট পায়। অবজেক্টে x ও y কোঅর্ডিনেট, প্রেসার ও সময় সংক্রান্ত তথ্য থাকে, যা মোশন প্রেডিক্টর ব্যবহার করে ভবিষ্যতের MotionEvent অবজেক্ট সম্পর্কে অনুমান করে।

পূর্বাভাস দেওয়া MotionEventটি অবজেক্ট শুধুমাত্র অনুমান। অনুমান করা ইভেন্ট, অনুভূত লেটেন্সি কমাতে পারে, তবে অনুমান করা ডেটা, আসল MotionEvent ডেটা পাওয়ার সাথে সাথেই তার সাথে পরিবর্তন করতে হবে।

মোশন প্রেডিকশন লাইব্রেরি Android 4.4 (API লেভেল 19) ও তার পরবর্তী যেকোনও ভার্সনে এবং Android 9 (API লেভেল 28) ও তার পরবর্তী যেকোনও ভার্সনে চলা ChromeOS ডিভাইসে উপলভ্য।

লেটেন্সির কারণে রেন্ডার করা স্ট্রোক স্টাইলাসের পজিশনের থেকে পিছিয়ে থাকে। স্ট্রোক ও স্টাইলাসের মধ্যেকার ফাঁক প্রেডিকশন পয়েন্ট দিয়ে পূরণ করা হয়। বাকি থাকা ব্যবধান হল অনুভূত লেটেন্সি।
ছবি ১২. মোশন প্রেডিকশনের মাধ্যমে লেটেন্সি কমানো হয়েছে।

ডিপেন্ডেন্সি

মোশন প্রেডিকশন লাইব্রেরি প্রেডিকশন প্রয়োগ করার সুবিধা প্রদান করে। অ্যাপের মডিউল build.gradle ফাইলে লাইব্রেরি ডিপেন্ডেন্সি হিসেবে যোগ করা হয়েছে:

dependencies {
    implementation "androidx.input:input-motionprediction:1.0.0-beta01"
}

প্রয়োগ

মোশন প্রেডিকশন লাইব্রেরিতে MotionEventPredictor ইন্টারফেস অন্তর্ভুক্ত থাকে, যা নিম্নলিখিত পদ্ধতিগুলি সংজ্ঞায়িত করে:

  • record(): ব্যবহারকারীর অ্যাকশনের রেকর্ড হিসেবে MotionEvent অবজেক্ট স্টোর করে
  • predict(): পূর্বাভাস দেওয়া MotionEvent রিটার্ন করে
MotionEventPredictor-এর একটি ইনস্ট্যান্স ঘোষণা করুন
var motionEventPredictor = MotionEventPredictor.newInstance(view)
প্রেডিক্টরে ডেটা ফিড করুন
motionEventPredictor.record(motionEvent)
পূর্বাভাস দিন

when (motionEvent.action) {
   MotionEvent.ACTION_MOVE -> {
       val predictedMotionEvent = motionEventPredictor?.predict()
       if(predictedMotionEvent != null) {
            // use predicted MotionEvent to inject a new artificial point
       }
   }
}

মোশন প্রেডিকশন সংক্রান্ত করণীয় ও বর্জনীয়

✓ করবেন

নতুন পূর্বাভাসের পয়েন্ট যোগ করা হলে পূর্বাভাসের পয়েন্ট সরিয়ে দিন।

✗ করবেন না

ফাইনাল রেন্ডারিংয়ের জন্য প্রেডিকশন পয়েন্ট ব্যবহার করবেন না।

নোট-নেওয়ার অ্যাপ

ChromeOS আপনার অ্যাপকে কিছু নোট-নেওয়া অ্যাকশন ঘোষণা করার অনুমতি দেয়।

ChromeOS-এ নোট নেওয়ার অ্যাপ হিসেবে কোনও অ্যাপ রেজিস্টার করতে, ইনপুট মানানসই দেখুন।

Android-এ নোট-নেওয়ার অ্যাপ হিসেবে কোনও অ্যাপ রেজিস্টার করতে, নোট-নেওয়ার অ্যাপ তৈরি করুন বিকল্প দেখুন।

Android 14 (API লেভেল 34), ACTION_CREATE_NOTE ইনটেন্ট নিয়ে এসেছে, যা আপনার অ্যাপকে লক স্ক্রিনে নোট নেওয়ার অ্যাক্টিভিটি শুরু করার অনুমতি দেয়।

ML Kit-এর মাধ্যমে ডিজিটাল ইঙ্ক শনাক্তকরণ

ML Kit ডিজিটাল ইঙ্ক শনাক্তকরণ ফিচারের সাহায্যে, আপনার অ্যাপ ডিজিটাল সারফেসে হাতে লেখা টেক্সট শত শত ভাষায় শনাক্ত করতে পারে। এছাড়াও, আপনি স্কেচ ক্লাসিফাই করতে পারবেন।

ML Kit Ink.Stroke.Builder ক্লাস প্রদান করে যাতে Ink অবজেক্ট তৈরি করা যায় যা মেশিন লার্নিং মডেলের মাধ্যমে প্রসেস করে হাতের লেখা টেক্সটে কনভার্ট করা যায়।

হাতের লেখা শনাক্ত করার পাশাপাশি, মডেলটি জেসচার শনাক্ত করতে পারে, যেমন মুছে ফেলা এবং বৃত্ত।

আরও জানতে ডিজিটাল ইঙ্ক শনাক্তকরণ দেখুন।

অতিরিক্ত রিসোর্স

ডেভেলপার নির্দেশিকা

কোডল্যাবস

,

Android এবং ChromeOS বিভিন্ন ধরনের API প্রদান করে যা আপনাকে এমন অ্যাপ তৈরি করতে সাহায্য করে যা ব্যবহারকারীদের একটি ব্যতিক্রমী স্টাইলাস অভিজ্ঞতা প্রদান করে। MotionEvent ক্লাস স্ক্রিনের সাথে স্টাইলাসের ইন্টার‍্যাকশন সম্পর্কে তথ্য প্রকাশ করে, যার মধ্যে স্টাইলাসের চাপ, ওরিয়েন্টেশন, টিল্ট, হোভার ও পাম শনাক্তকরণ অন্তর্ভুক্ত। কম লেটেন্সি গ্রাফিক্স ও মোশন প্রেডিকশন লাইব্রেরি স্টাইলাস অন-স্ক্রিন রেন্ডারিং উন্নত করে যাতে স্বাভাবিক, পেন-ও-কাগজের মতো অভিজ্ঞতা প্রদান করা যায়।

MotionEvent

MotionEvent ক্লাস ব্যবহারকারীর ইনপুট ইন্টার‍্যাকশন দেখায়, যেমন স্ক্রিনে টাচ পয়েন্টারের পজিশন ও মুভমেন্ট। স্টাইলাস ইনপুটের জন্য, MotionEvent এছাড়াও প্রেসার, ওরিয়েন্টেশন, টিল্ট ও হোভার ডেটা প্রকাশ করে।

ইভেন্ট ডেটা

স্টাইলাস MotionEvent অবজেক্ট অ্যাক্সেস করতে, ড্রয়িং সারফেসে pointerInteropFilter মডিফায়ার যোগ করুন। এমন একটি পদ্ধতি সহ ViewModel ক্লাস প্রয়োগ করুন যা মোশন ইভেন্ট প্রসেস করে; pointerInteropFilter মডিফায়ারের onTouchEvent ল্যাম্বডা হিসেবে পদ্ধতিটি পাস করুন:

@Composable
@OptIn(ExperimentalComposeUiApi::class)
fun DrawArea(modifier: Modifier = Modifier) {
    Canvas(
        modifier = modifier
            .clipToBounds()
            .pointerInteropFilter {
                viewModel.processMotionEvent(it)
            }

    ) {
        // Drawing code here.
    }
}

MotionEvent অবজেক্ট UI ইভেন্টের নিম্নলিখিত দিক সম্পর্কিত ডেটা প্রদান করে:

  • অ্যাকশন: ডিভাইসের সাথে ফিজিক্যাল ইন্ট্যার‍্যাকশন—স্ক্রিন টাচ করা, স্ক্রিনের সারফেসের উপর পয়েন্টার সরানো, স্ক্রিনের সারফেসের উপর পয়েন্টার হোভার করা
  • পয়েন্টার: স্ক্রিনের সাথে ইন্টার‍্যাক্ট করা অবজেক্টের শনাক্তকারী—আঙুল, স্টাইলাস, মাউস
  • অ্যাক্সিস: ডেটার ধরন—x ও y কোঅর্ডিনেট, প্রেসার, টিল্ট, ওরিয়েন্টেশন ও হোভার (দূরত্ব)

অ্যাকশন

স্টাইলাস সাপোর্ট প্রয়োগ করতে, ব্যবহারকারী কী অ্যাকশন পারফর্ম করছেন তা আপনাকে বুঝতে হবে।

MotionEvent-এ বিভিন্ন ধরনের ACTION কনস্ট্যান্ট থাকে যা মোশন ইভেন্ট সংজ্ঞায়িত করে। স্টাইলাসের জন্য সবচেয়ে গুরুত্বপূর্ণ অ্যাকশনের মধ্যে নিম্নলিখিতগুলি অন্তর্ভুক্ত:

অ্যাকশন বর্ণনা
ACTION_DOWN
ACTION_POINTER_DOWN
পয়েন্টার স্ক্রিনের সাথে কানেক্ট করেছে।
ACTION_MOVE স্ক্রিনে পয়েন্টার নড়াচড়া করছে।
ACTION_UP
ACTION_POINTER_UP
পয়েন্টার আর স্ক্রিনের সাথে কানেক্ট করা নেই
ACTION_CANCEL আগের বা বর্তমান মোশন সেট কখন বাতিল করা উচিত।

আপনার অ্যাপ ACTION_DOWN হলে নতুন স্ট্রোক শুরু করা, ACTION_MOVE,-এর মাধ্যমে স্ট্রোক আঁকা এবং ACTION_UP ট্রিগার হলে স্ট্রোক শেষ করার মতো টাস্ক পারফর্ম করতে পারে।

নির্দিষ্ট পয়েন্টারের জন্য ACTION_DOWN থেকে ACTION_UP পর্যন্ত MotionEventটি অ্যাকশনের সেটকে মোশন সেট বলা হয়।

পয়েন্টার

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

পয়েন্টার ইনডেক্সের রেঞ্জ শূন্য থেকে শুরু করে MotionEvent#pointerCount() দ্বারা রিটার্ন করা পয়েন্টারের সংখ্যা থেকে ১ বিয়োগ করে পাওয়া সংখ্যা পর্যন্ত হয়।

getAxisValue(axis, pointerIndex) পদ্ধতির মাধ্যমে পয়েন্টারের অক্ষের ভ্যালু অ্যাক্সেস করা যাবে। পয়েন্টার ইনডেক্স বাদ দেওয়া হলে, সিস্টেম প্রথম পয়েন্টার, পয়েন্টার শূন্য (0)-এর জন্য ভ্যালু রিটার্ন করে।

MotionEvent অবজেক্টে ব্যবহার করা পয়েন্টারের ধরন সম্পর্কে তথ্য থাকে। আপনি পয়েন্টার ইনডেক্স ইটারেট করে এবং getToolType(pointerIndex) মেথড কল করে পয়েন্টারের ধরন জানতে পারবেন।

পয়েন্টার সম্পর্কে আরও জানতে, মাল্টি-টাচ জেসচার ম্যানেজ করুন দেখুন।

স্টাইলাস ইনপুট

আপনি TOOL_TYPE_STYLUS-এর মাধ্যমে স্টাইলাস ইনপুট ফিল্টার করতে পারবেন:

val isStylus = TOOL_TYPE_STYLUS == event.getToolType(pointerIndex)

স্টাইলাসটি TOOL_TYPE_ERASER-এর সাথে ইরেজার হিসেবে ব্যবহার করা হয়েছে বলেও রিপোর্ট করতে পারে:

val isEraser = TOOL_TYPE_ERASER == event.getToolType(pointerIndex)

স্টাইলাস অ্যাক্সিস ডেটা

ACTION_DOWN এবং ACTION_MOVE স্টাইলাস সম্পর্কে অক্ষ ডেটা প্রদান করে, যেমন x এবং y কোঅর্ডিনেট, প্রেসার, ওরিয়েন্টেশন, টিল্ট এবং হোভার।

এই ডেটা অ্যাক্সেস করার সুবিধা চালু করতে, MotionEvent API getAxisValue(int) প্রদান করে, যেখানে প্যারামিটারটি নিম্নলিখিত যেকোনও অক্ষ শনাক্তকারী:

অক্ষ getAxisValue()-এর রিটার্ন ভ্যালু
AXIS_X মোশন ইভেন্টের X কোঅর্ডিনেট।
AXIS_Y মোশন ইভেন্টের Y কোঅর্ডিনেট।
AXIS_PRESSURE টাচস্ক্রিন বা টাচপ্যাডের ক্ষেত্রে, আঙুল, স্টাইলাস বা অন্য কোনও পয়েন্টার দিয়ে প্রয়োগ করা চাপ। মাউস বা ট্র্যাকবলের ক্ষেত্রে, প্রাইমারি বোতাম প্রেস করা হলে ১, অন্যথায় ০।
AXIS_ORIENTATION টাচস্ক্রিন বা টাচপ্যাডের জন্য, ডিভাইসের উল্লম্ব প্লেনের সাপেক্ষে আঙুল, স্টাইলাস বা অন্য পয়েন্টারের ওরিয়েন্টেশন।
AXIS_TILT রেডিয়ানে স্টাইলাসের টিল্ট অ্যাঙ্গেল।
AXIS_DISTANCE স্ক্রিন থেকে স্টাইলাসের দূরত্ব।

যেমন, MotionEvent.getAxisValue(AXIS_X) প্রথম পয়েন্টারের জন্য x কোঅর্ডিনেট ফেরত পাঠায়।

এছাড়াও, মাল্টি-টাচ জেসচার ম্যানেজ করা দেখুন।

অবস্থান

আপনি নিম্নলিখিত কলগুলির মাধ্যমে একটি পয়েন্টারের x এবং y স্থানাঙ্কগুলি পুনরুদ্ধার করতে পারেন:

স্ক্রিনে স্টাইলাস দিয়ে আঁকা, যেখানে x ও y কোঅর্ডিনেট ম্যাপ করা আছে।
ছবি ১. স্টাইলাস পয়েন্টারের x এবং y স্ক্রিন কোঅর্ডিনেট।

চাপ

আপনি MotionEvent#getAxisValue(AXIS_PRESSURE) বা প্রথম পয়েন্টারের জন্য, MotionEvent#getPressure()-এর মাধ্যমে পয়েন্টার প্রেসার রিট্রিভ করতে পারবেন।

টাচস্ক্রিন বা টাচপ্যাডের জন্য প্রেসার ভ্যালু হল ০ (কোনও প্রেসার নেই) এবং ১-এর মধ্যে একটি মান, তবে স্ক্রিন ক্যালিব্রেশনের উপর নির্ভর করে আরও বেশি মান রিটার্ন করা যেতে পারে।

স্টাইলাস স্ট্রোক যা কম থেকে বেশি চাপের ধারাবাহিকতা দেখায়। বাঁদিকে স্ট্রোকটি সরু ও হালকা, যা কম চাপের ইঙ্গিত দেয়। স্ট্রোকটি বাঁদিক থেকে ডানদিকে আরও চওড়া এবং গাঢ় হতে থাকে যতক্ষণ না এটি সবচেয়ে ডানদিকে সবচেয়ে চওড়া এবং গাঢ় হয়, যা সর্বোচ্চ চাপ নির্দেশ করে।
ছবি ২. চাপের উপস্থাপনা—বাঁদিকে কম চাপ, ডানদিকে বেশি চাপ।

সজ্জা

স্টাইলাস কোন দিকে পয়েন্ট করছে তা ওরিয়েন্টেশন থেকে বোঝা যায়।

getAxisValue(AXIS_ORIENTATION) বা getOrientation() (প্রথম পয়েন্টারের জন্য) ব্যবহার করে পয়েন্টারের ওরিয়েন্টেশন ফিরিয়ে আনা যাবে।

স্টাইলাসের ক্ষেত্রে, ঘড়ির কাঁটার দিকে ০ থেকে পাই (𝛑) অথবা ঘড়ির কাঁটার বিপরীতে ০ থেকে -পাই-এর মধ্যে রেডিয়ান ভ্যালু হিসেবে ওরিয়েন্টেশন দেখানো হয়।

ওরিয়েন্টেশন আপনাকে বাস্তব জীবনের ব্রাশ প্রয়োগ করতে দেয়। যেমন, স্টাইলাস যদি ফ্ল্যাট ব্রাশের মতো কাজ করে, তাহলে ফ্ল্যাট ব্রাশের প্রস্থ স্টাইলাসের ওরিয়েন্টেশনের উপর নির্ভর করে।

ছবি ৩. স্টাইলাস বাঁদিকে প্রায় মাইনাস .৫৭ রেডিয়ানে পয়েন্ট করছে।

ঝোকানো

স্ক্রিনের সাপেক্ষে স্টাইলাসের ইনক্লিনেশন টিল্ট পরিমাপ করে।

টিল্ট স্টাইলাসের পজিটিভ কোণ রেডিয়ানে দেখায়, যেখানে শূন্য হল স্ক্রিনের সাথে লম্ব এবং 𝛑/২ হল সারফেসের সাথে সমান্তরাল।

getAxisValue(AXIS_TILT) ব্যবহার করে টিল্ট অ্যাঙ্গেল পুনরুদ্ধার করা যাবে (প্রথম পয়েন্টারের জন্য কোনও শর্টকাট নেই)।

বাস্তব জীবনের টুল যতটা সম্ভব কাছাকাছি পুনরুৎপাদন করতে টিল্ট ব্যবহার করা যেতে পারে, যেমন একটি কাত করা পেন্সিল দিয়ে শেডিং অনুকরণ করা।

স্ক্রিনের সারফেস থেকে স্টাইলাস প্রায় ৪০ ডিগ্রি কোণে হেলানো আছে।
ছবি ৪. স্টাইলাস প্রায় .৭৮৫ রেডিয়ান বা লম্ব থেকে ৪৫ ডিগ্রি টিল্ট করা হয়েছে।

উপরে নিয়ে যাওয়া

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

ব্রাশের সাইজের প্রিভিউ দেখতে বা কোনও বোতাম বেছে নেওয়া হচ্ছে তা বোঝাতে স্টাইলাস হোভার ব্যবহার করা যেতে পারে।

ছবি ৫. স্ক্রিনের উপর স্টাইলাস হোভার করছে। স্টাইলাস স্ক্রিনের সারফেস স্পর্শ না করলেও অ্যাপ প্রতিক্রিয়া দেখায়।

মনে রাখবেন: Compose এমন মডিফায়ার প্রদান করে যা UI এলিমেন্টের ইন্টার‍্যাক্টিভ অবস্থাকে প্রভাবিত করে:

  • hoverable: পয়েন্টার এন্টার ও এক্সিট ইভেন্ট ব্যবহার করে হোভার করা যায় এমন কম্পোনেন্ট কনফিগার করুন।
  • indication: ইন্টার‍্যাকশন হলে এই কম্পোনেন্টের জন্য ভিজ্যুয়াল এফেক্ট ড্র করে।

পাম রিজেকশন, নেভিগেশন ও অবাঞ্ছিত ইনপুট

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

ফলস্বরূপ, আপনাকে অবশ্যই ব্যবহারকারীর ইনপুটের ইতিহাস রাখতে হবে যাতে স্ক্রিন থেকে অবাঞ্ছিত টাচ সরানো যায় এবং বৈধ ব্যবহারকারীর ইনপুট আবার রেন্ডার করা যায়।

ACTION_CANCEL এবং FLAG_CANCELED

ACTION_CANCEL এবং FLAG_CANCELED, উভয়কেই ডিজাইন করা হয়েছে যাতে আপনাকে জানানো যায় যে আগের MotionEvent সেটটি শেষ ACTION_DOWN থেকে বাতিল করা উচিত, যাতে আপনি, উদাহরণস্বরূপ, কোনও নির্দিষ্ট পয়েন্টারের জন্য ড্রয়িং অ্যাপের শেষ স্ট্রোকটি আগের অবস্থায় ফিরিয়ে আনতে পারেন।

ACTION_CANCEL

Android 1.0 (API লেভেল ১)-এ যোগ করা হয়েছে

ACTION_CANCEL থেকে বোঝা যায় যে মোশন ইভেন্টের আগের সেট বাতিল করতে হবে।

নিচে উল্লেখ করা যেকোনও একটি শনাক্ত করা হলে ACTION_CANCEL ট্রিগার করা হয়:

  • নেভিগেশন জেসচার
  • পাম রিজেকশন

ACTION_CANCEL ট্রিগার করা হলে, আপনাকে getPointerId(getActionIndex())-এর মাধ্যমে অ্যাক্টিভ পয়েন্টার শনাক্ত করতে হবে। তারপর ইনপুট ইতিহাস থেকে সেই পয়েন্টার দিয়ে তৈরি করা স্ট্রোক সরিয়ে দিন এবং দৃশ্যটি আবার রেন্ডার করুন।

FLAG_CANCELED

Android 13 (API লেভেল 33)-এ যোগ করা হয়েছে

FLAG_CANCELED পয়েন্টার উপরে যাওয়ার অর্থ হল ব্যবহারকারী অনিচ্ছাকৃতভাবে টাচ করেছেন। ব্যবহারকারী ভুলবশত স্ক্রিন টাচ করলে, যেমন ডিভাইসটি ধরে থাকার সময় বা স্ক্রিনে হাতের তালু রাখলে, সাধারণত এই ফ্ল্যাগ সেট করা হয়।

আপনি নিম্নলিখিত উপায়ে ফ্ল্যাগ ভ্যালু অ্যাক্সেস করতে পারবেন:

val cancel = (event.flags and FLAG_CANCELED) == FLAG_CANCELED

ফ্ল্যাগ সেট করা থাকলে, আপনাকে এই পয়েন্টার থেকে শেষ ACTION_DOWN-এর মধ্যে থেকে শেষ MotionEvent সেট আগের অবস্থায় ফিরিয়ে আনতে হবে।

ACTION_CANCEL-এর মতো, getPointerId(actionIndex)-এর সাথে পয়েন্টার পাওয়া যাবে।

ছবি ৬. স্টাইলাস স্ট্রোক ও পাম টাচ MotionEvent সেট তৈরি করে। পাম টাচ বাতিল করা হয়েছে এবং ডিসপ্লে আবার রেন্ডার করা হয়েছে।

ফুল স্ক্রিন, এজ-টু-এজ ও নেভিগেশন জেসচার

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

ছবি ৭. কোনও অ্যাপ ব্যাকগ্রাউন্ডে সরানোর জন্য সোয়াইপ জেসচার।

আপনার অ্যাপে অবাঞ্ছিত টাচ ট্রিগার করা থেকে জেসচারকে আটকাতে, আপনি ইনসেট এবং ACTION_CANCEL-এর সুবিধা নিতে পারেন।

এছাড়াও, পাম রিজেকশন, নেভিগেশন ও অবাঞ্ছিত ইনপুট বিভাগ দেখুন।

অবাঞ্ছিত টাচ ইভেন্ট থেকে নেভিগেশন জেসচার প্রতিরোধ করতে WindowInsetsController-এর setSystemBarsBehavior() পদ্ধতি এবং BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE ব্যবহার করুন:

// Configure the behavior of the hidden system bars.
windowInsetsController.systemBarsBehavior =
    WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE

ইনসেট ও জেসচার ম্যানেজমেন্ট সম্পর্কে আরও জানতে, দেখুন:

কম লেটেন্সি

ব্যবহারকারীর ইনপুট প্রসেস ও রেন্ডার করতে হার্ডওয়্যার, সিস্টেম ও অ্যাপ্লিকেশনের যে সময় লাগে, তাকে লেটেন্সি বলা হয়।

লেটেন্সি = হার্ডওয়্যার ও OS ইনপুট প্রসেসিং + অ্যাপ প্রসেসিং + সিস্টেম কম্পোজিটিং

  • হার্ডওয়্যার রেন্ডারিং
লেটেন্সির কারণে রেন্ডার করা স্ট্রোক স্টাইলাসের পজিশনের থেকে পিছিয়ে থাকে। স্ট্রোক রেন্ডার করা এবং স্টাইলাসের পজিশনের মধ্যে যে ব্যবধান থাকে তা লেটেন্সি হিসেবে দেখানো হয়।
ছবি ৮. লেটেন্সির কারণে রেন্ডার করা স্ট্রোক স্টাইলাসের পজিশনের থেকে পিছিয়ে থাকে।

লেটেন্সির সোর্স

  • টাচস্ক্রিনের (হার্ডওয়্যার) সাথে স্টাইলাস রেজিস্টার করা: প্রাথমিক ওয়্যারলেস কানেকশন যখন স্টাইলাস এবং OS রেজিস্টার এবং সিঙ্ক করার জন্য কমিউনিকেট করে।
  • টাচ স্যাম্পলিং রেট (হার্ডওয়্যার): প্রতি সেকেন্ডে যতবার টাচস্ক্রিন চেক করে দেখে যে কোনও পয়েন্টার সারফেস টাচ করছে কিনা, এটি ৬০ থেকে ১০০০Hz পর্যন্ত হতে পারে।
  • ইনপুট প্রসেসিং (অ্যাপ): ব্যবহারকারীর ইনপুটে রঙ, গ্রাফিক এফেক্ট ও ট্রান্সফর্মেশন প্রয়োগ করা।
  • গ্রাফিক রেন্ডারিং (OS + হার্ডওয়্যার): বাফার সোয়াপিং, হার্ডওয়্যার প্রসেসিং।

লো-লেটেন্সি গ্রাফিক্স

Jetpack লো-লেটেন্সি গ্রাফিক্স লাইব্রেরি ব্যবহারকারীর ইনপুট ও অন-স্ক্রিন রেন্ডারিংয়ের মধ্যে প্রসেসিংয়ের সময় কমায়।

লাইব্রেরি মাল্টি-বাফার রেন্ডারিং এড়িয়ে প্রসেসিংয়ের সময় কমায় এবং ফ্রন্ট-বাফার রেন্ডারিং টেকনিকের সুবিধা নেয়, যার অর্থ হল সরাসরি স্ক্রিনে লেখা।

ফ্রন্ট-বাফার রেন্ডারিং

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

অ্যাপ স্ক্রিন বাফারে লেখে এবং স্ক্রিন বাফার থেকে পড়ে।
ছবি ৯. ফ্রন্ট-বাফার রেন্ডারিং।
অ্যাপ মাল্টি-বাফারে লেখে, যা স্ক্রিন বাফারের সাথে অদলবদল করে। অ্যাপ স্ক্রিন বাফার থেকে পড়ে।
ছবি ১০. মাল্টি-বাফার রেন্ডারিং।

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

Android 10 (API লেভেল ২৯) ও তার পরবর্তী ভার্সনে এবং Android 10 (API লেভেল ২৯) ও তার পরবর্তী ভার্সনে চলা ChromeOS ডিভাইসে লো-লেটেন্সি লাইব্রেরি উপলভ্য।

ডিপেন্ডেন্সি

কম-লেটেন্সি লাইব্রেরি ফ্রন্ট-বাফার রেন্ডারিং প্রয়োগের জন্য কম্পোনেন্ট প্রদান করে। অ্যাপের মডিউল build.gradle ফাইলে লাইব্রেরিটি ডিপেন্ডেন্সি হিসেবে যোগ করা হয়েছে:

dependencies {
    implementation "androidx.graphics:graphics-core:1.0.0-alpha03"
}

GLFrontBufferRenderer কলব্যাক

কম-লেটেন্সি লাইব্রেরিতে GLFrontBufferRenderer.Callback ইন্টারফেস অন্তর্ভুক্ত থাকে, যা নিম্নলিখিত পদ্ধতিগুলি সংজ্ঞায়িত করে:

GLFrontBufferRenderer-এর সাথে আপনি যে ধরনের ডেটা ব্যবহার করেন, লো-লেটেন্সি লাইব্রেরি সেই সম্পর্কে কোনও মতামত দেয় না।

তবে, লাইব্রেরি ডেটা পয়েন্টের শত শত স্ট্রিম হিসেবে ডেটা প্রসেস করে; তাই, মেমরির ব্যবহার ও অ্যালোকেশন অপ্টিমাইজ করার জন্য আপনার ডেটা ডিজাইন করুন।

কলব্যাক

রেন্ডারিং কলব্যাক চালু করতে, GLFrontBufferedRenderer.Callback প্রয়োগ করুন এবং onDrawFrontBufferedLayer() ও onDrawDoubleBufferedLayer() ওভাররাইড করুন। GLFrontBufferedRenderer আপনার ডেটা সবচেয়ে অপ্টিমাইজ করা উপায়ে রেন্ডার করার জন্য কলব্যাক ব্যবহার করে।

val callback = object: GLFrontBufferedRenderer.Callback<DATA_TYPE> {
   override fun onDrawFrontBufferedLayer(
       eglManager: EGLManager,
       bufferInfo: BufferInfo,
       transform: FloatArray,
       param: DATA_TYPE
   ) {
       // OpenGL for front buffer, short, affecting small area of the screen.
   }
   override fun onDrawMultiDoubleBufferedLayer(
       eglManager: EGLManager,
       bufferInfo: BufferInfo,
       transform: FloatArray,
       params: Collection<DATA_TYPE>
   ) {
       // OpenGL full scene rendering.
   }
}
GLFrontBufferedRenderer-এর একটি ইনস্ট্যান্স ঘোষণা করুন

SurfaceView এবং আপনার আগে তৈরি করা কলব্যাক প্রদান করে GLFrontBufferedRenderer প্রস্তুত করুন। GLFrontBufferedRenderer আপনার কলব্যাক ব্যবহার করে ফ্রন্ট ও ডবল বাফারে রেন্ডারিং অপ্টিমাইজ করে:

var glFrontBufferRenderer = GLFrontBufferedRenderer<DATA_TYPE>(surfaceView, callbacks)
রেন্ডার করা হচ্ছে

আপনি renderFrontBufferedLayer() মেথড কল করলে ফ্রন্ট-বাফার রেন্ডারিং শুরু হয়, যা onDrawFrontBufferedLayer() কলব্যাক ট্রিগার করে।

আপনি commit() ফাংশন কল করলে ডবল-বাফার রেন্ডারিং আবার শুরু হয়, যা onDrawMultiDoubleBufferedLayer() কলব্যাক ট্রিগার করে।

নিচের উদাহরণে, ব্যবহারকারী স্ক্রিনে আঁকা শুরু করলে (ACTION_DOWN) এবং পয়েন্টারটি চারপাশে সরালে (ACTION_MOVE) প্রসেসটি ফ্রন্ট বাফারে রেন্ডার করে (দ্রুত রেন্ডারিং)। পয়েন্টারটি স্ক্রিনের সারফেস থেকে সরে গেলে (ACTION_UP) প্রসেসটি ডবল বাফারে রেন্ডার করে।

আপনি requestUnbufferedDispatch() ব্যবহার করে ইনপুট সিস্টেমকে বলতে পারেন যে মোশন ইভেন্ট ব্যাচ না করে, সেগুলি উপলভ্য হওয়ার সাথে সাথেই ডেলিভার করতে:

when (motionEvent.action) {
   MotionEvent.ACTION_DOWN -> {
       // Deliver input events as soon as they arrive.
       view.requestUnbufferedDispatch(motionEvent)
       // Pointer is in contact with the screen.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE)
   }
   MotionEvent.ACTION_MOVE -> {
       // Pointer is moving.
       glFrontBufferRenderer.renderFrontBufferedLayer(DATA_TYPE)
   }
   MotionEvent.ACTION_UP -> {
       // Pointer is not in contact in the screen.
       glFrontBufferRenderer.commit()
   }
   MotionEvent.CANCEL -> {
       // Cancel front buffer; remove last motion set from the screen.
       glFrontBufferRenderer.cancel()
   }
}

রেন্ডারিং সংক্রান্ত করণীয় ও বর্জনীয়

✓ করবেন

স্ক্রিনের ছোট অংশ, হাতের লেখা, ড্রয়িং, স্কেচিং।

✗ করবেন না

ফুলস্ক্রিন আপডেট, প্যানিং, জুমিং। ছিঁড়ে যেতে পারে।

ছিঁড়ে ফেলা

স্ক্রিন বাফার একই সময়ে পরিবর্তন করা হলে স্ক্রিন রিফ্রেশ করার সময় টিয়ারিং হয়। স্ক্রিনের একটি অংশে নতুন ডেটা এবং অন্য অংশে পুরনো ডেটা দেখা যায়।

স্ক্রিন রিফ্রেশ করার সময় টিয়ারিংয়ের কারণে Android ছবির উপরের ও নিচের অংশ মিসঅ্যালাইন হয়ে গেছে।
ছবি ১১. স্ক্রিন উপর থেকে নিচে রিফ্রেশ হওয়ার সময় টিয়ারিং।

মোশন প্রেডিকশন

Jetpack মোশন প্রেডিকশন লাইব্রেরি ব্যবহারকারীর স্ট্রোক পাথ অনুমান করে এবং রেন্ডারারকে সাময়িক, কৃত্রিম পয়েন্ট প্রদান করে অনুভূত লেটেন্সি কমায়।

মোশন প্রেডিকশন লাইব্রেরি MotionEvent অবজেক্ট হিসেবে আসল ব্যবহারকারীর ইনপুট পায়। অবজেক্টে x ও y কোঅর্ডিনেট, প্রেসার ও সময় সংক্রান্ত তথ্য থাকে, যা মোশন প্রেডিক্টর ব্যবহার করে ভবিষ্যতের MotionEvent অবজেক্ট সম্পর্কে অনুমান করে।

পূর্বাভাস দেওয়া MotionEventটি অবজেক্ট শুধুমাত্র অনুমান। অনুমান করা ইভেন্ট, অনুভূত লেটেন্সি কমাতে পারে, তবে অনুমান করা ডেটা, আসল MotionEvent ডেটা পাওয়ার সাথে সাথেই তার সাথে পরিবর্তন করতে হবে।

মোশন প্রেডিকশন লাইব্রেরি Android 4.4 (API লেভেল 19) ও তার পরবর্তী যেকোনও ভার্সনে এবং Android 9 (API লেভেল 28) ও তার পরবর্তী যেকোনও ভার্সনে চলা ChromeOS ডিভাইসে উপলভ্য।

লেটেন্সির কারণে রেন্ডার করা স্ট্রোক স্টাইলাসের পজিশনের থেকে পিছিয়ে থাকে। স্ট্রোক ও স্টাইলাসের মধ্যেকার ফাঁক প্রেডিকশন পয়েন্ট দিয়ে পূরণ করা হয়। বাকি থাকা ব্যবধান হল অনুভূত লেটেন্সি।
ছবি ১২. মোশন প্রেডিকশনের মাধ্যমে লেটেন্সি কমানো হয়েছে।

ডিপেন্ডেন্সি

মোশন প্রেডিকশন লাইব্রেরি প্রেডিকশন প্রয়োগ করার সুবিধা প্রদান করে। অ্যাপের মডিউল build.gradle ফাইলে লাইব্রেরি ডিপেন্ডেন্সি হিসেবে যোগ করা হয়েছে:

dependencies {
    implementation "androidx.input:input-motionprediction:1.0.0-beta01"
}

প্রয়োগ

মোশন প্রেডিকশন লাইব্রেরিতে MotionEventPredictor ইন্টারফেস অন্তর্ভুক্ত থাকে, যা নিম্নলিখিত পদ্ধতিগুলি সংজ্ঞায়িত করে:

  • record(): ব্যবহারকারীর অ্যাকশনের রেকর্ড হিসেবে MotionEvent অবজেক্ট স্টোর করে
  • predict(): পূর্বাভাস দেওয়া MotionEvent রিটার্ন করে
MotionEventPredictor-এর একটি ইনস্ট্যান্স ঘোষণা করুন
var motionEventPredictor = MotionEventPredictor.newInstance(view)
প্রেডিক্টরে ডেটা ফিড করুন
motionEventPredictor.record(motionEvent)
পূর্বাভাস দিন

when (motionEvent.action) {
   MotionEvent.ACTION_MOVE -> {
       val predictedMotionEvent = motionEventPredictor?.predict()
       if(predictedMotionEvent != null) {
            // use predicted MotionEvent to inject a new artificial point
       }
   }
}

মোশন প্রেডিকশন সংক্রান্ত করণীয় ও বর্জনীয়

✓ করবেন

নতুন পূর্বাভাসের পয়েন্ট যোগ করা হলে পূর্বাভাসের পয়েন্ট সরিয়ে দিন।

✗ করবেন না

ফাইনাল রেন্ডারিংয়ের জন্য প্রেডিকশন পয়েন্ট ব্যবহার করবেন না।

নোট-নেওয়ার অ্যাপ

ChromeOS আপনার অ্যাপকে কিছু নোট-নেওয়া অ্যাকশন ঘোষণা করার অনুমতি দেয়।

ChromeOS-এ নোট নেওয়ার অ্যাপ হিসেবে কোনও অ্যাপ রেজিস্টার করতে, ইনপুট মানানসই দেখুন।

Android-এ নোট-নেওয়ার অ্যাপ হিসেবে কোনও অ্যাপ রেজিস্টার করতে, নোট-নেওয়ার অ্যাপ তৈরি করুন বিকল্প দেখুন।

Android 14 (API লেভেল 34), ACTION_CREATE_NOTE ইনটেন্ট নিয়ে এসেছে, যা আপনার অ্যাপকে লক স্ক্রিনে নোট নেওয়ার অ্যাক্টিভিটি শুরু করার অনুমতি দেয়।

ML Kit-এর মাধ্যমে ডিজিটাল ইঙ্ক শনাক্তকরণ

ML Kit ডিজিটাল ইঙ্ক শনাক্তকরণ ফিচারের সাহায্যে, আপনার অ্যাপ ডিজিটাল সারফেসে হাতে লেখা টেক্সট শত শত ভাষায় শনাক্ত করতে পারে। এছাড়াও, আপনি স্কেচ ক্লাসিফাই করতে পারবেন।

ML Kit Ink.Stroke.Builder ক্লাস প্রদান করে যাতে Ink অবজেক্ট তৈরি করা যায় যা মেশিন লার্নিং মডেলের মাধ্যমে প্রসেস করে হাতের লেখা টেক্সটে কনভার্ট করা যায়।

হাতের লেখা শনাক্ত করার পাশাপাশি, মডেলটি জেসচার শনাক্ত করতে পারে, যেমন মুছে ফেলা এবং বৃত্ত।

আরও জানতে ডিজিটাল ইঙ্ক শনাক্তকরণ দেখুন।

অতিরিক্ত রিসোর্স

ডেভেলপার নির্দেশিকা

কোডল্যাবস