วิธีตั้งค่าฟอนต์ที่กำหนดเองให้เป็น Spinner text โดยทางโปรแกรม?


93

ฉันมีไฟล์ฟอนต์ ttf ในโฟลเดอร์ assets ฉันรู้วิธีใช้สำหรับ textviews กับ:

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

ฉันได้กำหนดการค้นหาข้อความสปินเนอร์ของฉันในไฟล์ xml ของตัวเอง (เหมือน usuall ใน 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" />

ฉันไม่สามารถอ้างอิง textview นี้จากโค้ดได้ฉันมักจะได้รับข้อยกเว้นของตัวชี้ที่เป็นโมฆะ เช่นฉันพยายาม:

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

เป็นไปได้ไหมที่จะเลือกแบบอักษรภายนอกของฉันแม้กระทั่งสำหรับข้อความสปินเนอร์ของฉันที่กำหนดไว้ใน xml ของตัวเอง

ขอขอบคุณ.

แก้ไขพร้อมคำตอบ:

ใช้งานได้:

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);

อาจจำเป็นต้องเพิ่ม

import android.view.ViewGroup;

ไปยังรายการการนำเข้าของคุณที่ด้านบนสุดของไฟล์ของคุณ ด้วยเหตุผลบางประการ Eclipse ไม่ให้คำแนะนำนี้เมื่อไม่รู้จักคลาส ViewGroup ที่เกี่ยวข้องกับโค้ด


2
ขอบคุณเพื่อนมาก .. หลังจากต่อสู้มานานฉันได้พบสิ่งนี้ สิ่งนี้บันทึกแผนที่ประจำวันของฉัน
Andro Selva

ขอบคุณที่เพิ่มคำตอบ!
CommonSenseCode

คำถามที่ดีมาก ...
Rahul Kushwaha

คำตอบ:


81

นี่คือสิ่งที่ทำงานให้ฉัน (ใช้ความคิดทั้งจากCommonsWare ของและgsanllorente ของคำตอบ):

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;
    }
}

หากคุณเช่นเดียวกับฉันซึ่งเดิมสร้าง Spinner โดยใช้ArrayAdapter.createFromResource()และทรัพยากรอาร์เรย์ (ดังในเอกสาร Spinner ) คุณจะใช้ MySpinnerAdapter ดังนี้:

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

1
เยี่ยมมาก! ฉันไปไกลกว่านั้นและสร้างassignAdapterWithOptions(Spinner spinner, int textArrayResId)วิธีการรับบริบทจากspinner.getContext()และกำหนดอะแดปเตอร์ให้กับสปินเนอร์ที่อยู่ข้างใน (เลย์เอาต์สปินเนอร์นั้นโดดเด่นกว่าสำหรับแอพทั้งหมดของฉัน)
IG Pascual

สิ่งนี้ช่วยฉันได้มากขอบคุณ ... @ Jonik
Rahul Kushwaha

24

คุณจะใช้แบบอักษรผ่านแบบกำหนดเองSpinnerAdapterในgetView()และgetDropDownView().


ฉันแก้ไขคำถามด้วยปัญหาล่าสุดของฉันคุณช่วยบอกได้ไหมว่าฉันทำอะไรผิด Tnx
DixieFlatline

1
@DixieFlatline: คุณต้องเพิ่มการนำเข้าสำหรับandroid.view.ViewGroupสันนิษฐานว่า
CommonsWare

15

หากคุณใช้ Adapter ของคุณในไฟล์อื่นคุณสามารถเข้าถึงฟังก์ชัน "getAssets ()" จากตัวสร้างของอะแด็ปเตอร์ได้เนื่องจากคุณมีบริบทเป็นพารามิเตอร์

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);
    }
}

อันนี้ช่วยได้จริงๆขอบคุณ :)
Jashan PJ

