এক নজরে ড্রয়েবল

'কম্পোজ' ফিচার ব্যবহার করে দেখুন
Jetpack Compose হল Android-এর জন্য সাজেস্ট করা UI টুলকিট। Compose-এ কীভাবে গ্রাফিক্স দেখাতে হয় তা জানুন।

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

ক্লাস কনস্ট্রাক্টর ব্যবহার করা ছাড়াও Drawable ডিফাইন ও ইনস্ট্যানশিয়েট করার দুটি উপায় আছে:

  • আপনার প্রোজেক্টে সেভ করা কোনও ইমেজ রিসোর্স (একটি বিটম্যাপ ফাইল) ইনফলেশন করুন।
  • ড্রয়েবল প্রপার্টি নির্ধারণ করে এমন XML রিসোর্স ইনফলেশন করুন।

মনে রাখবেন: এর পরিবর্তে, আপনি হয়ত ভেক্টর ড্রয়েবল ব্যবহার করতে পছন্দ করবেন, যা সংশ্লিষ্ট রঙের তথ্য সহ পয়েন্ট, লাইন ও কার্ভের একটি সেট দিয়ে কোনও ছবিকে সংজ্ঞায়িত করে। এর ফলে, কোয়ালিটি নষ্ট না করেই বিভিন্ন সাইজের জন্য ভেক্টর ড্রয়েবল স্কেল করা যায়। আরও তথ্যের জন্য, Vector ড্রয়েবল ওভারভিউ দেখুন।

রিসোর্স ছবি থেকে ড্রয়েবল তৈরি করা

আপনার প্রজেক্ট রিসোর্স থেকে কোনও ইমেজ ফাইল রেফারেন্স করে আপনার অ্যাপে গ্রাফিক্স যোগ করতে পারবেন। PNG (সাজেস্ট করা), JPG (গ্রহণযোগ্য) এবং GIF (ব্যবহার না করাই ভাল) ফাইল আপলোড করা যাবে। অ্যাপ আইকন, লোগো এবং অন্যান্য গ্রাফিক্স, যেমন গেমের মধ্যে ব্যবহৃত গ্রাফিক্স, এই টেকনিকের জন্য উপযুক্ত।

ইমেজ রিসোর্স ব্যবহার করতে, আপনার প্রোজেক্টের res/drawable/ ডিরেক্টরিতে ফাইল যোগ করুন। প্রোজেক্টে থাকা অবস্থায়, আপনার কোড বা XML লেআউট থেকে ইমেজ রিসোর্স রেফারেন্স করতে পারবেন। যাই হোক, এটি একটি রিসোর্স আইডি ব্যবহার করে উল্লেখ করা হয়, যা হল ফাইল টাইপ এক্সটেনশন ছাড়া ফাইলের নাম। যেমন, my_image.png-কে my_image হিসেবে উল্লেখ করুন।

মনে রাখবেন: বিল্ড প্রসেস চলাকালীন aapt টুল res/drawable/ ডিরেক্টরিতে থাকা ইমেজ রিসোর্সকে লসলেস ইমেজ কম্প্রেশন ব্যবহার করে অটোমেটিক অপ্টিমাইজ করতে পারে। যেমন, ২৫৬টির বেশি রঙের প্রয়োজন নেই এমন একটি ট্রু-কালার PNG রঙের প্যালেট সহ ৮-বিট PNG-তে কনভার্ট করা হতে পারে। এর ফলে একই কোয়ালিটির ছবি তৈরি হয়, তবে এর জন্য কম মেমরি প্রয়োজন হয়। এর ফলে, এই ডিরেক্টরিতে রাখা ইমেজ বাইনারি বিল্ড করার সময় পরিবর্তন হতে পারে। আপনি যদি কোনও ছবিকে বিটম্যাপে কনভার্ট করার জন্য বিটস্ট্রিম হিসেবে পড়ার পরিকল্পনা করেন, তাহলে আপনার ছবিগুলিকে res/raw/ ফোল্ডারে রাখুন, যেখানে aapt টুল সেগুলিকে পরিবর্তন করে না।

নিচের কোড স্নিপেট থেকে কীভাবে ImageView তৈরি করতে হয় তা জানতে পারবেন, এটি ড্রয়েবল রিসোর্স থেকে তৈরি করা ছবি ব্যবহার করে এবং সেটি লেআউটে যোগ করে:

