অ্যান্ড্রয়েড - একটি কাস্টম (যৌগিক) উপাদান রচনা


132

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

আমি সাধারণত উপাদান ভিত্তিক ফ্রেমওয়ার্কগুলিতে যা করি তা হ'ল সবকিছুকে কাস্টম উপাদানগুলিতে বিভক্ত করা। প্রতিটি কাস্টম উপাদান তখন একটি পরিষ্কার দায়িত্ব থাকবে। এতে এতে নিজস্ব উপাদানগুলির সেট এবং সেই উপাদানটির সাথে সম্পর্কিত অন্যান্য সমস্ত যুক্তি রয়েছে contain

এটি কীভাবে করা যায় তা আমি সনাক্ত করার চেষ্টা করেছি এবং অ্যান্ড্রয়েড ডকুমেন্টেশনে আমি তাদের একটি "যৌগিক নিয়ন্ত্রণ" বলতে পছন্দ করি এমন কিছু পেয়েছি। (দেখুন http://developer.android.com/guide/topics/ui/custom-components.html# কম্পাউন্ড এবং "যৌগিক নিয়ন্ত্রণ" বিভাগে স্ক্রোল করুন) আমি একটি এক্সএমএল ফাইলের উপর ভিত্তি করে এমন একটি উপাদান তৈরি করতে চাই কাঠামো দেখুন।

ডকুমেন্টেশনে এটি বলে:

মনে রাখবেন যে কোনও ক্রিয়াকলাপের মতো আপনিও অন্তর্ভুক্ত উপাদানগুলি তৈরি করার জন্য ঘোষণামূলক (এক্সএমএল-ভিত্তিক) পদ্ধতির ব্যবহার করতে পারেন, বা আপনার কোড থেকে প্রোগ্রামিয়ালি এগুলি বাসাতে পারেন।

ঠিক আছে, এটি একটি ভাল খবর! এক্সএমএল-ভিত্তিক পদ্ধতিটি আমি যা চাই ঠিক তাই! তবে এটি কীভাবে করবেন তা বলে না, এটি "কার্যকলাপের সাথে যেমন হয়" তবে ... তবে আমি একটি ক্রিয়াকলাপে যা করি তা setContentView(...)এক্সএমএল থেকে মতামত উত্সাহিত করার আহ্বান । আপনি যদি সাবক্লাসের উদাহরণ হিসাবে ব্যবহার করেন তবে সেই পদ্ধতিটি উপলভ্য নয় LinearLayout

সুতরাং আমি এক্সএমএলটিকে ম্যানুয়ালি এইভাবে স্ফীত করার চেষ্টা করেছি:

public class MyCompoundComponent extends LinearLayout {

    public MyCompoundComponent(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.my_layout, this);
    }
}

এটি এক্সএমএল যে আমি লোড করছি LinearLayoutতা মূল উপাদান হিসাবে ঘোষণা করেছে তা বাদ দিয়ে এটি কাজ করে । এর ফলে স্ফীতিত LinearLayoutহওয়া বাচ্চা হওয়ার MyCompoundComponentফলে ইতিমধ্যে এটি নিজেই একটি LinearLayout!! সুতরাং এখন আমাদের মধ্যে একটি অপ্রয়োজনীয় লিনিয়ারলআউট এবং MyCompoundComponentএটির দৃষ্টিভঙ্গি আসলে দরকার।

অপ্রয়োজনীয় LinearLayoutতাত্ক্ষণিক কাজ এড়ানো থেকে দয়া করে কেউ আমাকে আরও কাছে যাওয়ার আরও ভাল উপায় সরবরাহ করতে পারেন ?


14
আমি এমন প্রশ্নগুলি পছন্দ করি যা থেকে আমি কিছু শিখি। ধন্যবাদ।
জেরেমি লোগান

5
আমি সম্প্রতি এটি সম্পর্কে একটি ব্লগ এন্ট্রি লিখেছি: blog.jteam.nl/2009/10/08/exploring-the-world-of-android-part-3
টম ভ্যান জুম্মেরেন

উত্তর:


101

আপনার এক্সএমএল রুট হিসাবে মার্জ ট্যাগটি ব্যবহার করুন

<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Your Layout -->
</merge>

এই নিবন্ধটি পরীক্ষা করুন।


10
আপনাকে অনেক ধন্যবাদ! আমি ঠিক তাই খুঁজছিলাম। এত দীর্ঘ প্রশ্নের এত সংক্ষিপ্ত উত্তর কীভাবে থাকতে পারে তা অবাক করে। অসাধারণ!
টম ভ্যান জুম্মেরেন

