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

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

MotionEvent

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

ইভেন্ট ডেটা

如需访问 MotionEvent 数据,请为组件添加 pointerInput 修饰符:

@Composable
fun Greeting() {
    Text(
        text = "Hello, Android!", textAlign = TextAlign.Center, style = TextStyle(fontSize = 5.em),
        modifier = Modifier
            .pointerInput(Unit) {
                awaitEachGesture {
                    while (true) {
                        val event = awaitPointerEvent()
                        event.changes.forEach { println(it) }
                    }
                }
            },
    )
}

একটি 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() মাইনাস 1 দ্বারা প্রত্যাবর্তিত পয়েন্টারের সংখ্যা পর্যন্ত।

পয়েন্টারগুলির অক্ষ মানগুলি 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 একটি টাচস্ক্রিন বা টাচপ্যাডের জন্য, আঙুল, লেখনী বা অন্য পয়েন্টার দ্বারা চাপ প্রয়োগ করা হয়। একটি মাউস বা ট্র্যাকবলের জন্য, প্রাথমিক বোতাম টিপলে 1, অন্যথায় 0।
AXIS_ORIENTATION একটি টাচস্ক্রিন বা টাচপ্যাডের জন্য, ডিভাইসের উল্লম্ব সমতলের সাপেক্ষে একটি আঙুল, লেখনী বা অন্য পয়েন্টারের অভিযোজন।
AXIS_TILT রেডিয়ানে লেখনীর কাত কোণ।
AXIS_DISTANCE পর্দা থেকে লেখনীর দূরত্ব।

উদাহরণস্বরূপ, MotionEvent.getAxisValue(AXIS_X) প্রথম পয়েন্টারের জন্য x স্থানাঙ্ক প্রদান করে।

এছাড়াও দেখুন মাল্টি-টাচ অঙ্গভঙ্গি পরিচালনা করুন

অবস্থান

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

ম্যাপ করা x এবং y স্থানাঙ্ক সহ স্ক্রিনে স্টাইলাস অঙ্কন।
চিত্র 1. একটি স্টাইলাস পয়েন্টারের X এবং y স্ক্রীন স্থানাঙ্ক।

চাপ

আপনি MotionEvent#getAxisValue(AXIS_PRESSURE) বা প্রথম পয়েন্টারের জন্য, MotionEvent#getPressure() দিয়ে পয়েন্টার চাপ পুনরুদ্ধার করতে পারেন।

টাচস্ক্রিন বা টাচপ্যাডের চাপের মান হল 0 (চাপ নেই) এবং 1-এর মধ্যে একটি মান, কিন্তু স্ক্রীন ক্রমাঙ্কনের উপর নির্ভর করে উচ্চতর মান ফেরত দেওয়া যেতে পারে।

স্টাইলাস স্ট্রোক যা নিম্ন থেকে উচ্চ চাপের ধারাবাহিকতা উপস্থাপন করে। স্ট্রোকটি বাম দিকে সংকীর্ণ এবং অজ্ঞান, নিম্নচাপ নির্দেশ করে। স্ট্রোকটি বাম থেকে ডানে প্রশস্ত এবং গাঢ় হয় যতক্ষণ না এটি ডানদিকে প্রশস্ত এবং অন্ধকার হয়, সর্বোচ্চ চাপ নির্দেশ করে।
চিত্র 2. চাপের উপস্থাপনা—বামে নিম্ন চাপ, ডানদিকে উচ্চ চাপ।

ওরিয়েন্টেশন

ওরিয়েন্টেশন নির্দেশ করে যে লেখনীটি কোন দিকে নির্দেশ করছে।

পয়েন্টার অভিযোজন getAxisValue(AXIS_ORIENTATION) বা getOrientation() (প্রথম পয়েন্টারের জন্য) ব্যবহার করে পুনরুদ্ধার করা যেতে পারে।

একটি লেখনীর জন্য, স্থিতিবিন্যাসটি 0 থেকে pi (𝛑) ঘড়ির কাঁটার দিকে বা 0 থেকে -pi ঘড়ির কাঁটার বিপরীতে রেডিয়ান মান হিসাবে ফেরত দেওয়া হয়।

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

চিত্র 3. লেখনী বাম দিকে নির্দেশ করছে বিয়োগ .57 রেডিয়ান।

কাত

কাত পর্দার সাপেক্ষে লেখনীর প্রবণতা পরিমাপ করে।

টিল্ট রেডিয়ানে লেখনীর ধনাত্মক কোণ প্রদান করে, যেখানে শূন্য পর্দার লম্ব এবং 𝛑/2 পৃষ্ঠের উপর সমতল।

