কাস্টম অ্যাটর্স সংজ্ঞায়িত করা হচ্ছে


472

আমার নিজের মতো করে নিজস্ব বৈশিষ্ট্যগুলি প্রয়োগ করতে হবে com.android.R.attr

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


20
এই দস্তাবেজগুলি আপনার পোস্টের
চেয়েও

আমি কাস্টম বৈশিষ্ট্যাবলী সম্পর্কে উদাহরণ সহ একটি চমৎকার নিবন্ধটি সুপারিশ করছি: এমসিএমবাইলওয়্যার.আর
২০১/0 /

একটি ছোট কাজের উদাহরণ সহায়ক হতে পারে: github.com/yujiaao/ MergeLayout1
ইউ জিয়াও

উত্তর:


971

বর্তমানে সেরা ডকুমেন্টেশন হ'ল উত্স। আপনি এখানে এটি একবার দেখতে পারেন (attrs.xML)

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

একটি <attr>উপাদান দুটি এক্সএমএল বৈশিষ্ট্য nameএবং formatnameআপনাকে এটিকে কিছু বলতে দেয় এবং কোডের মধ্যে যেমন এটি উল্লেখ করা শেষ হয় তেমনি R.attr.my_attributeformatঅ্যাট্রিবিউট 'টাইপ' অ্যাট্রিবিউট এর যদি আপনি চান তার উপর নির্ভর করে বিভিন্ন মান থাকতে পারে।

  • রেফারেন্স - যদি এটি অন্য কোনও উত্স আইডির উল্লেখ করে (যেমন, "@ রঙ / আমার_ রঙ", "@ লেআউট / মাই_লআউট")
  • রঙ
  • বুলিয়ান
  • মাত্রা
  • ভাসা
  • পূর্ণসংখ্যা
  • দড়ি
  • ভগ্নাংশ
  • enum - সাধারণত অন্তর্নিহিত সংজ্ঞায়িত
  • পতাকা - সাধারণত অন্তর্নিহিত সংজ্ঞায়িত

আপনি |উদাহরণস্বরূপ, ব্যবহার করে একাধিক ধরণের বিন্যাস সেট করতে পারেন format="reference|color"

enum বৈশিষ্ট্যগুলি নিম্নলিখিত হিসাবে সংজ্ঞায়িত করা যায়:

<attr name="my_enum_attr">
  <enum name="value1" value="1" />
  <enum name="value2" value="2" />
</attr>

flag মানগুলি সংজ্ঞায়িত করা প্রয়োজন ব্যতীত বৈশিষ্ট্যগুলি সমান হয় যাতে তারা একসাথে কিছুটা

<attr name="my_flag_attr">
  <flag name="fuzzy" value="0x01" />
  <flag name="cold" value="0x02" />
</attr>

গুণাবলী ছাড়াও <declare-styleable>উপাদান রয়েছে। এটি আপনাকে কাস্টম দর্শনটি ব্যবহার করতে পারে এমন বৈশিষ্ট্যগুলি সংজ্ঞায়িত করতে দেয়। আপনি কোনও <attr>উপাদান নির্দিষ্ট করে এটি করেন, যদি এটি পূর্বনির্ধারিত হয় তবে আপনি এটি নির্দিষ্ট করে না format। যদি আপনি কোনও অ্যান্ড্রয়েড অ্যাটরকে পুনরায় ব্যবহার করতে চান, উদাহরণস্বরূপ, অ্যান্ড্রয়েড: মাধ্যাকর্ষণ, তবে আপনি নীচে এটি করতে পারেন name

একটি কাস্টম দর্শন উদাহরণ <declare-styleable>:

<declare-styleable name="MyCustomView">
  <attr name="my_custom_attribute" />
  <attr name="android:gravity" />
</declare-styleable>

আপনার কাস্টম ভিউতে এক্সএমএলে আপনার কাস্টম বৈশিষ্ট্যগুলি সংজ্ঞায়িত করার সময় আপনাকে কয়েকটি জিনিস করতে হবে। আপনার বৈশিষ্ট্যগুলি খুঁজতে প্রথমে আপনাকে অবশ্যই একটি নেমস্পেস ঘোষণা করতে হবে। আপনি এটি মূল বিন্যাস উপাদানটিতে করেন। সাধারণত আছে xmlns:android="http://schemas.android.com/apk/res/android"। আপনি এখন যোগ করতে হবে xmlns:whatever="http://schemas.android.com/apk/res-auto"

উদাহরণ:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:whatever="http://schemas.android.com/apk/res-auto"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">

    <org.example.mypackage.MyCustomView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:gravity="center"
      whatever:my_custom_attribute="Hello, world!" />
