Làm cách nào để đặt phông chữ tùy chỉnh phông chữ thành Văn bản Spinner theo lập trình?


93

Tôi có tệp phông chữ ttf trong thư mục nội dung của mình. Tôi biết cách sử dụng nó cho các lần xem văn bản với:

Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
textview1.setTypeface(externalFont);

Tôi đã xác định giao diện cho văn bản spinner của mình trong tệp xml của chính nó (như usuall trong android):

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:textColor="#ffffff"
android:gravity="center" 
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee" />

Tôi chỉ không thể tham chiếu chế độ xem văn bản này từ mã, tôi luôn nhận được ngoại lệ con trỏ null. Ví dụ: tôi đã thử:

TextView spinner_text=(TextView)findViewById(R.id.text1);
spinner_text.setTypeface(externalFont);

Có thể chọn phông chữ bên ngoài của tôi ngay cả cho văn bản spinner của tôi được xác định trong xml của chính nó không?

Cảm ơn bạn.

CHỈNH SỬA với câu trả lời:

Những công việc này:

String [] items = new String[2];
    items[0]="Something1";
    items[1]="Something2";

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                    R.layout.spinaca, items) {

         public View getView(int position, View convertView, ViewGroup parent) {
                 View v = super.getView(position, convertView, parent);

                 Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
                 ((TextView) v).setTypeface(externalFont);

                 return v;
         }


         public View getDropDownView(int position,  View convertView,  ViewGroup parent) {
                  View v =super.getDropDownView(position, convertView, parent);

                 Typeface externalFont=Typeface.createFromAsset(getAssets(), "fonts/HelveticaNeueLTCom-Lt.ttf");
                 ((TextView) v).setTypeface(externalFont);
                 v.setBackgroundColor(Color.GREEN);

                 return v;
         }
 };


     adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);                                 
     spinner.setAdapter(adapter);

Nó có thể cần thiết để thêm

import android.view.ViewGroup;

Đến danh sách nhập của bạn ở đầu tệp của bạn. Vì lý do nào đó, Eclipse không đưa ra đề xuất này khi nó không nhận ra lớp ViewGroup có liên quan đến mã.


2
Cảm ơn bạn rất nhiều .. Sau một thời gian dài đấu tranh, tôi đã tìm thấy điều này. Điều này đã cứu rỗi một ngày của tôi
Andro Selva

cảm ơn vì đã thêm câu trả lời!
CommonSenseCode

Câu hỏi rất hay ...
Rahul Kushwaha

Câu trả lời:


81

Đây là những gì đã làm việc cho tôi (sử dụng cả ý tưởng từ câu trả lời của CommonsWaregsanllorente ):

private static class MySpinnerAdapter extends ArrayAdapter<String> {
    // Initialise custom font, for example:
    Typeface font = Typeface.createFromAsset(getContext().getAssets(),
                        "fonts/Blambot.otf");

    // (In reality I used a manager which caches the Typeface objects)
    // Typeface font = FontManager.getInstance().getFont(getContext(), BLAMBOT);

    private MySpinnerAdapter(Context context, int resource, List<String> items) {
        super(context, resource, items);
    }

    // Affects default (closed) state of the spinner
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        TextView view = (TextView) super.getView(position, convertView, parent);
        view.setTypeface(font);
        return view;
    }

    // Affects opened state of the spinner
    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        TextView view = (TextView) super.getDropDownView(position, convertView, parent);
        view.setTypeface(font);
        return view;
    }
}

Nếu bạn, giống như tôi, ban đầu điền Spinner bằng cách sử dụng ArrayAdapter.createFromResource()và một tài nguyên mảng (như trong tài liệu Spinner ), thì bạn sẽ sử dụng MySpinnerAdapter như thế này:

MySpinnerAdapter<String> adapter = new MySpinnerAdapter(
        getContext(),
        R.layout.view_spinner_item,
        Arrays.asList(getResources().getStringArray(R.array.my_array))
);
spinner.setAdapter(adapter);

1
Tuyệt quá! Tôi thậm chí còn đi xa hơn và tạo ra một assignAdapterWithOptions(Spinner spinner, int textArrayResId)phương pháp, nhận được bối cảnh từ spinner.getContext()và gán adapter cho spinner bên trong nó (bố trí spinner là stander cho toàn bộ ứng dụng của tôi)
IG Pascual

Trợ giúp này tôi alot.Thanks ... @ Jonik
Rahul Kushwaha