কাত কোণ getAxisValue(AXIS_TILT) ব্যবহার করে পুনরুদ্ধার করা যেতে পারে (প্রথম পয়েন্টারের জন্য কোন শর্টকাট নেই)।

কাত পেন্সিলের সাহায্যে শেডিং নকল করার মতো বাস্তব-জীবনের সরঞ্জামগুলি যতটা সম্ভব কাছাকাছি পুনরুত্পাদন করতে ব্যবহার করা যেতে পারে।

স্টাইলাস পর্দার পৃষ্ঠ থেকে প্রায় 40 ডিগ্রী ঝুঁকেছে।
চিত্র 4. লেখনী প্রায় .785 রেডিয়ানে বা লম্ব থেকে 45 ডিগ্রিতে কাত।

হোভার

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

স্টাইলাস হোভার ব্রাশের আকারের পূর্বরূপ দেখতে বা একটি বোতাম নির্বাচন করা হচ্ছে তা নির্দেশ করতে ব্যবহার করা যেতে পারে।

চিত্র 5. স্টাইলাস একটি স্ক্রিনের উপর ঘোরাফেরা করছে। স্টাইলাস স্ক্রীন পৃষ্ঠকে স্পর্শ না করলেও অ্যাপ প্রতিক্রিয়া দেখায়।

দ্রষ্টব্য: রচনা সংশোধক সরবরাহ করে যা UI উপাদানগুলির ইন্টারেক্টিভ অবস্থাকে প্রভাবিত করে:

  • hoverable : পয়েন্টার এন্টার এবং এক্সিট ইভেন্ট ব্যবহার করে কম্পোনেন্টকে হোভারেবল করতে কনফিগার করুন।
  • indication : মিথস্ক্রিয়া ঘটলে এই উপাদানটির জন্য ভিজ্যুয়াল প্রভাব আঁকে।

পাম প্রত্যাখ্যান, নেভিগেশন, এবং অবাঞ্ছিত ইনপুট

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

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

ACTION_CANCEL এবং FLAG_CANCELED৷

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

ACTION_CANCEL

Android 1.0 (API স্তর 1) এ যোগ করা হয়েছে

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) দিয়ে পাওয়া যেতে পারে।

চিত্র 6. স্টাইলাস স্ট্রোক এবং পামের স্পর্শ MotionEvent সেট তৈরি করে। পাম স্পর্শ বাতিল করা হয়েছে, এবং প্রদর্শন পুনরায় রেন্ডার করা হয়েছে।

সম্পূর্ণ স্ক্রীন, প্রান্ত থেকে প্রান্ত, এবং নেভিগেশন অঙ্গভঙ্গি

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

চিত্র 7. একটি অ্যাপকে ব্যাকগ্রাউন্ডে সরানোর জন্য অঙ্গভঙ্গি সোয়াইপ করুন।

আপনার অ্যাপে অবাঞ্ছিত ছোঁয়া ট্রিগার করা থেকে অঙ্গভঙ্গি প্রতিরোধ করতে, আপনি ইনসেট এবং 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

ইনসেট এবং অঙ্গভঙ্গি ব্যবস্থাপনা সম্পর্কে আরও জানতে, দেখুন:

কম বিলম্ব

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

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

  • হার্ডওয়্যার রেন্ডারিং
লেটেন্সি রেন্ডার করা স্ট্রোককে লেখনীর অবস্থান থেকে পিছিয়ে দেয়। রেন্ডার করা স্ট্রোক এবং স্টাইলাস অবস্থানের মধ্যে ব্যবধানটি বিলম্বের প্রতিনিধিত্ব করে।
চিত্র 8. লেটেন্সি রেন্ডার করা স্ট্রোককে লেখনীর অবস্থান থেকে পিছিয়ে দেয়।

বিলম্বের উৎস

  • টাচস্ক্রিন (হার্ডওয়্যার) সহ স্টাইলাস নিবন্ধন করা: যখন স্টাইলাস এবং OS নিবন্ধিত এবং সিঙ্ক করার জন্য যোগাযোগ করে তখন প্রাথমিক বেতার সংযোগ।
  • টাচ স্যাম্পলিং রেট (হার্ডওয়্যার): একটি টাচস্ক্রিন প্রতি সেকেন্ডে কতবার একটি পয়েন্টার পৃষ্ঠকে স্পর্শ করছে কিনা তা পরীক্ষা করে, 60 থেকে 1000Hz পর্যন্ত।
  • ইনপুট প্রক্রিয়াকরণ (অ্যাপ): ব্যবহারকারীর ইনপুটে রঙ, গ্রাফিক প্রভাব এবং রূপান্তর প্রয়োগ করা।
  • গ্রাফিক রেন্ডারিং (OS + হার্ডওয়্যার): বাফার সোয়াপিং, হার্ডওয়্যার প্রসেসিং।

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

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

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

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

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

