Hi all
if you have been a regular visitor of this website you have seen that I have shown you how to create a simple widget, adding controls to it, adding event handlers in the views etc…
Do check this website for more tutorials on widgets.
You can find other tutorials by following this LINK.
This tutorial is also an important one on widgets.
People always find it difficult to customize their widgets with Custom Fonts. AS of now you cannot directly set the font in a TextView in a Widget. For that you have to go indirectly.
In this example I will show you how to create a Clock widget with Custom Font.
So we will start.
At first we will create the XML files.
acitvity_main.xml – This is our main layout which contains a button that creates the widget.
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:background="@android:color/white" > <button android:id="@+id/create_widget" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="Create Widget"></button> </relativelayout>
Now the layout for the Widget and the WidgetProvider.
my_widget_provider.xml
< ?xml version="1.0" encoding="utf-8"?> <appwidget -provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="250dip" android:minHeight="70dip" android:updatePeriodMillis="300000" android:configure="com.coderzheaven.customfontinwidget.SettingsPage" android:initialLayout="@layout/widget_main"></appwidget>
widget_main.xml
< ?xml version="1.0" encoding="utf-8"?> <framelayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widget_root" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:baselineAligned="false" android:orientation="vertical" > <imageview android:id="@+id/imageView_bg" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitXY" android:contentDescription="@drawable/ic_launcher"></imageview> <imageview android:id="@+id/imageView_txt" android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitXY" android:contentDescription="@drawable/ic_launcher"></imageview> </framelayout>
OK Now the AndroidManifest File.
Do look at my old posts for more explanation about the Mainfest files when you are using the widgets.
< ?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.coderzheaven.customfontinwidget" android:versionCode="1" android:versionName="1.0" > <uses -sdk android:minSdkVersion="8" android:targetSdkVersion="17"></uses> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.coderzheaven.customfontinwidget.SettingsPage" android:configChanges="keyboardHidden|orientation" android:label="@string/app_name" android:theme="@android:style/Theme.Translucent" > <intent -filter> <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"></action> </intent> </activity> <receiver android:name=".RepeatingAlarm" android:process=":remote"></receiver> <!-- Broadcast Receiver that will process AppWidget Updates --> <receiver android:name="com.coderzheaven.customfontinwidget.MyAppWidgetProvider" android:label="@string/app_name" > <intent -filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE"></action> </intent> <meta -data android:name="android.appwidget.provider" android:resource="@layout/my_widget_provider" /> </receiver> </application> </manifest>
Now create an XML file inside the drawable folder and name it theme0.xml and copy this code into it.
< ?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item><shape> <gradient android:angle="90" android:centerColor="#7700FF00" android:endColor="#3300FF00" android:startColor="#3300FF00"></gradient> <stroke android:width="1dp" android:color="#FF00FF00"></stroke> <corners android:radius="10dp"></corners> <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp"></padding> </shape></item> </selector>
Now our XML files are over.
Now we look at the java code.
we have 4 java classes
1. MyAppWidgetProvider.java
2. MyTimer.java
3. RepeatingAlarm.java
4. SettingsPage.java
SettingsPage.java
package com.coderzheaven.customfontinwidget; import android.app.Activity; import android.appwidget.AppWidgetManager; import android.content.Intent; import android.graphics.Bitmap; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.RemoteViews; public class SettingsPage extends Activity implements OnClickListener { int thisWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getIdOfCurrentWidget(savedInstanceState); ((Button) findViewById(R.id.create_widget)).setOnClickListener(this); } /** * Get the Id of Current Widget from the intent from the Widget or if it is * the first time **/ void getIdOfCurrentWidget(Bundle savedInstanceState) { setResult(RESULT_CANCELED); Bundle extras = getIntent().getExtras(); if (extras != null) { thisWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID); } } /** * Update the widget on first run * * @param widgetId * - the ID of current widget to be created */ public void updateWidget(int widgetId) { RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.widget_main); MyTimer myTimer = new MyTimer(this); Bitmap bmp = myTimer.buildUpdate(myTimer.getTodaysTime()); remoteViews.setImageViewBitmap(R.id.imageView_txt, bmp); // set a background remoteViews.setImageViewResource(R.id.imageView_bg, R.drawable.theme0); AppWidgetManager appWidgetManager = AppWidgetManager .getInstance(SettingsPage.this); // update the widget appWidgetManager.updateAppWidget(widgetId, remoteViews); } public void setResultDataToWidget(int result, int widgetId) { System.out.println("WID ID = " + widgetId); // update the widget on creation updateWidget(widgetId); // set the result back to widget Intent resultValue = new Intent(); // pass the widget ID along with the intent so that we will get it on // the cofiguration activity resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); setResult(result, resultValue); finish(); } @Override public void onClick(View v) { if (v.getId() == R.id.create_widget) setResultDataToWidget(Activity.RESULT_OK, thisWidgetId); } }
MyAppWidgetProvider.java
package com.coderzheaven.customfontinwidget; import android.app.AlarmManager; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.Context; import android.content.Intent; import android.os.SystemClock; public class MyAppWidgetProvider extends AppWidgetProvider { @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { Intent intent = new Intent(context, RepeatingAlarm.class); PendingIntent sender = PendingIntent .getBroadcast(context, 0, intent, 0); // We want the alarm to go off 1 seconds from now. long firstTime = SystemClock.elapsedRealtime(); firstTime += 1000; // Schedule the alarm! AlarmManager am = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, firstTime, 1000, sender); } }
MyTimer.java
package com.coderzheaven.customfontinwidget; import java.util.Calendar; import android.appwidget.AppWidgetManager; import android.content.ComponentName; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Paint.Align; import android.graphics.Typeface; import android.widget.RemoteViews; public class MyTimer { RemoteViews remoteViews; Context context; AppWidgetManager appWidgetManager; ComponentName thisWidget; public MyTimer(Context context) { appWidgetManager = AppWidgetManager.getInstance(context); this.context = context; remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_main); thisWidget = new ComponentName(context, MyAppWidgetProvider.class); } public synchronized void runAndUpdateTheWidget() { int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget); for (final int appWidgetId : allWidgetIds) { System.out.println("UPDATING......" + getTodaysTime() + " ID = " + appWidgetId); remoteViews.setImageViewBitmap(R.id.imageView_txt, buildUpdate(getTodaysTime())); appWidgetManager.updateAppWidget(appWidgetId, remoteViews); } } public Bitmap buildUpdate(String time) { int bmpWidth = 250; int bmpHeight = 100; Bitmap myBitmap = Bitmap.createBitmap(bmpWidth, bmpHeight, Bitmap.Config.ARGB_8888); Canvas myCanvas = new Canvas(myBitmap); Paint paint = new Paint(); Typeface clock = Typeface.createFromAsset(context.getAssets(), "digital-7.ttf"); paint.setAntiAlias(true); paint.setSubpixelText(true); paint.setTypeface(clock); paint.setStyle(Paint.Style.FILL); paint.setColor(Color.RED); paint.setTextSize(70); paint.setTextAlign(Align.CENTER); myCanvas.drawText(time, bmpWidth / 2, bmpHeight / 2 + (bmpHeight / 4), paint); return myBitmap; } public String getTodaysTime() { final Calendar c = Calendar.getInstance(); int hour = Integer .parseInt(convertToNormal(c.get(Calendar.HOUR_OF_DAY))); int minute = c.get(Calendar.MINUTE); int seconds = c.get(Calendar.SECOND); return new StringBuilder().append(pad(hour)).append(":") .append(pad(minute)).append(":").append(pad(seconds)) .toString(); } private static String pad(int c) { if (c >= 10) return String.valueOf(c); else return "0" + String.valueOf(c); } public String convertToNormal(int hour) { if (hour > 12) hour = hour - 12; return pad(hour); } }
And the Broadcast receiver
RepeatingAlarm.java
package com.coderzheaven.customfontinwidget; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; public class RepeatingAlarm extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { MyTimer myTimer = new MyTimer(context); myTimer.runAndUpdateTheWidget(); } }
Your Clock widget with custom Font is complete, Go on and run it and Check in the widgets area.
You can download the complete source code from this link.
Please leave your valuable comments on this post. We have put a lot of effort on creating this post for you.
Hi:
Great Job, nice tutorials!
The link to the source code at the end of this page doesn’t work. Could you please correct it?
Pingback: Creating a Clock Widget in Android with Custom Font. - appgong
I shouldn’t need several pages of code to change a font. This is fucking insane
Its the complete Widget implementation,not just changing the font.
Looks like the source code link doesn’t work.
I have updated the link. Please check.
plz update the source code link again, I need it.
I have updated the link…please download again…
Thanks fro visiting.