</LinearLayout>

অবশেষে, সেই কাস্টম বৈশিষ্ট্যটি অ্যাক্সেস করতে আপনি সাধারণত আপনার কাস্টম ভিউর কনস্ট্রাক্টরে নিম্নরূপ করুন।

public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);

  TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);

  String str = a.getString(R.styleable.MyCustomView_my_custom_attribute);

  //do something with str

  a.recycle();
}

শেষ। :)


14
এখানে একটি নমুনা প্রকল্প রয়েছে যা একটি কাস্টম দিয়ে ব্যবহারের জন্য কাস্টম বৈশিষ্ট্যগুলি দেখায় View: github.com/commonsguy/cw-advandroid/tree/master/Views/…
CommonsWare

7
আপনি যদি কোনও লাইব্রেরি প্রকল্পের কাস্টম অ্যাটর্স ব্যবহার করছেন: এই প্রশ্নটি দেখুন: stackoverflow.com/questions/5819369/… - এটি ব্যবহার করা হয় বলে মনে হচ্ছে xmlns:my="http://schemas.android.com/apk/lib/my.namespace"- কোনও অনুলিপি করা Attrs.xML নেই। নোটস্পেসের ইউআরআই পাথটি অবশ্যই / apk / * lib * নয় / apk / res হওয়া উচিত Note
thom_nic

2
@ থমনিচলস apk/libএকটি গ্রন্থাগার প্রকল্পের রেফারেন্স ফর্ম্যাট সহ কাস্টম বৈশিষ্ট্যে আমার জন্য কাজ করে নি। কি করেনি কাজ ব্যবহার ছিল apk/res-autoহিসাবে প্রস্তাব, stackoverflow.com/a/13420366/22904 এবং মাত্র নিচের এছাড়াও stackoverflow.com/a/10217752
Giulio Piancastelli

1
@ কিবার্টিকাসের উদ্ধৃতি দিয়ে: "পতাকাগুলির বৈশিষ্ট্যগুলি মানগুলি সংজ্ঞায়িত করার প্রয়োজন ব্যতীত একই রকম হয় যাতে এগুলি একসাথে বিট করা যায়"। আমার মতে এটি enumএবং এর মধ্যে মূল পার্থক্যকে হ্রাস করার মতো flag: পূর্ববর্তীটি আমাদের একটি এবং শুধুমাত্র একটি মান বাছাই করতে দেয়, পরবর্তীটি আমাদের বেশ কয়েকটিকে একত্রিত করতে দেয়। আমি এখানে একটি অনুরূপ প্রশ্নে একটি দীর্ঘ উত্তর লিখেছিলাম , এবং এখন এই প্রশ্নটি পেয়ে আমি অনুভব করেছি যে আমি এটির সাথে লিঙ্ক করব।
র‌্যাড হারিং

5
a.recycle()স্মৃতি মুক্ত করার জন্য এখানে খুব গুরুত্বপূর্ণ
তাশ পেমিভা

87

কিবার্টিকাসের উত্তরটি ভাল তবে একটি দরকারী বিশদ অনুপস্থিত। আপনি যদি একটি লাইব্রেরিতে এগুলি প্রয়োগ করেন তবে প্রতিস্থাপন করুন:

xmlns:whatever="http://schemas.android.com/apk/res/org.example.mypackage"

সঙ্গে:

xmlns:whatever="http://schemas.android.com/apk/res-auto"

অন্যথায় অ্যাপ্লিকেশন যা গ্রন্থাগারটি ব্যবহার করে তাতে রানটাইম ত্রুটি থাকবে।


3
এটি কেবল সম্প্রতি যুক্ত করা হয়েছিল ... কয়েক সপ্তাহ আগে আমার মনে হয়। নিশ্চয়ই এটি যুক্ত করা হয়েছিল কবার্তিকাস তার উত্তর লেখার অনেক পরে।
আর্টঅফ ওয়ারফেয়ার

12
আমি মনে করি এটি এর চেয়েও পুরনো, তবে এটি অবশ্যই যুক্ত করা হয়েছিল কবার্টিকাস তার উত্তর লেখার অনেক পরে। তাকে দোষ দিচ্ছেন না, কেবল একটি দরকারী বিশদ যুক্ত করুন।
নিল মিলার

11
বিভ্রান্তি রক্ষা করতে আমি apk / res-auto ব্যবহারের জন্য Qbericus এর উত্তর আপডেট করেছি।
সূচনা 17

15