24

Bạn sẽ áp dụng phông chữ thông qua tùy chỉnh của riêng bạn SpinnerAdapter, trong getView()getDropDownView().


Tôi đã chỉnh sửa câu hỏi của mình với vấn đề mới nhất của tôi, bạn có thể vui lòng cho biết tôi đang làm gì sai không. Tnx
DixieFlatline,

1
@DixieFlatline: bạn cần phải thêm một nhập khẩu đối với android.view.ViewGroup, có lẽ
CommonsWare

15

Nếu bạn triển khai Bộ điều hợp của mình trong một tệp khác, bạn có thể truy cập hàm "getAssets ()" từ hàm tạo của Bộ điều hợp, vì bạn có Ngữ cảnh làm tham số.

public class YourItemAdapter extends ArrayAdapter<String> {
int recurso;
Typeface tf;

public YourItemAdapter(Context _context, int _resource,
        List<String> _items) {

    super(_context, _resource, _items);
    recurso=_resource;
    tf=Typeface.createFromAsset(_context.getAssets(),"font/digital-7.ttf");
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    //You can use the new tf here.
    TextView spinner_text=(TextView)findViewById(R.id.text1);
    spinner_text.setTypeface(tf);
    }
}

cái này thực sự hữu ích, Cảm ơn bạn :)
Jashan PJ

Điều này khá hữu ích, mặc dù nó không hoạt động với tôi: findViewById(R.id.text1)dường như không tìm thấy TextView, mặc dù ID chính xác. Một số vấn đề khác trong đoạn mã này: 1) thiếu câu lệnh trả về trong getView(), 2) trường không sử dụng recurso, 3) một số vấn đề về kiểu như đặt tên biến spinner_text(nên có spinnerText). Đây là những gì làm việc cho tôi .
Jonik

4

Hãy thử tạo tùy chỉnh custom_spinner.xml này

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

<com.xxxx.xxxx.CheckedTextViewC

    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1"
    style="?android:attr/spinnerDropDownItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:textAlignment="center"
    android:paddingTop="5dp"
    android:paddingBottom="5dp"
    android:textSize="18sp"

    />

Tạo CheckedtextView tùy chỉnh như thế này

import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.CheckedTextView;

public class CheckedTextViewC extends CheckedTextView {

    public CheckedTextViewC(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
    }
    public CheckedTextViewC(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }
    public CheckedTextViewC(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
    public void setTypeface(Typeface tf, int style) {
        if(!this.isInEditMode()){
        Typeface normalTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Roboto-Light.ttf");
        Typeface boldTypeface = Typeface.createFromAsset(getContext().getAssets(), "font/Roboto-Light.ttf");

        if (style == Typeface.BOLD) {
            super.setTypeface(boldTypeface/*, -1*/);
        } else {
            super.setTypeface(normalTypeface/*, -1*/);
        }
        }

    }
}

triển khai bố cục mới

adapter= new ArrayAdapter <String>(Menu.this,R.layout.custom_spinner, list);

Tôi nghĩ điều này sẽ tốt hơn, vì bạn không phải làm bẩn bộ điều hợp và bạn có thể sử dụng CustomTextview này ở bất kỳ nơi nào khác trong Ứng dụng của mình.
Milad,

2

Đây là phần tiếp theo của câu trả lời trước của tôi: https://stackoverflow.com/a/51100507/787399

Vì lý do tương thích, bạn có thể sử dụng các kiểu và lớp tùy chỉnh dựa trên các widget trong Android. Mặc dù trên Android cấp 15, các /res/fontthư mục tài nguyên mới đã được giới thiệu:

Tài nguyên Phông chữ trong Android

Bước 1: khai báo item_spinner.xml

<?xml version="1.0" encoding="utf-8"?>
<com.my_package.custom_views.FontTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv_spinner"
    style="@style/App_TextViewStyleSmall"
    android:layout_gravity="start|bottom"
    android:layout_marginLeft="@dimen/dp_5"
    android:layout_marginStart="@dimen/dp_5"
    android:ellipsize="marquee"
    android:gravity="start|bottom"
    android:padding="@dimen/dp_10"
    android:singleLine="true"
    android:textAlignment="inherit" />
    <!--declared in layout: item_spinner.xml-->
    <!-- removed attributes:  android:layout_width="match_parent"
               android:layout_height="wrap_content"
               android:textColor="@color/text_grey_light"
               android:textSize="@dimen/sp_14" -->
    <!--style="?android:attr/spinnerItemStyle"-->

bước 2: khai báo item_spinner_dropdown.xml:

<?xml version="1.0" encoding="utf-8"?>
<com.my_package.custom_views.FontTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/tv_spinner"
    style="@style/App_TextViewStyleSmall"
    android:layout_gravity="start|bottom"
    android:layout_marginLeft="@dimen/dp_5"
    android:layout_marginStart="@dimen/dp_5"
    android:ellipsize="marquee"
    android:gravity="start|bottom"
    android:padding="@dimen/dp_10"
    android:singleLine="true" />
    <!--declared in layout: item_spinner_dropdown.xml -->
    <!--removed: ?android:attr/dropdownListPreferredItemHeight-->
    <!--style="?android:attr/spinnerDropDownItemStyle"-->

Bước 3: Sử dụng con quay trong bố cục:

<LinearLayout
            android:id="@+id/ll_my_spinner"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/fet_bus_entity"
            android:layout_marginTop="@dimen/dp_12"
            android:orientation="horizontal">