Kotlin

private lateinit var constraintLayout: ConstraintLayout

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Instantiate an ImageView and define its properties
    val i = ImageView(this).apply {
        setImageResource(R.drawable.my_image)
        contentDescription = resources.getString(R.string.my_image_desc)

        // set the ImageView bounds to match the Drawable's dimensions
        adjustViewBounds = true
        layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT)
    }

    // Create a ConstraintLayout in which to add the ImageView
    constraintLayout = ConstraintLayout(this).apply {

        // Add the ImageView to the layout.
        addView(i)
    }

    // Set the layout as the content view.
    setContentView(constraintLayout)
}

জাভা

ConstraintLayout constraintLayout;

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  // Create a ConstraintLayout in which to add the ImageView
  constraintLayout = new ConstraintLayout(this);

  // Instantiate an ImageView and define its properties
  ImageView i = new ImageView(this);
  i.setImageResource(R.drawable.my_image);
  i.setContentDescription(getResources().getString(R.string.my_image_desc));

  // set the ImageView bounds to match the Drawable's dimensions
  i.setAdjustViewBounds(true);
  i.setLayoutParams(new ViewGroup.LayoutParams(
          ViewGroup.LayoutParams.WRAP_CONTENT,
          ViewGroup.LayoutParams.WRAP_CONTENT));

  // Add the ImageView to the layout and set the layout as the content view.
  constraintLayout.addView(i);
  setContentView(constraintLayout);
}

অন্যান্য ক্ষেত্রে, আপনি নিজের ইমেজ রিসোর্সকে Drawable অবজেক্ট হিসেবে ম্যানেজ করতে চাইতে পারেন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

Kotlin

val myImage: Drawable = ResourcesCompat.getDrawable(context.resources, R.drawable.my_image, null)

জাভা

Resources res = context.getResources();
Drawable myImage = ResourcesCompat.getDrawable(res, R.drawable.my_image, null);

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

নিচের XML স্নিপেট থেকে বোঝা যাবে যে XML লেআউটে কীভাবে ImageView-এ ড্রয়েবল রিসোর্স যোগ করা যায়:

<ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/my_image"
        android:contentDescription="@string/my_image_desc" />

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

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

XML রিসোর্স থেকে ড্রয়েবল তৈরি করা

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

XML-এ আপনার Drawable নির্দিষ্ট করার পরে, আপনার প্রোজেক্টের res/drawable/ ডিরেক্টরিতে ফাইলটি সেভ করুন। নিচে দেওয়া উদাহরণে এমন XML দেখানো হয়েছে যা TransitionDrawable রিসোর্সকে সংজ্ঞায়িত করে, যা Drawable থেকে ইনহেরিট করা হয়:

<!-- res/drawable/expand_collapse.xml -->
<transition xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/image_expand"/>
    <item android:drawable="@drawable/image_collapse"/>
</transition>

তারপরে, Resources#getDrawable() কল করে এবং আপনার XML ফাইলের রিসোর্স আইডি পাস করে অবজেক্টটি রিট্রিভ ও ইনস্ট্যানশিয়েট করুন। inflate() মেথড কাজ করে এমন যেকোনও Drawable সাবক্লাস XML-এ ডিফাইন করা এবং আপনার অ্যাপের মাধ্যমে ইনস্ট্যানশিয়েট করা যেতে পারে।

XML ইনফ্লেশন কাজ করে এমন প্রতিটি ড্রয়েবল ক্লাস নির্দিষ্ট XML অ্যাট্রিবিউট ব্যবহার করে যা অবজেক্ট প্রপার্টি নির্ধারণ করতে সাহায্য করে। নিচের কোডটি TransitionDrawable ইনস্ট্যানশিয়েট করে এবং এটিকে ImageView অবজেক্টের কন্টেন্ট হিসেবে সেট করে:

Kotlin

val transition= ResourcesCompat.getDrawable(
        context.resources,
        R.drawable.expand_collapse,
        null
) as TransitionDrawable

val image: ImageView = findViewById(R.id.toggle_image)
image.setImageDrawable(transition)