আড়াআড়ি এই মার্জ লেআউট আইক্লিং সম্পর্কে কি?
কোস্তাদিন

2
@ টিম্ম্ম হাহাহাহাহা ভিজ্যুয়াল এডিটর থাকার আগেই আমি এই প্রশ্নটি জিজ্ঞাসা করেছি :)
টম ভ্যান জুম্মেরেন

0

আমার মনে হয় আপনি যেভাবে এটি করার কথা বলেছিলেন তা হ'ল XML মূল উপাদান হিসাবে আপনার শ্রেণীর নামটি ব্যবহার করুন:

<com.example.views.MyView xmlns:....
       android:orientation="vertical" etc.>
    <TextView android:id="@+id/text" ... />
</com.example.views.MyView>

এবং তারপরে আপনার ক্লাসটি আপনি যে কোনও লেআউটটি ব্যবহার করতে চান তা থেকে নেওয়া হয়েছে। দ্রষ্টব্য যে আপনি যদি এই পদ্ধতিটি ব্যবহার করেন তবে আপনি এখানে বিন্যাসের স্ফীতক ব্যবহার করবেন না

public class MyView extends LinearLayout
{
    public ConversationListItem(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }
    public ConversationListItem(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
    }


    public void setData(String text)
    {
        mTextView.setText(text);
    }

    private TextView mTextView;

    @Override
    protected void onFinishInflate()
    {
        super.onFinishInflate();

        mTextView = (TextView)findViewById(R.id.text);
    }
}

এবং তারপরে আপনি এক্সএমএল লেআউটে আপনার ভিউটি স্বাভাবিক হিসাবে ব্যবহার করতে পারেন। আপনি যদি প্রোগ্রামটি ভিউটি তৈরি করতে চান তবে আপনাকে নিজেই এটি ফুলে উঠতে হবে:

MyView v = (MyView)inflater.inflate(R.layout.my_view, parent, false);

দুর্ভাগ্যক্রমে এটি আপনাকে করতে v = new MyView(context)দেয় না কারণ নেস্টেড লেআউটগুলি সমস্যাটির আশেপাশে কোনও উপায় বলে মনে হচ্ছে না, সুতরাং এটি সত্যই কোনও সম্পূর্ণ সমাধান নয়। MyViewএটিকে কিছুটা সুন্দর করার জন্য আপনি এই জাতীয় কোনও পদ্ধতি যুক্ত করতে পারেন:

public static MyView create(Context context)
{
    return (MyView)LayoutInflater.fromContext(context).inflate(R.layout.my_view, null, false);
}

দাবি অস্বীকার: আমি সম্পূর্ণ বলকগুলিতে কথা বলছি।


ধন্যবাদ! আমি এই উত্তরটিও সঠিক বলে মনে করি :) তবে তিন বছর আগে, যখন আমি এই প্রশ্নটি জিজ্ঞাসা করেছি, "মার্জ "ও কৌশলটি করেছিল!
টম ভ্যান জুম্মেরেন

8
এবং তারপরে কেউ এসেছেন এবং আপনার কাস্টম ভিউটিকে কোনও লেআউটে ন্যায্য <com.example.views.MyView />এবং আপনার সাথে কল করার চেষ্টা করে setDataএবং onFinishInflateকলগুলি এনপিই নিক্ষেপ করা শুরু করে এবং কেন এটি আপনার কোনও ধারণা নেই।
ক্রিস্টোফার পেরি

কৌশলটি এখানে আপনার কাস্টম ভিউটি ব্যবহার করা হয়, তারপরে কনস্ট্রাক্টরে একটি লেআউটকে স্ফীত করে যা কোনও রুট হিসাবে একত্রীকরণ ট্যাগ ব্যবহার করে। এখন আপনি এটি এক্সএমএল এ ব্যবহার করতে পারেন, বা কেবল এটি নতুন করে। সমস্ত ঘাঁটি আচ্ছাদিত, যা প্রশ্ন / গৃহীত উত্তরগুলি একসাথে করে। আপনি যা করতে পারবেন না তা হ'ল সরাসরি বিন্যাসটি উল্লেখ করুন। এটি এখন কাস্টম নিয়ন্ত্রণের দ্বারা 'মালিকানাধীন' এবং কেবল এটি নির্মাণকারীর দ্বারা ব্যবহার করা উচিত। তবে আপনি যদি এই পদ্ধতির ব্যবহার করছেন তবে কেন এটিকে অন্য কোথাও ব্যবহার করার দরকার পড়বে? আপনি না।
মার্ক এ। ডোনোহো
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.