অ্যাপ স্ক্রিন বাফারে লেখে এবং স্ক্রিন বাফার থেকে রিড করে।
চিত্র 9. ফ্রন্ট-বাফার রেন্ডারিং।
অ্যাপ মাল্টি-বাফারে লেখে, যা স্ক্রিন বাফারের সাথে অদলবদল করে। অ্যাপ স্ক্রিন বাফার থেকে রিড করে।
চিত্র 10. মাল্টি-বাফার রেন্ডারিং।

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

লো-লেটেন্সি লাইব্রেরি Android 10 (API লেভেল 29) এবং উচ্চতর থেকে এবং Android 10 (API লেভেল 29) এবং উচ্চতর চলমান 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-এর একটি উদাহরণ ঘোষণা করুন

GLFrontBufferedRenderer প্রস্তুত করুন SurfaceView এবং কলব্যাকগুলি প্রদান করে যা আপনি আগে তৈরি করেছেন। 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()
   }
}

রেন্ডারিং করা এবং না করা

✓ করুন

পর্দার ছোট অংশ, হাতের লেখা, অঙ্কন, স্কেচিং।

✗ করবেন না

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

ছিঁড়ে যাওয়া

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

স্ক্রীন রিফ্রেশ হওয়ার সময় ছিঁড়ে যাওয়ার কারণে অ্যান্ড্রয়েড ছবির উপরের এবং নীচের অংশগুলি ভুলভাবে সংযোজন করা হয়েছে৷
চিত্র 11. স্ক্রীন হিসাবে ছিঁড়ে যাওয়া উপরে থেকে নীচে রিফ্রেশ হয়।

গতির পূর্বাভাস

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

মোশন পূর্বাভাস লাইব্রেরি MotionEvent অবজেক্ট হিসাবে বাস্তব ব্যবহারকারীর ইনপুট পায়। বস্তুগুলিতে x এবং y স্থানাঙ্ক, চাপ এবং সময় সম্পর্কে তথ্য রয়েছে, যা ভবিষ্যতের MotionEvent অবজেক্টের ভবিষ্যদ্বাণী করার জন্য গতি ভবিষ্যদ্বাণী দ্বারা লিভারেজ করা হয়।

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

গতির পূর্বাভাস লাইব্রেরি Android 4.4 (API স্তর 19) এবং উচ্চতর এবং Android 9 (API স্তর 28) এবং উচ্চতর চলমান ChromeOS ডিভাইসগুলিতে উপলব্ধ।

লেটেন্সি রেন্ডার করা স্ট্রোককে লেখনীর অবস্থান থেকে পিছিয়ে দেয়। স্ট্রোক এবং লেখনীর মধ্যে ফাঁক ভবিষ্যদ্বাণী পয়েন্ট দিয়ে ভরা হয়. অবশিষ্ট ব্যবধান হল অনুভূত লেটেন্সি।
চিত্র 12. গতির পূর্বাভাস দ্বারা লেটেন্সি হ্রাস করা হয়েছে।

নির্ভরতা

গতি ভবিষ্যদ্বাণী লাইব্রেরি ভবিষ্যদ্বাণী বাস্তবায়ন প্রদান করে. লাইব্রেরিটি অ্যাপের মডিউল 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 14 (API স্তর 34), ACTION_CREATE_NOTE অভিপ্রায় চালু করেছে, যা আপনার অ্যাপকে লক স্ক্রিনে একটি নোট নেওয়ার কার্যকলাপ শুরু করতে সক্ষম করে।

এমএল কিট সহ ডিজিটাল কালি স্বীকৃতি

এমএল কিট ডিজিটাল কালি শনাক্তকরণের মাধ্যমে, আপনার অ্যাপটি শত শত ভাষায় ডিজিটাল পৃষ্ঠে হাতে লেখা পাঠ্যকে চিনতে পারে। আপনি স্কেচ শ্রেণীবদ্ধ করতে পারেন.

এমএল কিট Ink বস্তু তৈরি করতে Ink.Stroke.Builder ক্লাস প্রদান করে যা মেশিন লার্নিং মডেল দ্বারা প্রক্রিয়া করা যেতে পারে হাতের লেখাকে পাঠ্যে রূপান্তর করতে।

হাতের লেখার স্বীকৃতি ছাড়াও, মডেলটি অঙ্গভঙ্গি চিনতে সক্ষম, যেমন মুছে ফেলা এবং বৃত্ত।

আরও জানতে ডিজিটাল কালি স্বীকৃতি দেখুন।

অতিরিক্ত সম্পদ

বিকাশকারী গাইড

কোডল্যাব