// Description of the initial state that the drawable represents.
image.contentDescription = resources.getString(R.string.collapsed)

// Then you can call the TransitionDrawable object's methods.
transition.startTransition(1000)

// After the transition is complete, change the image's content description
// to reflect the new state.

জাভা

Resources res = context.getResources();
TransitionDrawable transition =
    (TransitionDrawable) ResourcesCompat.getDrawable(res, R.drawable.expand_collapse, null);

ImageView image = (ImageView) findViewById(R.id.toggle_image);
image.setImageDrawable(transition);

// Description of the initial state that the drawable represents.
image.setContentDescription(getResources().getString(R.string.collapsed));

// Then you can call the TransitionDrawable object's methods.
transition.startTransition(1000);

// After the transition is complete, change the image's content description
// to reflect the new state.

কাজ করে এমন XML অ্যাট্রিবিউট সম্পর্কে আরও জানতে, উপরে তালিকাভুক্ত ক্লাস দেখুন।

শেপ ড্রয়েবল

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

ShapeDrawable হল Drawable-এর সাবক্লাস। এই কারণে, যেখানে Drawable প্রত্যাশিত সেখানে আপনি ShapeDrawable ব্যবহার করতে পারবেন। যেমন, আপনি ভিউয়ের setBackgroundDrawable() মেথডে পাস করে ভিউয়ের ব্যাকগ্রাউন্ড সেট করতে ShapeDrawable অবজেক্ট ব্যবহার করতে পারেন। এছাড়াও, আপনি নিজের কাস্টম ভিউ হিসেবে আকৃতি আঁকতে এবং আপনার অ্যাপের লেআউটে যোগ করতে পারবেন।

ShapeDrawable-এর নিজস্ব draw() মেথড থাকার কারণে, আপনি View-এর একটি সাবক্লাস তৈরি করতে পারেন যা onDraw() ইভেন্টের সময় ShapeDrawable অবজেক্ট ড্র করে, যেমনটি নিচের কোড উদাহরণে দেখানো হয়েছে:

Kotlin

class CustomDrawableView(context: Context) : View(context) {
    private val drawable: ShapeDrawable = run {
        val x = 10
        val y = 10
        val width = 300
        val height = 50
        contentDescription = context.resources.getString(R.string.my_view_desc)

        ShapeDrawable(OvalShape()).apply {
            // If the color isn't set, the shape uses black as the default.
            paint.color = 0xff74AC23.toInt()
            // If the bounds aren't set, the shape can't be drawn.
            setBounds(x, y, x + width, y + height)
        }
    }

    override fun onDraw(canvas: Canvas) {
        drawable.draw(canvas)
    }
}

জাভা

public class CustomDrawableView extends View {
  private ShapeDrawable drawable;

  public CustomDrawableView(Context context) {
    super(context);

    int x = 10;
    int y = 10;
    int width = 300;
    int height = 50;
    setContentDescription(context.getResources().getString(
            R.string.my_view_desc));

    drawable = new ShapeDrawable(new OvalShape());
    // If the color isn't set, the shape uses black as the default.
    drawable.getPaint().setColor(0xff74AC23);
    // If the bounds aren't set, the shape can't be drawn.
    drawable.setBounds(x, y, x + width, y + height);
  }

  protected void onDraw(Canvas canvas) {
    drawable.draw(canvas);
  }
}

আপনি উপরে দেওয়া CustomDrawableView কোড স্যাম্পেলে ক্লাস ব্যবহার করতে পারেন, ঠিক যেভাবে অন্য কোনও কাস্টম ভিউ ব্যবহার করেন। যেমন, আপনি প্রোগ্রামাটিক পদ্ধতিতে আপনার অ্যাপের অ্যাক্টিভিটিতে এটি যোগ করতে পারেন, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

Kotlin

private lateinit var customDrawableView: CustomDrawableView

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    customDrawableView = CustomDrawableView(this)

    setContentView(customDrawableView)
}

জাভা

CustomDrawableView customDrawableView;

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  customDrawableView = new CustomDrawableView(this);

  setContentView(customDrawableView);
}