উপরের উত্তরটি কয়েকটি জিনিস বাদ দিয়ে সমস্ত কিছু দুর্দান্তভাবে কভার করে।

প্রথমত, যদি কোনও শৈলী না থাকে, তবে (Context context, AttributeSet attrs)পদ্ধতিটি স্বাক্ষরটি পছন্দটি ইনস্ট্যান্ট করতে ব্যবহৃত হবে। context.obtainStyledAttributes(attrs, R.styleable.MyCustomView)এক্ষেত্রে কেবল টাইপড্রেই পেতে ব্যবহার করুন ।

দ্বিতীয়ত এটি প্লুরালসের সংস্থানগুলি (পরিমাণের স্ট্রিং) কীভাবে মোকাবেলা করতে হবে তা কভার করে না। এগুলি টাইপড্রাই ব্যবহার করে মোকাবেলা করা যাবে না। এখানে আমার সেকবারপ্রিফারেন্সির একটি কোড স্নিপেট রয়েছে যা পছন্দের সংক্ষিপ্তসারটিকে অগ্রাধিকারের মান অনুসারে এর মানটিকে বিন্যাস করে sets পছন্দের জন্য xML যদি অ্যান্ড্রয়েড সেট করে: কোনও পাঠ্য স্ট্রিংয়ের একটি সংক্ষিপ্তসার বা স্ট্রিংটিকে পছন্দ করে দেওয়া পছন্দটির মানটিকে স্ট্রিংয়ে ফর্ম্যাট করা হয় (মানটি তুলতে এটিতে এটি% d থাকা উচিত)। যদি অ্যান্ড্রয়েড: সংক্ষিপ্তসারটি বহুবিধ সংস্থানে সেট করা থাকে, তবে ফলাফলটি ফর্ম্যাট করতে এটি ব্যবহৃত হয়।

// Use your own name space if not using an android resource.
final static private String ANDROID_NS = 
    "http://schemas.android.com/apk/res/android";
private int pluralResource;
private Resources resources;
private String summary;

public SeekBarPreference(Context context, AttributeSet attrs) {
    // ...
    TypedArray attributes = context.obtainStyledAttributes(
        attrs, R.styleable.SeekBarPreference);
    pluralResource =  attrs.getAttributeResourceValue(ANDROID_NS, "summary", 0);
    if (pluralResource !=  0) {
        if (! resources.getResourceTypeName(pluralResource).equals("plurals")) {
            pluralResource = 0;
        }
    }
    if (pluralResource ==  0) {
        summary = attributes.getString(
            R.styleable.SeekBarPreference_android_summary);
    }
    attributes.recycle();
}

@Override
public CharSequence getSummary() {
    int value = getPersistedInt(defaultValue);
    if (pluralResource != 0) {
        return resources.getQuantityString(pluralResource, value, value);
    }
    return (summary == null) ? null : String.format(summary, value);
}

  • এটি কেবল একটি উদাহরণ হিসাবে দেওয়া হয়েছে, তবে আপনি যদি পছন্দটি স্ক্রিনে সংক্ষিপ্তসারটি সেট করতে প্রলুব্ধ হন, তবে আপনাকে notifyChanged()পছন্দের onDialogClosedপদ্ধতিতে কল করতে হবে ।

5

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

পদক্ষেপ 1: একটি কাস্টম ভিউ ক্লাস তৈরি করুন।

public class CustomView extends FrameLayout {
    private TextView titleView;

    public CustomView(Context context) {
        super(context);
        init(null, 0, 0);
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(attrs, 0, 0);
    }

    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs, defStyleAttr, 0);
    }

    @RequiresApi(21)
    public CustomView(
            Context context, 
            AttributeSet attrs,
            int defStyleAttr,
            int defStyleRes) {

        super(context, attrs, defStyleAttr, defStyleRes);
        init(attrs, defStyleAttr, defStyleRes);
    }

    public void setTitle(String title) {
        titleView.setText(title);
    }

    private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        inflate(getContext(), R.layout.custom_view, this);

        titleView = findViewById(R.id.title_view);
    }
}

পদক্ষেপ 2: values/attrs.xmlরিসোর্স ফাইলে একটি স্ট্রিং বৈশিষ্ট্য নির্ধারণ করুন:

<resources>
    <declare-styleable name="CustomView">
        <attr name="title" format="string"/>
    </declare-styleable>
</resources>

পদক্ষেপ 3: প্রয়োগ @StringHandlerকরতে টীকা setTitleপদ্ধতি যখন দৃশ্য স্ফীত হয় ক্ষুদ্র দুরবিনবিশেষ ফ্রেমওয়ার্ক রুট অ্যাট্রিবিউট মান এই পদ্ধতিতে বলতে।

