ساخت View سفارشی

بعضی وقت ها نیاز میشه که ترکیبی از چند view را در صفحات مختلفی به کار ببریم ، مثلا در یکی از پروژه ها به دکمه هایی نیاز داشتم که یک آیکون کوچک کنار نوشته ها قرار می داد ،

خوب برای ساخت همچین دکمه ای مجبور بودم از یک LinearLayout یا RelativeLayout استفاده کنم و بعد داخل اون ۲ view دیگر قرار بدهم ،

اولی آیکونی که قرار بود روی دکمه قرار داشته باشه

دومی متنی که روی دکمه نوشته شده بود

و بعد با دادن یک بکگراند از نوع selector به layout به شکل یک دکمه در می آمد.

<LinearLayout
        android:id="@+id/callButton"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_buttons_height"
        android:gravity="center"
        >
    <org.lastsecond.LastSecond.widget.PersianTextView
            android:id="@+id/customButton_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/app_buttons_textColor"
            android:textSize="@dimen/app_buttons_textSize"
            android:text=""
            android:layout_marginRight="5dp"/>
    <org.lastsecond.LastSecond.widget.IconTextView
            android:id="@+id/customButton_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/app_buttons_textColor"
            android:textSize="@dimen/app_buttons_textSize"
            android:text=""
            />
</LinearLayout>

خوب همه چیز خوبه فقط یک مسئله پیش می آید :

من دربرنامه به تعداد زیادی از این دکمه ها نیاز دارم و اگر هربار بخواهم برای هر دکمه این همه کد رو بنویسم هم حجم برنامه زیاد میشه و هم اگر زمانی نیاز به یک تغییر کوچک در ظاهر دکمه ها داشته باشم ، مجبورم همه دکمه هارا تغییر بدهم.

اما یک راه حل ساختن یک view سفارشی هست

 

برای ساخت یک دکمه سفارشی یک فایل layout به اسم custom_button.xml درست می کنم و کد های طراحی دکمه ها را داخل آن قرار می دهم :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/callButton"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="@dimen/app_buttons_height"
        android:gravity="center"
        >
    <org.lastsecond.LastSecond.widget.PersianTextView
            android:id="@+id/customButton_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/app_buttons_textColor"
            android:textSize="@dimen/app_buttons_textSize"
            android:text=""
            android:layout_marginRight="5dp"/>
    <org.lastsecond.LastSecond.widget.IconTextView
            android:id="@+id/customButton_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@color/app_buttons_textColor"
            android:textSize="@dimen/app_buttons_textSize"
            android:text=""
            />
</LinearLayout>

 

برای اینکه اندروید اون رو به عنوان یک view بشناسه یک فایل به اسم CustomButton.java می سازم و کد های زیر را داخل آن می نویسم :

public class CustomButton extends FrameLayout {
    TextView textView;
    TextView icon;

    public CustomButton(Context context) {
        super(context);
            init();
    }

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

    public CustomButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
         init();
    }

    private void init() {
        View view = inflate(getContext(), R.layout.custom_button, null);
        textView = (TextView) view.findViewById(R.id.customButton_text);
        icon = (TextView) view.findViewById(R.id.customButton_icon);

        addView(view);
    }


    public void setText(String text) {
        textView.setText(text);
    }

    public void setIcon(String iconFont) {
        icon.setText(iconFont);
    }

    public void setTextColor(int color) {
        textView.setTextColor(color);
        icon.setTextColor(color);
    }

}

در اینجا کلاس FrameLayout را extends کردم سپس در هر ۳ constructor موجود آن متد init() را فراخوانی کردم.

در متد init() یک view را inflate می کنم و به FrameLayout اضافه می کنم . برای inflate کردن مانند جاهای دیگه یک View از روی یک layout ساخته شده (همان layout دکمه ای که پیش از این ساخته بودم).

 

۳ متد دیگر برای ایجاد تغییر درمتن و رنگ متن دکمه ها می باشد.

 

خوب View ما آماده شد حالا به صورت زیر میتونم از اون توی layout های خودم استفاده کنم :

        <iac.iact.MyApp.CustomButton
                android:id="@+id/commentButton"
                android:layout_width="50dp"
                android:layout_height="@dimen/app_buttons_height"
                android:background="@drawable/tabs_background_selector"
                />

و توی کد ها هم به صورت زیر دکمه ها رو تعریف می کنم :

    CustomButton commentButton = (CustomButton) findViewById(R.id.commentButton);

 

و الان میتونم با استفاده از ۳ متدی که بالا نوشته بودم متن اون رو هم تغییر بدم :

commentButton.setText("Comment");

 

 

حالا می خوام کمی پیشرفته تر کار کنم ، یعنی قصد دارم CustomButton رو طوری درست کنم که بتونم توی خود xml به اون متن بدهم یا اینکه چند مشخصه دیگر هم از xml تنظیم کنم :

واسه این کار باید در پوشه values در res فایلی به اسم attrs.xml درست کنم (اگر قبل وجود دارد کد ها را به آن اضافه کنید) و برای دکمه خود چند مشخصه جدید تعریف بکنم :

    <declare-styleable name="CustomButton">
        <attr name="android:text"/>
        <attr name="android:textColor"/>
        <attr name="android:textSize"/>
        <attr name="iconFont" format="string"/>
    </declare-styleable>