পরিবর্তে, আপনি যদি XML লেআউটে কাস্টম ভিউ ব্যবহার করতে চান, তাহলে CustomDrawableView ক্লাসকে অবশ্যই View(Context, AttributeSet) কনস্ট্রাক্টর ওভাররাইড করতে হবে, যা ক্লাসটি XML থেকে ইনফ্লেট করার সময় কল করা হয়। XML লেআউটে কীভাবে CustomDrawableView ঘোষণা করতে হয় তা নিম্নলিখিত উদাহরণ থেকে দেখুন:

<com.example.shapedrawable.CustomDrawableView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />

ShapeDrawable ক্লাসের মতো android.graphics.drawable প্যাকেজের অন্যান্য অনেক ড্রয়েবল ধরনের মাধ্যমে আপনি পাবলিক মেথড ব্যবহার করে অবজেক্টের বিভিন্ন প্রপার্টি নির্ধারণ করতে পারবেন। কিছু উদাহরণ প্রপার্টি যা আপনি অ্যাডজাস্ট করতে চাইতে পারেন তার মধ্যে আলফা ট্রান্সপারেন্সি, কালার ফিল্টার, ডিথার, অস্বচ্ছতা এবং রঙ অন্তর্ভুক্ত।

এছাড়াও, আপনি XML রিসোর্স ব্যবহার করে আদিম ড্রয়েবল শেপ নির্ধারণ করতে পারবেন। আরও তথ্যের জন্য, ড্রয়েবল রিসোর্স প্রকার-এর মধ্যে শেপ ড্রয়েবল দেখুন।

NinePatch ড্রয়েবল

NinePatchDrawable গ্রাফিক হল একটি প্রসারিত করা যায় এমন বিটম্যাপ ছবি যা আপনি ভিউয়ের ব্যাকগ্রাউন্ড হিসেবে ব্যবহার করতে পারেন। Android ভিউয়ের কন্টেন্ট যাতে দেখা যায় সেই জন্য গ্রাফিকের সাইজ অটোমেটিক পরিবর্তন করে। NinePatch ছবির ব্যবহারের একটি উদাহরণ হল স্ট্যান্ডার্ড Android বোতামের ব্যাকগ্রাউন্ড—বিভিন্ন দৈর্ঘ্যের স্ট্রিংয়ের জন্য বোতামগুলিকে প্রসারিত করতে হবে। A NinePatch গ্রাফিক হল একটি সাধারণ PNG ছবি যার মধ্যে অতিরিক্ত ১-পিক্সেল বর্ডার থাকে। এটি আপনার প্রোজেক্টের res/drawable/ ডিরেক্টরিতে 9.png এক্সটেনশন সহ সেভ করতে হবে।

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

এছাড়াও, আপনি ছবির একটি ঐচ্ছিক ড্রয়িংযোগ্য বিভাগ (কার্যকরভাবে, প্যাডিং লাইন) নির্ধারণ করতে পারেন, এর জন্য ডানদিকে একটি লাইন এবং নিচে একটি লাইন আঁকতে হবে। কোনও View অবজেক্ট যদি NinePatch গ্রাফিককে তার ব্যাকগ্রাউন্ড হিসেবে সেট করে এবং তারপরে ভিউয়ের টেক্সট নির্দিষ্ট করে, তাহলে এটি নিজেকে এমনভাবে প্রসারিত করে যাতে সমস্ত টেক্সট শুধুমাত্র ডান এবং নিচের লাইন (অন্তর্ভুক্ত থাকলে) দ্বারা নির্ধারিত জায়গা দখল করে। প্যাডিং লাইন অন্তর্ভুক্ত না করা থাকলে, Android এই ড্রয়েবল এরিয়াকে সংজ্ঞায়িত করতে বাঁদিকের ও উপরের লাইন ব্যবহার করে।

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

ছবি ১-এ বোতামের সংজ্ঞা দেওয়ার জন্য ব্যবহৃত NinePatch গ্রাফিক্সের একটি উদাহরণ দেখানো হয়েছে:

স্ট্রেচ করা যায় এমন অংশ
ও প্যাডিং বক্সের ছবি

ছবি ১: বোতামকে সংজ্ঞায়িত করে এমন NinePatch গ্রাফিক্সের উদাহরণ

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

