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 স্থানাঙ্কগুলি পুনরুদ্ধার করতে পারেন:
MotionEvent#getAxisValue(AXIS_X)অথবাMotionEvent#getX()MotionEvent#getAxisValue(AXIS_Y)অথবাMotionEvent#getY()
চাপ
আপনি
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()
}
}
রেন্ডারিং সংক্রান্ত করণীয় ও বর্জনীয়
স্ক্রিনের ছোট অংশ, হাতের লেখা, ড্রয়িং, স্কেচিং।
ফুলস্ক্রিন আপডেট, প্যানিং, জুমিং। ছিঁড়ে যেতে পারে।
ছিঁড়ে ফেলা
স্ক্রিন বাফার একই সময়ে পরিবর্তন করা হলে স্ক্রিন রিফ্রেশ করার সময় টিয়ারিং হয়। স্ক্রিনের একটি অংশে নতুন ডেটা এবং অন্য অংশে পুরনো ডেটা দেখা যায়।
মোশন প্রেডিকশন
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 স্থানাঙ্কগুলি পুনরুদ্ধার করতে পারেন:
MotionEvent#getAxisValue(AXIS_X)অথবাMotionEvent#getX()MotionEvent#getAxisValue(AXIS_Y)অথবাMotionEvent#getY()
চাপ
আপনি
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()
}
}
রেন্ডারিং সংক্রান্ত করণীয় ও বর্জনীয়
স্ক্রিনের ছোট অংশ, হাতের লেখা, ড্রয়িং, স্কেচিং।
ফুলস্ক্রিন আপডেট, প্যানিং, জুমিং। ছিঁড়ে যেতে পারে।
ছিঁড়ে ফেলা
স্ক্রিন বাফার একই সময়ে পরিবর্তন করা হলে স্ক্রিন রিফ্রেশ করার সময় টিয়ারিং হয়। স্ক্রিনের একটি অংশে নতুন ডেটা এবং অন্য অংশে পুরনো ডেটা দেখা যায়।
মোশন প্রেডিকশন
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 অবজেক্ট তৈরি করা যায় যা মেশিন লার্নিং মডেলের মাধ্যমে প্রসেস করে
হাতের লেখা টেক্সটে কনভার্ট করা যায়।
হাতের লেখা শনাক্ত করার পাশাপাশি, মডেলটি জেসচার শনাক্ত করতে পারে, যেমন মুছে ফেলা এবং বৃত্ত।
আরও জানতে ডিজিটাল ইঙ্ক শনাক্তকরণ দেখুন।