توی این کد  یک styleable به اسم CustomButton تعریف کردم که مشخصه های android:text  و android:textColor و android:textSize و iconFont را شامل می شود.

همون طور که میبینید یک مشخصه به اسم iconFont با format="string" هم داریم ، فرقش به مشخصه های دیگر این است که یک مشخصه سفارشی هست و نوعش رو خود باید تعیین کنیم ، در صورتی که android:text قبلا نوعش مشخص شده .

حالا توی xml به صورت زیر میتونم دکمه رو تعریف کنم :

        <ir.iact.MyApp.CustomButton
                android:id="@+id/commentButton"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="@dimen/app_buttons_height"
                android:text="@string/app_comment"
                android:textSize="@dimen/app_buttons_textSize"
                app:iconFont="@string/icon_news"
                android:background="@drawable/tabs_background_selector"
                />

همون طور که میبینید مشخصه های android:text و android:textSize مثل بقیه مشخصه ها می باشند اما app:iconFont یک مشخصه جدید می باشد (خوب حالا این app چی هست رو باید در ابتدای xml معرفی کنیم :

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

این رو به ابتدای layout خود زیر

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

اضافه کنید تا اندروید خودش این مشخصه را پیدا و معرفی کند.

 

بعد از این نیاز داریم تا کلاس CustomButton رو هم کمی تغییر بدهیم تا مقادیر گرفته شده از xml را در view سفارشی خودمون set کنیم:

public class CustomButton extends FrameLayout {
    TextView textView;
    TextView icon;

    public CustomButton(Context context) {
        super(context);
            init(null);
    }

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

    public CustomButton(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
            init(attrs);
    }

    private void init(AttributeSet attrs) {
        View view = inflate(getContext(), R.layout.custom_button, null);
        textView = (TextView) view.findViewById(R.id.customButton_text);
        icon = (TextView) view.findViewById(R.id.customButton_icon);


        if (attrs != null) {
            TypedArray attributes = getContext().obtainStyledAttributes(attrs, R.styleable.CustomButton);

            textView.setText(attributes.getString(R.styleable.CustomButton_android_text));
            icon.setText(attributes.getString(R.styleable.CustomButton_iconFont));
            setTextColor(attributes.getColor(R.styleable.CustomButton_android_textColor, Color.WHITE));
        }


        addView(view);
    }


    public void setText(String text) {
        textView.setText(text);
    }

    public void setIcon(String iconFont) {
        icon.setText(iconFont);
    }

    public void setTextColor(int color) {
        textView.setTextColor(color);
        icon.setTextColor(color);
    }

    public void setTextSize(float textSize) {
        textView.setTextSize(textSize);
        icon.setTextSize(textSize);
    }
}

در اینجا از attrs استفاده کردم و مقادیر را با کد زیر گرفتم :

 TypedArray attributes = getContext().obtainStyledAttributes(attrs, R.styleable.CustomButton);

و بعد مقدار دهی کردم :


            textView.setText(attributes.getString(R.styleable.CustomButton_android_text));
            icon.setText(attributes.getString(R.styleable.CustomButton_iconFont));
            setTextColor(attributes.getColor(R.styleable.CustomButton_android_textColor, Color.WHITE));

 

تمام ، view شما آماده است

امیدوارم مفید بوده باشه 🙂

http://stackoverflow.com/questions/2695646/declaring-a-custom-android-ui-element-using-xml

 

برچسب ها:
پست قبلی
پست بعدی

درباره ایلیا عابدینی

برنامه نویس اندروید و کارشناس مهندسی پزشکی، نفر سوم مسابقه برنامه نویسی اندروید http://www.schallenge.ir ، از سال 92 برنامه نویسی اندروید رو شروع کردم و در حال حاضر در شرکت عصر دانش در حال توسعه اپلیکیشن تجارت پی می باشدم ، این وبلاگ رو ساختم تا تجربیات روزانه و مفید خودم رو داخل اون بزارم. رزومه : iact.ir/cv

5 دیدگاه

  1. با حال بود 

    مرسی

  2. خیلی خوب و سازنده بود،

    امیدوارم موفق بوده و قدر امثال شماها توسط همگان دانسته شود، 

  3. slm merC az site khobeton

    ۱soal dashtam :

    man ye activity daram ke to xmlesh ye view pager hast ke har kodom az pagea text view khodesho dare . hala age bekham fonte external add konam vase har kodom az layehaye xmlam ke to view pageram hast . bayad chikar konam!?

     

  4. dar halate adi ba ye hamchin codei dar activity mishe :

    TextView myTextView=(TextView)findViewById(R.id.mmm);
    Typeface typeFace= Typeface.createFromAsset(getAssets(), "Xanadu.ttf");
    myTextView.setTypeface(typeFace);

    ama moshkel injast ke man to laye activitim view pager daram na text view! va inke mikham text view yeki az layehaey ke dar view pager namayesh mide fontesh avaz she

دیدگاهتان را ثبت کنید

آدرس ایمیل شما منتشر نمی شود.علامت دارها لازمند. *

*

رفتن به بالا