৯-প্যাচ আঁকুন টুলটি WYSIWYG গ্রাফিক্স এডিটর ব্যবহার করে আপনার NinePatch ছবি তৈরি করার একটি অত্যন্ত সহজ উপায় অফার করে। এমনকি, আপনি যদি স্ট্রেচেবল এরিয়ার জন্য এমন কোনও অঞ্চল বেছে নেন যেখানে পিক্সেল রেপ্লিকেশনের ফলে ড্রয়িং আর্টিফ্যাক্ট তৈরি হওয়ার ঝুঁকি থাকে, তাহলে এটি সতর্কবার্তা দেয়।

নিচে দেওয়া স্যাম্পেল লেআউট XML থেকে বোঝা যাবে যে কীভাবে কয়েকটি বোতামে NinePatch গ্রাফিক যোগ করতে হয়। NinePatch ছবিটি res/drawable/my_button_background.9.png-এ সেভ করা হয়।

<Button android:id="@+id/tiny"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerInParent="true"
        android:text="Tiny"
        android:textSize="8sp"
        android:background="@drawable/my_button_background"/>

<Button android:id="@+id/big"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerInParent="true"
        android:text="Biiiiiiig text!"
        android:textSize="30sp"
        android:background="@drawable/my_button_background"/>

মনে রাখবেন, টেক্সটের চারপাশে বোতামটি যাতে সুন্দরভাবে ফিট করে, সেই জন্য layout_width এবং layout_height অ্যাট্রিবিউট wrap_content হিসেবে সেট করা হয়েছে।

Figure 2-এ XML ও NinePatch ছবি থেকে রেন্ডার করা দুটি বোতাম দেখানো হয়েছে যা উপরে দেখানো হয়েছে। লক্ষ্য করুন, টেক্সট অনুযায়ী বোতামের দৈর্ঘ্য ও প্রস্থ কীভাবে পরিবর্তিত হয় এবং ব্যাকগ্রাউন্ড ছবি সেটিকে জায়গা করে দেওয়ার জন্য প্রসারিত হয়।

ছোট ও
সাধারণ সাইজের বোতামের ছবি

ছবি ২: XML রিসোর্স ও NinePatch গ্রাফিক ব্যবহার করে রেন্ডার করা বোতাম

কাস্টম ড্রয়েবল

আপনি কিছু কাস্টম ড্রয়িং তৈরি করতে চাইলে, Drawable ক্লাস (বা এর যেকোনও সাবক্লাস) এক্সটেন্ড করে তা করতে পারবেন।

সবচেয়ে গুরুত্বপূর্ণ পদ্ধতি হল draw(Canvas) কারণ এটি Canvas অবজেক্ট প্রদান করে যা আপনাকে অবশ্যই ড্রয়িং সংক্রান্ত নির্দেশাবলী প্রদান করতে ব্যবহার করতে হবে।

নিচের কোডটি Drawable-এর একটি সাধারণ সাবক্লাস দেখায় যা একটি বৃত্ত আঁকে:

Kotlin

class MyDrawable : Drawable() {
    private val redPaint: Paint = Paint().apply { setARGB(255, 255, 0, 0) }

    override fun draw(canvas: Canvas) {
        // Get the drawable's bounds
        val width: Int = bounds.width()
        val height: Int = bounds.height()
        val radius: Float = Math.min(width, height).toFloat() / 2f

        // Draw a red circle in the center
        canvas.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), radius, redPaint)
    }

    override fun setAlpha(alpha: Int) {
        // This method is required
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        // This method is required
    }

    override fun getOpacity(): Int =
        // Must be PixelFormat.UNKNOWN, TRANSLUCENT, TRANSPARENT, or OPAQUE
        PixelFormat.OPAQUE
}

জাভা

public class MyDrawable extends Drawable {
    private final Paint redPaint;

    public MyDrawable() {
        // Set up color and text size
        redPaint = new Paint();
        redPaint.setARGB(255, 255, 0, 0);
    }

    @Override
    public void draw(Canvas canvas) {
        // Get the drawable's bounds
        int width = getBounds().width();
        int height = getBounds().height();
        float radius = Math.min(width, height) / 2;

        // Draw a red circle in the center
        canvas.drawCircle(width/2, height/2, radius, redPaint);
    }

