كيفية استخدام محرف مخصص في عنصر واجهة مستخدم؟

StackOverflow https://stackoverflow.com/questions/4318572

  •  29-09-2019
  •  | 
  •  

سؤال

لدي عنصر واجهة مستخدم الساعة الرقمية. كيف يمكنني استخدام خط مخصص من الأصول/الخطوط كخط افتراضي في TextView يعرض الساعة؟

هذا هو الكود الخاص بي:

    package android.tristan.widget.digiclock;

import java.util.Calendar;

import android.app.PendingIntent;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.os.Vibrator;
import android.text.format.DateFormat;
import android.widget.RemoteViews;


public class DigiClock extends AppWidgetProvider {

    @Override
    public void onDisabled(Context context) {
        super.onDisabled(context);
        context.stopService(new Intent(context, UpdateService.class));
    }
    public void onReceive(Context context, Intent intent)
    {
        super.onReceive(context, intent);

        if(intent.getAction().equals("android.tristan.widget.digiclock.CLICK"))
        {
          Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
          vibrator.vibrate(50);           
            final Intent alarmClockIntent = new Intent(Intent.ACTION_MAIN, null);
            alarmClockIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            final ComponentName cn = new ComponentName("com.android.deskclock", "com.android.deskclock.AlarmClock");
            alarmClockIntent.setComponent(cn);
            alarmClockIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(alarmClockIntent);
        }
        if(intent.getAction().equals("android.tristan.widget.digiclock.CLICK_2"))
        {
          Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
          vibrator.vibrate(50);
           final Intent calendarIntent = new Intent(Intent.ACTION_MAIN, null);
           calendarIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            final ComponentName cn = new ComponentName("com.android.calendar", "com.android.calendar.LaunchActivity");
            calendarIntent.setComponent(cn);
            calendarIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(calendarIntent);       
        }
    }

    @Override
    public void onEnabled(Context context) {
        super.onEnabled(context);
        context.startService(new Intent(UpdateService.ACTION_UPDATE));
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        super.onUpdate(context, appWidgetManager, appWidgetIds);
        context.startService(new Intent(UpdateService.ACTION_UPDATE));
        final int Top = appWidgetIds.length;
        final int Bottom = appWidgetIds.length;
        for (int i=0; i<Top; i++)
        {
            int[] appWidgetId = appWidgetIds;
            RemoteViews top=new RemoteViews(context.getPackageName(), R.layout.main);
            Intent clickintent=new Intent("android.tristan.widget.digiclock.CLICK");
            PendingIntent pendingIntentClick=PendingIntent.getBroadcast(context, 0, clickintent, 0);
            top.setOnClickPendingIntent(R.id.TopRow, pendingIntentClick);
            appWidgetManager.updateAppWidget(appWidgetId, top);
        }
        for (int i=0; i<Bottom; i++)
        {
            int[] appWidgetId = appWidgetIds;
            RemoteViews bottom=new RemoteViews(context.getPackageName(), R.layout.main);
            Intent clickintent=new Intent("android.tristan.widget.digiclock.CLICK_2");
            PendingIntent pendingIntentClick=PendingIntent.getBroadcast(context, 0, clickintent, 0);
            bottom.setOnClickPendingIntent(R.id.BottomRow, pendingIntentClick);
            appWidgetManager.updateAppWidget(appWidgetId, bottom);
        }
}

    public static final class UpdateService extends Service {

       static final String ACTION_UPDATE = "android.tristan.widget.digiclock.action.UPDATE";

        private final static IntentFilter sIntentFilter;

        private final static String FORMAT_12_HOURS = "h:mm";
        private final static String FORMAT_24_HOURS = "kk:mm";

        private String mTimeFormat;
        private String mDateFormat;
        private String mDayFormat;
        private Calendar mCalendar;

        static {
            sIntentFilter = new IntentFilter();
            sIntentFilter.addAction(Intent.ACTION_TIME_TICK);
            sIntentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
            sIntentFilter.addAction(Intent.ACTION_TIME_CHANGED);
        }

        @Override
        public void onCreate() {
            super.onCreate();
            reinit();
            registerReceiver(mTimeChangedReceiver, sIntentFilter);
         }