            <com.my_package.custom_views.FontTextView
                style="@style/App_TextViewStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="start|bottom"
                android:gravity="start|bottom"
                android:text="@string/are_you_a" />

            <Spinner
                android:id="@+id/sp_my_spinner"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/dp_5"
                android:layout_marginStart="@dimen/dp_5"
                android:layout_gravity="end|bottom"
                android:spinnerMode="dropdown" />
        </LinearLayout>

[Lưu ý: id của FontTextView giống nhau trong cả bố cục, mục xoay và mục thả xuống]

Bước 4: Sử dụng nó trong Activity / Fragment:

private void initSpinnerBusinessType(View rootView) {
        String[] ar_dd_bus_type = getResources().getStringArray(R.array.ar_dd_bus_type);
        List<String> lst_bus_type = Arrays.asList(ar_dd_bus_type);
        ArrayList<String> ar_bus_type = new ArrayList<>(lst_bus_type);
        //==

        ArrayAdapter<String> adapter = new ArrayAdapter<>(activity, R.layout.item_spinner, R.id.tv_spinner, ar_bus_type);
        adapter.setDropDownViewResource(R.layout
                .item_spinner_dropdown);
        //=========
        Spinner sp_my_spinner= rootView.findViewById(R.id.sp_my_spinner);
        sp_my_spinner.setAdapter(adapter);
    }

[để được hướng dẫn thêm, hãy xem bài đăng khác của tôi: https://stackoverflow.com/a/51077569/787399https://stackoverflow.com/a/22164007/787399 ]


0

Vui lòng làm theo các tùy chỉnh cơ bản của FontTextView, FontEditView, FontRadioButton, FontCheckBox và FontButton.

[Để có câu trả lời chính xác, sau khi xem hướng dẫn này, vui lòng xem tại: https://stackoverflow.com/a/51113022/787399 ]

Sử dụng FontTextView tùy chỉnh, trong bố cục mục ArrayAdapter, như sau:

public class FontEditText extends AppCompatEditText {

//    private String FONT = "fonts/roboto_regular.ttf";

    public FontEditText(Context context) {
        super(context, null);
//        setFontFromAsset(context, null, R.style.DefaultFontTextView);
//        FONT = getContext().getString(R.string.font_roboto_regular);
    }

    public FontEditText(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        setFontFromAsset(context, attrs, R.attr.fetFontStyle);
    }

    public FontEditText(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setFontFromAsset(context, attrs, defStyleAttr);
    }

    private void setFontFromAsset(Context context, AttributeSet attrs, int defStyle) {
        BaseActivity activity = (BaseActivity)((MyApplication) context.getApplicationContext()).getCurrentActivity();
        FontAndLocaleManager fontAndLocaleManager = activity.getFontAndLocaleManager();
        fontAndLocaleManager.setFontFromAsset(this, R.styleable.FontEditText, R.styleable.FontEditText_fetFontFace, attrs, defStyle);
    }
}

sử dụng mã:

public void setFontFromAsset(View view, int[] resViewStyleable, int resStyleableViewFontFace, AttributeSet attrs, int defStyle) {
        String strFont = null;
        Typeface tfFontFace = null;
        String strButton = FontButton.class.getCanonicalName(),
                strTextView = FontTextView.class.getCanonicalName(),
                strEditText = FontEditText.class.getCanonicalName(),
                strView = view.getClass().getCanonicalName();
        try {
            if (view.isInEditMode()) {
                return;
            }
            //R.string.font_roboto_regular
            strFont = context.getString(R.string.font_roboto_regular);
            tfFontFace = Typeface.createFromAsset(context.getAssets(), strFont);

            //AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes
            //R.styleable.FontButton
            TypedArray a = context.obtainStyledAttributes(attrs, resViewStyleable, defStyle, 0);
            //R.styleable.FontButton_btFontFace
            String derivedFont = a.getString(resStyleableViewFontFace);

            a.recycle();

            //==
            try {
                if (derivedFont != null) {
                    Typeface derivedFontFace = Typeface.createFromAsset(context.getAssets(), derivedFont);
                    if (strView.equals(strButton)) {
                        ((FontButton) view).setTypeface(derivedFontFace);
                    } else if (strView.equals(strTextView)) {
                        ((FontTextView) view).setTypeface(derivedFontFace);
                    } else if (strView.equals(strEditText)) {
                        ((FontEditText) view).setTypeface(derivedFontFace);
                    }
                    return;
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            if (strFont != null && tfFontFace != null) {
                if (strView.equals(strButton)) {
                    ((FontButton) view).setTypeface(tfFontFace);
                } else if (strView.equals(strTextView)) {
                    ((FontTextView) view).setTypeface(tfFontFace);
                } else if (strView.equals(strEditText)) {
                    ((FontEditText) view).setTypeface(tfFontFace);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

Mô tả kiểu và thuộc tính trong xmls tương ứng:

<!--FontTextView-->
    <declare-styleable name="FontTextViewStyle">
        <!-- Style of the FontTextView. -->
        <attr name="ftvFontStyle" format="reference"/>

    </declare-styleable>
    <declare-styleable name="FontTextView">
        <!-- Font face of FontTextView. -->
        <attr name="ftvFontFace" format="reference"/>
    </declare-styleable>

<!--FontTextView-->
<style name="StyledFontTextView" parent="@android:style/Theme.Light">
<item name="ftvFontStyle">@style/DefaultFontTextView</item>
</style>

<style name="DefaultFontTextView">
<item name="ftvFontFace">@string/font_roboto_regular</item>
</style>

xác định thêm một số kiểu:

<style name="App_TextViewStyle" parent="@android:style/Widget.TextView">
        <item name="android:textColor">@color/text_grey</item>
        <item name="android:textSize">@dimen/sp_20</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
    </style>
    <style name="App_TextViewStyleMedium" parent="@android:style/Widget.TextView">
        <item name="android:textColor">@color/text_hint</item>
        <item name="android:textSize">@dimen/sp_18</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
    </style>
    <style name="App_TextViewStyleSmall" parent="@android:style/Widget.TextView">
        <item name="android:textColor">@color/text_grey_light</item>
        <item name="android:textSize">@dimen/sp_14</item>
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">wrap_content</item>
    </style>

đề cập đến các phông chữ trong string.xml của bạn:

...
<string name="font_roboto_regular">fonts/roboto_regular.ttf</string>
...

và sử dụng trong các bố cục tiết kiệm một số mã và thời gian:

<com.mypackage.custom_views.FontTextView
                style="@style/App_TextViewStyleMedium"
                android:layout_gravity="start|bottom"
                android:gravity="start|bottom"
                app:fetFontFace="@string/font_roboto_regular"
                android:text="@string/are_you_a" />

Ở cấp độ Android 16 trở lên, tất cả điều này được đơn giản hóa, vì giờ đây bạn có thể giữ TTF và các tài nguyên phông chữ khác trong /res/fontthư mục, thay vì trong nội dung. Điều đó loại bỏ hầu hết các lớp, kiểu và thuộc tính tùy chỉnh, hãy xem:

Tài nguyên Phông chữ trong Android

Happy Coding với phong cách !! :-)


Câu trả lời dài, nhưng một lần làm việc. Sau đó, đây là một tái sử dụng.
Abhinav Saxena

-1

Các bạn, tôi đã tìm thấy một giải pháp tuyệt vời, tôi bọc bộ chuyển đổi gốc bởi người trợ giúp như

Sử dụng SpinnerViewHelper lớp này và giao dịch vui vẻ với Android

new SpinnerViewHelper((Spinner)view.findViewById(R.id.labelSurveyNumber),(parent, v, position, id) -> UrduFontHelper.set(v));

Biểu thức Lambda được sử dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.