@HandlesString(attributeId = R.styleable.CustomView_title)
public void setTitle(String title) {
    titleView.setText(title);
}

এখন আপনার ক্লাসে একটি স্পাইগ্লাস টিকা রয়েছে, স্পাইগ্লাস ফ্রেমওয়ার্কটি এটি সংকলন-সময় সনাক্ত করে এবং স্বয়ংক্রিয়ভাবে CustomView_SpyglassCompanionশ্রেণিটি তৈরি করবে ।

পদক্ষেপ 4: কাস্টম ভিউয়ের initপদ্ধতিতে উত্পন্ন শ্রেণিটি ব্যবহার করুন :

private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    inflate(getContext(), R.layout.custom_view, this);

    titleView = findViewById(R.id.title_view);

    CustomView_SpyglassCompanion
            .builder()
            .withTarget(this)
            .withContext(getContext())
            .withAttributeSet(attrs)
            .withDefaultStyleAttribute(defStyleAttr)
            .withDefaultStyleResource(defStyleRes)
            .build()
            .callTargetMethodsNow();
}

এটাই. এখন আপনি যখন এক্সএমএল থেকে ক্লাসটি ইনস্ট্যান্ট করেন, স্পাইগ্লাসের সহযোগী বৈশিষ্ট্যগুলি ব্যাখ্যা করে এবং প্রয়োজনীয় পদ্ধতিতে কল দেয়। উদাহরণস্বরূপ, যদি আমরা নীচের লেআউটটি স্ফীত করি তবে আর্গুমেন্ট হিসাবে setTitleডাকা হবে "Hello, World!"

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:width="match_parent"
    android:height="match_parent">

    <com.example.CustomView
        android:width="match_parent"
        android:height="match_parent"
        app:title="Hello, World!"/>
</FrameLayout>

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

আরও তথ্য এবং উদাহরণের জন্য গিথুব রেপোতে দেখুন।


আপনি গুগল ডেটা বাইন্ডিংয়ের সাথে এটি অর্জন করতে পারেন - নির্দিষ্ট বৈশিষ্ট্যের জন্য যদি কোনও অ্যাট্রিবিউট বন্ডিং না থাকে, জিডিবি সেট * পদ্ধতিটি আবিষ্কার করার চেষ্টা করে এবং পরিবর্তে এটি ব্যবহার করে। এই ক্ষেত্রে আপনাকে লিখতে হবে, বলুন android:title="@{&quot;Hello, world!&quot;}"
ভূত

0

যদি আপনি উপাদান formatথেকে বৈশিষ্ট্য বাদ দেন attr, আপনি এটি এক্সএমএল লেআউট থেকে কোনও শ্রেণি রেফারেন্স করতে ব্যবহার করতে পারেন।

  • উদাহরণস্বরূপ atrs.xML থেকে ।
  • অ্যান্ড্রয়েড স্টুডিও বুঝতে পারে যে ক্লাসটি এক্সএমএল থেকে রেফারেন্স করা হচ্ছে
    • অর্থাত
      • Refactor > Rename কাজ
      • Find Usages কাজ
      • এবং তাই ...

... / src / main / res / মান / attrs.xML এ কোনও formatবৈশিষ্ট্য নির্দিষ্ট করবেন না

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="MyCustomView">
        ....
        <attr name="give_me_a_class"/>
        ....
    </declare-styleable>

</resources>

এটি কোনও লেআউট ফাইলটিতে ব্যবহার করুন ...

<?xml version="1.0" encoding="utf-8"?>
<SomeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- make sure to use $ dollar signs for nested classes -->
    <MyCustomView
        app:give_me_a_class="class.type.name.Outer$Nested/>

    <MyCustomView
        app:give_me_a_class="class.type.name.AnotherClass/>

</SomeLayout>

আপনার দর্শন শুরুর কোডটিতে শ্রেণি পার্স করুন ...

class MyCustomView(
        context:Context,
        attrs:AttributeSet)
    :View(context,attrs)
{
    // parse XML attributes
    ....
    private val giveMeAClass:SomeCustomInterface
    init
    {
        context.theme.obtainStyledAttributes(attrs,R.styleable.ColorPreference,0,0).apply()
        {
            try
            {
                // very important to use the class loader from the passed-in context
                giveMeAClass = context::class.java.classLoader!!
                        .loadClass(getString(R.styleable.MyCustomView_give_me_a_class))
                        .newInstance() // instantiate using 0-args constructor
                        .let {it as SomeCustomInterface}
            }
            finally
            {
                recycle()
            }
        }
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.