        @Override
        public void onDestroy() {
            super.onDestroy();
            unregisterReceiver(mTimeChangedReceiver);
        }

        @Override
        public void onStart(Intent intent, int startId) {
            super.onStart(intent, startId);

            if (ACTION_UPDATE.equals(intent.getAction())) {
                update();
            }
        }

        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }


        private void update() {
            mCalendar.setTimeInMillis(System.currentTimeMillis());
            final CharSequence time = DateFormat.format(mTimeFormat, mCalendar);
            final CharSequence date = DateFormat.format(mDateFormat, mCalendar);
            final CharSequence day = DateFormat.format(mDayFormat, mCalendar);

            RemoteViews views = new RemoteViews(getPackageName(), R.layout.main);
            views.setTextViewText(R.id.Time, time);
            views.setTextViewText(R.id.Day, day);
            views.setTextViewText(R.id.Date, date);

            ComponentName widget = new ComponentName(this, DigiClock.class);
            AppWidgetManager manager = AppWidgetManager.getInstance(this);
            manager.updateAppWidget(widget, views);
        }

        private void reinit() {
            mDayFormat = getString(R.string.day_format);
            mDateFormat = getString(R.string.date_format);
            mTimeFormat = is24HourMode(this) ? FORMAT_24_HOURS : FORMAT_12_HOURS;
            mCalendar = Calendar.getInstance();
        }

        private static boolean is24HourMode(final Context context) {
            return android.text.format.DateFormat.is24HourFormat(context);
        }

        private final BroadcastReceiver mTimeChangedReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();

                if (action.equals(Intent.ACTION_TIME_CHANGED) ||
                    action.equals(Intent.ACTION_TIMEZONE_CHANGED))
                {
                    reinit();
                }

                update();
            }
        };
    }
}
هل كانت مفيدة؟

المحلول

المطلوب هو جعل الخط على قماش ، ثم تمريره إلى صورة نقطية وتعيين ذلك إلى ImageView. مثل ذلك:

public Bitmap buildUpdate(String time) 
{
    Bitmap myBitmap = Bitmap.createBitmap(160, 84, Bitmap.Config.ARGB_4444);
    Canvas myCanvas = new Canvas(myBitmap);
    Paint paint = new Paint();
    Typeface clock = Typeface.createFromAsset(this.getAssets(),"Clockopia.ttf");
    paint.setAntiAlias(true);
    paint.setSubpixelText(true);
    paint.setTypeface(clock);
    paint.setStyle(Paint.Style.FILL);
    paint.setColor(Color.WHITE);
    paint.setTextSize(65);
    paint.setTextAlign(Align.CENTER);
    myCanvas.drawText(time, 80, 60, paint);
    return myBitmap;
}

هذا هو الجزء الذي يقوم بالخط لتصوير شيء ، وهذه هي كيفية استخدامه:

String time = (String) DateFormat.format(mTimeFormat, mCalendar);
RemoteViews views = new RemoteViews(getPackageName(), R.layout.main);
views.setImageViewBitmap(R.id.TimeView, buildUpdate(time));

كما قد تلاحظ ، يعرض هذا الرمز الوقت الحالي في صورة ImageView ، ولكن يمكن تعديله بسهولة على أي احتياجات.

يحرر:

تم إهمال ARGB_4444 لـ ARGB_8888 كما هو مذكور في توثيق

تم إهمال هذا الحقل في مستوى API 13. بسبب رديء الجودة لهذا التكوين ، يُنصح باستخدام ARGB_8888 بدلاً من ذلك.

نصائح أخرى

لقد تغيرت قليلاً عن حجم القياس ، وبالتالي فإن صورة نقطية ستدعم حجم الخطوط المختلفة. إنه مجرد دعم نص سطر واحد.