สิ่งนี้มีประโยชน์แม้ว่าจะไม่ได้ผลสำหรับฉัน: findViewById(R.id.text1)ดูเหมือนว่าจะไม่พบ TextView แม้ว่า ID จะถูกต้องก็ตาม ปัญหาอื่น ๆ ในรหัสนี้: 1) ไม่มีคำสั่งส่งคืนในgetView()2) ฟิลด์ที่ไม่ได้ใช้recurso3) ปัญหาเกี่ยวกับสไตล์บางอย่างเช่นการตั้งชื่อตัวแปรspinner_text(ควรจะเป็นspinnerText) นี่คือสิ่งที่ทำงานให้ฉัน
Jonik

4

ลองสร้าง custom_spinner.xml ที่กำหนดเอง

<?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"

    />

สร้าง CheckedtextView ที่กำหนดเองเช่นนี้

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*/);
        }
        }

    }
}

ใช้รูปแบบใหม่

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

ฉันคิดว่าสิ่งนี้จะดีกว่าเพราะคุณไม่ต้องทำให้มือของคุณสกปรกบนอะแดปเตอร์และคุณสามารถใช้ CustomTextview นี้ได้ทุกที่ในแอปของคุณ
Milad

2

นี่คือความต่อเนื่องของคำตอบก่อนหน้าของฉัน: https://stackoverflow.com/a/51100507/787399

ด้วยเหตุผลด้านความเข้ากันได้คุณสามารถใช้สไตล์และคลาสที่กำหนดเองกับวิดเจ็ตใน Android แม้ว่าจะสูงกว่า Android ระดับ 15 แต่/res/fontก็มีการเปิดตัวโฟลเดอร์ทรัพยากรใหม่:

ทรัพยากรแบบอักษรใน Android

ขั้นตอนที่ 1: ประกาศ 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"-->

ขั้นตอนที่ 2: ประกาศ 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"-->

ขั้นตอนที่ 3: ใช้สปินเนอร์ในเค้าโครง:

<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>

[หมายเหตุ: id ของ FontTextView เหมือนกันทั้งในเลย์เอาต์รายการสปินเนอร์และรายการแบบเลื่อนลง]

ขั้นตอนที่ 4: ใช้ในกิจกรรม / ส่วนย่อย:

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);
    }

[สำหรับคำแนะนำเพิ่มเติมดูโพสต์อื่นของฉัน: https://stackoverflow.com/a/51077569/787399และhttps://stackoverflow.com/a/22164007/787399 ]


0

โปรดปฏิบัติตามการปรับแต่งพื้นฐานของ FontTextView, FontEditView, FontRadioButton, FontCheckBox และ FontButton

[สำหรับคำตอบที่แน่นอนหลังจากอ่านคู่มือนี้โปรดดู: https://stackoverflow.com/a/51113022/787399 ]

ใช้ FontTextView แบบกำหนดเองในเค้าโครงรายการ ArrayAdapter ดังนี้:

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);
    }
}

ใช้รหัส:

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();
        }

    }

อธิบายรูปแบบและคุณลักษณะใน xml ที่เกี่ยวข้อง:

<!--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>

กำหนดรูปแบบเพิ่มเติม:

<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>

พูดถึงแบบอักษรใน strings.xml ของคุณ:

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

และใช้ในการจัดวางเพื่อประหยัดรหัสและเวลา:

<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" />

ใน Android ระดับ 16 ขึ้นไปทั้งหมดนี้ง่ายขึ้นเพราะตอนนี้คุณสามารถเก็บ TTF และทรัพยากรแบบอักษรอื่น ๆ ไว้ใน/res/fontโฟลเดอร์แทนที่จะอยู่ในเนื้อหา ซึ่งจะลบคลาสสไตล์และแอตทริบิวต์ที่กำหนดเองส่วนใหญ่โปรดดู:

ทรัพยากรแบบอักษรใน Android

Happy Coding อย่างมีสไตล์ !! :-)


คำตอบยาว แต่ทำงานครั้งเดียว หลังจากนั้นก็สามารถนำกลับมาใช้ใหม่ได้
Abhinav Saxena

-1

พวกฉันพบวิธีแก้ปัญหาที่ยอดเยี่ยมฉันห่ออะแดปเตอร์ orignal โดยผู้ช่วยเช่น

ใช้SpinnerViewHelperคลาสนี้และมีความสุขกับการทำงานร่วมกับ Android

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

ใช้นิพจน์แลมบ์ดา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.