    @Override
    public void setAlpha(int alpha) {
        // This method is required
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        // This method is required
    }

    @Override
    public int getOpacity() {
        // Must be PixelFormat.UNKNOWN, TRANSLUCENT, TRANSPARENT, or OPAQUE
        return PixelFormat.OPAQUE;
    }
}

তারপরে, আপনি যেখানে চান সেখানে আপনার ড্রয়েবল যোগ করতে পারবেন, যেমন এখানে দেখানো হয়েছে সেইভাবে ImageView-এ:

Kotlin

val myDrawing = MyDrawable()
val image: ImageView = findViewById(R.id.imageView)
image.setImageDrawable(myDrawing)
image.contentDescription = resources.getString(R.string.my_image_desc)

জাভা

MyDrawable mydrawing = new MyDrawable();
ImageView image = findViewById(R.id.imageView);
image.setImageDrawable(mydrawing);
image.setContentDescription(getResources().getString(R.string.my_image_desc));

এছাড়াও, Android 7.0 (API লেভেল 24) ও তার পরবর্তী যেকোনও ভার্সনে, আপনি নিম্নলিখিত উপায়ে XML-এর মাধ্যমে নিজের কাস্টম ড্রয়েবল এর ইনস্ট্যান্স নির্ধারণ করতে পারবেন:

  • XML এলিমেন্টের নাম হিসেবে সম্পূর্ণভাবে উপযুক্ত ক্লাস নেম ব্যবহার করা। এই পদ্ধতির জন্য, কাস্টম ড্রয়েবল ক্লাসকে অবশ্যই একটি পাবলিক টপ-লেভেল ক্লাস হতে হবে:
    <com.myapp.MyDrawable xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="#ffff0000" />
  • XML ট্যাগ নেম হিসেবে drawable ব্যবহার করা এবং ক্লাস অ্যাট্রিবিউট থেকে সম্পূর্ণ-কোয়ালিফায়েড ক্লাসের নাম নির্দিষ্ট করা। এই পদ্ধতিটি পাবলিক টপ-লেভেল ক্লাস এবং পাবলিক স্ট্যাটিক ইনার ক্লাসের জন্য ব্যবহার করা যেতে পারে:
    <drawable xmlns:android="http://schemas.android.com/apk/res/android"
        class="com.myapp.MyTopLevelClass$MyDrawable"
        android:color="#ffff0000" />

ড্রয়েবল আইটেমে টিন্ট যোগ করা

Android 5.0 (API লেভেল 21) ও এর পরবর্তী যেকোনও ভার্সনে, আপনি বিটম্যাপ ও নাইন-প্যাচকে আলফা মাস্ক হিসেবে ডিফাইন করতে পারবেন। আপনি কালার রিসোর্স বা থিম অ্যাট্রিবিউট দিয়ে সেগুলিকে টিন্ট করতে পারেন, যা কালার রিসোর্স (যেমন, ?android:attr/colorPrimary) হিসেবে সমাধান করে। সাধারণত, আপনি এইসব অ্যাসেট একবারই তৈরি করেন এবং আপনার থিমের সাথে ম্যাচ করার জন্য সেগুলি অটোমেটিক কালার করেন।

আপনি BitmapDrawable, NinePatchDrawable বা VectorDrawable অবজেক্টে setTint() পদ্ধতির মাধ্যমে টিন্ট প্রয়োগ করতে পারবেন। এছাড়াও, আপনি android:tint এবং android:tintMode অ্যাট্রিবিউট ব্যবহার করে লেআউটে টিন্ট কালার ও মোড সেট করতে পারেন।

ছবি থেকে গুরুত্বপূর্ণ রঙ এক্সট্র্যাক্ট করা

Android Support Library-তে Palette ক্লাস অন্তর্ভুক্ত থাকে, যা আপনাকে কোনও ছবি থেকে বিশিষ্ট রঙ এক্সট্র্যাক্ট করতে দেয়। আপনি নিজের ড্রয়েবলকে Bitmap হিসেবে লোড করতে এবং এর রঙ অ্যাক্সেস করার জন্য Palette-এ পাস করতে পারবেন। আরও তথ্যের জন্য, Palette API-এর সাহায্যে রঙ বেছে নেওয়া নিবন্ধটি পড়ুন।