public static Bitmap getFontBitmap(Context context, String text, int color, float fontSizeSP) {
    int fontSizePX = convertDiptoPix(context, fontSizeSP);
    int pad = (fontSizePX / 9);
    Paint paint = new Paint();
    Typeface typeface = Typeface.createFromAsset(context.getAssets(), "Fonts/Roboto-Regular.ttf");
    paint.setAntiAlias(true);
    paint.setTypeface(typeface);
    paint.setColor(color);
    paint.setTextSize(fontSizePX);

    int textWidth = (int) (paint.measureText(text) + pad * 2);
    int height = (int) (fontSizePX / 0.75);
    Bitmap bitmap = Bitmap.createBitmap(textWidth, height, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    float xOriginal = pad;
    canvas.drawText(text, xOriginal, fontSizePX, paint);
    return bitmap;
}

public static int convertDiptoPix(Context context, float dip) {
    int value = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, context.getResources().getDisplayMetrics());
    return value;
}

هذا يجعل الخط إلى صورة نقطية ، ثم يعين صورة نقطية إلى صورة.

public static RemoteViews buildUpdate(Context context)
{
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.main);
    Bitmap myBitmap = Bitmap.createBitmap(100, 50, Bitmap.Config.ARGB_4444);
    Canvas myCanvas = new Canvas(myBitmap);
    Paint paint = new Paint();
    Typeface clock = Typeface.createFromAsset(context.getAssets(),"Clockopia.ttf");
    paint.setAntiAlias(true);
    paint.setSubpixelText(true);
    paint.setTypeface(clock);
    paint.setStyle(Paint.Style.FILL);
    paint.setColor(Color.BLACK);
    paint.setTextSize(15);
    myCanvas.drawText("Test", 0, 20, paint);

    views.setImageViewBitmap(R.id.TimeView, myBitmap);

    return views;
}

سيؤدي هذا الحل إلى إنشاء صورة نقطية هو الحجم الدقيق المطلوب لتناسب النص.

/**
 * Creates and returns a new bitmap containing the given text.
 */
public static Bitmap createTextBitmap(final String text, final Typeface typeface, final float textSizePixels, final int textColour)
{
    final TextPaint textPaint = new TextPaint();
    textPaint.setTypeface(typeface);
    textPaint.setTextSize(textSizePixels);
    textPaint.setAntiAlias(true);
    textPaint.setSubpixelText(true);
    textPaint.setColor(textColour);
    textPaint.setTextAlign(Paint.Align.LEFT);
    Bitmap myBitmap = Bitmap.createBitmap((int) textPaint.measureText(text), (int) textSizePixels, Bitmap.Config.ARGB_8888);
    Canvas myCanvas = new Canvas(myBitmap);
    myCanvas.drawText(text, 0, myBitmap.getHeight(), textPaint);
    return myBitmap;
}

كما ذكرنا في مكان آخر ، يمكن بعد ذلك تعيين صورة نقطية إلى صورة مصغرة.

final Bitmap textBitmap = createTextBitmap(text,
        FontManager.get().getTypeface("slab-serif", 0),
        context.getResources().getDimension(R.dimen.widget_font_size_large),
        context.getResources().getColor(R.color.widget_text)
);
views.setImageViewBitmap(R.id.widget_cardTextImage, textBitmap);

هذا له ميزة إنتاج صورة نقطية لن يقلم أو تجاوز النص الذي يجب أن يحتوي عليه ، وهو أمر مهم بالنسبة للأدوات المصغّرة حيث تختلف أبعادها بين الأجهزة والإصدارات.

لا يمكنني العثور عليه الآن ، لكنني طرحت نفس السؤال وحصلت على رد من Google بأن هذا غير ممكن. أنت مقيد حقًا بما يمكنك فعله باستخدام AppWidgets ، على سبيل المثال ، يمكنك فقط استخدام أجهزة واجهة المستخدم معينة فقط ولا يمكنك استخدام الخطوط المخصصة.

remoteviews.setTextViewText(textview_id, new SpannableStringBuilder(Html.fromHtml("<b>"+some_text_vaeiable"+"</b>")) );

هذه هي الطريقة التي أفعل بها في تطبيقاتي ، يجب أن تنطبق على الأدوات أيضًا.

Typeface customfont = Typeface.createFromAsset(getAssets(), "fonts/somefont.ttf");
TextView textview = (TextView) findViewById(R.id.textview);
textview.setTypeface(customfont);
textview.setText("Hey custom font!"); 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top