Use a star to notify available updates to dictionaries
CHANGELOG.md
20 | 20 | * Fix alignment in dictionary list. | |
21 | 21 | * Small alignment and size fixes in dictionary download screen. | |
22 | 22 | * Add back button to action bars to better navigate between screens. | |
23 | + | * Use a star to notify dictionary updates instead of background color. | |
23 | 24 | ||
24 | 25 | ### Features | |
25 | 26 |
app/src/main/java/eu/lepiller/nani/DictionaryActivity.java
1 | 1 | package eu.lepiller.nani; | |
2 | 2 | ||
3 | 3 | import android.content.Intent; | |
4 | + | import android.graphics.drawable.Drawable; | |
4 | 5 | import android.os.AsyncTask; | |
5 | 6 | import android.os.Bundle; | |
6 | 7 | import androidx.appcompat.app.AppCompatActivity; | |
… | |||
22 | 23 | import java.net.MalformedURLException; | |
23 | 24 | import java.net.URL; | |
24 | 25 | import java.util.ArrayList; | |
26 | + | import java.util.HashMap; | |
25 | 27 | ||
26 | 28 | import eu.lepiller.nani.dictionary.DictionariesAdapter; | |
27 | 29 | import eu.lepiller.nani.dictionary.DictionaryFactory; |
app/src/main/java/eu/lepiller/nani/DictionaryDownloadActivity.java
80 | 80 | setContentView(R.layout.activity_dictionary_download); | |
81 | 81 | Bundle extras = getIntent().getExtras(); | |
82 | 82 | ||
83 | - | getSupportActionBar().setDisplayHomeAsUpEnabled(true); | |
84 | - | ||
85 | 83 | // TODO: this will open the first dictionary on error, we probably want to display a proper | |
86 | 84 | // error instead. | |
87 | 85 | int position = 0; |
app/src/main/java/eu/lepiller/nani/dictionary/DictionariesAdapter.java
1 | 1 | package eu.lepiller.nani.dictionary; | |
2 | 2 | ||
3 | 3 | import android.content.Context; | |
4 | + | import android.graphics.Typeface; | |
4 | 5 | import android.graphics.drawable.Drawable; | |
5 | 6 | import android.view.LayoutInflater; | |
6 | 7 | import android.view.View; | |
… | |||
18 | 19 | ||
19 | 20 | public class DictionariesAdapter extends ArrayAdapter<Dictionary> { | |
20 | 21 | private Context context; | |
22 | + | ||
21 | 23 | public DictionariesAdapter(Context context, ArrayList<Dictionary> dictionaries) { | |
22 | 24 | super(context, 0, dictionaries); | |
23 | 25 | this.context = context; | |
… | |||
45 | 47 | TextView entry_count_view = convertView.findViewById(R.id.entries_view); | |
46 | 48 | ||
47 | 49 | // Populate the data into the template view using the data object | |
48 | - | Drawable icon = dictionary.getDrawable(context); | |
50 | + | Drawable icon; | |
51 | + | if (dictionary.isDownloaded() && !dictionary.isUpToDate()) | |
52 | + | icon = dictionary.getNewDrawable(context); | |
53 | + | else | |
54 | + | icon = dictionary.getDrawable(context); | |
55 | + | ||
49 | 56 | if(icon != null) { | |
50 | 57 | Drawable.ConstantState state = icon.getConstantState(); | |
51 | 58 | if(state != null) { | |
… | |||
59 | 66 | } | |
60 | 67 | ||
61 | 68 | name_view.setText(dictionary.getName()); | |
69 | + | if(!dictionary.isUpToDate() && dictionary.isDownloaded()) { | |
70 | + | name_view.setTypeface(null, Typeface.BOLD); | |
71 | + | } else { | |
72 | + | name_view.setTypeface(null, Typeface.NORMAL); | |
73 | + | } | |
62 | 74 | description_view.setText(dictionary.getDescription()); | |
63 | - | if(!dictionary.isUpToDate() && dictionary.isDownloaded()) | |
64 | - | convertView.setBackgroundColor(context.getResources().getColor(R.color.colorUpdate)); | |
65 | - | else | |
66 | - | convertView.setBackgroundColor(0); | |
67 | 75 | ||
68 | 76 | int size = dictionary.getExpectedFileSize(); | |
69 | 77 | NumberFormat nf = NumberFormat.getInstance(); |
app/src/main/java/eu/lepiller/nani/dictionary/Dictionary.java
1 | 1 | package eu.lepiller.nani.dictionary; | |
2 | 2 | ||
3 | 3 | import android.content.Context; | |
4 | + | import android.graphics.Bitmap; | |
5 | + | import android.graphics.BitmapFactory; | |
6 | + | import android.graphics.Canvas; | |
7 | + | import android.graphics.drawable.BitmapDrawable; | |
4 | 8 | import android.graphics.drawable.Drawable; | |
5 | 9 | import android.os.Build; | |
10 | + | import android.util.Log; | |
6 | 11 | import android.util.Pair; | |
7 | 12 | ||
8 | 13 | import java.io.File; | |
… | |||
15 | 20 | import java.security.NoSuchAlgorithmException; | |
16 | 21 | import java.util.Map; | |
17 | 22 | ||
23 | + | import eu.lepiller.nani.R; | |
24 | + | ||
18 | 25 | abstract public class Dictionary { | |
19 | 26 | private String name; | |
20 | 27 | private String description, fullDescription; | |
… | |||
23 | 30 | private String sha256; | |
24 | 31 | private File file, temporaryFile; | |
25 | 32 | ||
33 | + | private static Drawable drawable=null, newDrawable=null; | |
34 | + | private static final String TAG = "DICO"; | |
35 | + | ||
26 | 36 | Dictionary(String n, String descr, String fullDescr, File cacheDir, int fileSize, int entries, String hash) { | |
27 | 37 | name = n; | |
28 | 38 | description = descr; | |
… | |||
71 | 81 | public abstract Map<String, Pair<File, File>> getDownloads(); | |
72 | 82 | ||
73 | 83 | public Drawable getDrawable(Context context) { | |
74 | - | Drawable drawable; | |
75 | - | int drawableResId = getDrawableId(); | |
76 | - | if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { | |
77 | - | drawable = context.getResources().getDrawable(drawableResId, context.getTheme()); | |
78 | - | } else { | |
79 | - | drawable = context.getResources().getDrawable(drawableResId); | |
84 | + | if(drawable == null) { | |
85 | + | int drawableResId = getDrawableId(); | |
86 | + | if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { | |
87 | + | drawable = context.getResources().getDrawable(drawableResId, context.getTheme()); | |
88 | + | } else { | |
89 | + | drawable = context.getResources().getDrawable(drawableResId); | |
90 | + | } | |
80 | 91 | } | |
81 | 92 | return drawable; | |
82 | 93 | } | |
83 | 94 | ||
95 | + | private Bitmap drawableToBitmap(Drawable drawable) { | |
96 | + | Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), | |
97 | + | Bitmap.Config.ARGB_8888); | |
98 | + | Canvas canvas = new Canvas(bitmap); | |
99 | + | drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); | |
100 | + | drawable.draw(canvas); | |
101 | + | return bitmap; | |
102 | + | } | |
103 | + | ||
104 | + | private Bitmap drawableToBitmap(Drawable drawable, int width, int height) { | |
105 | + | Bitmap background = drawableToBitmap(drawable); | |
106 | + | return Bitmap.createScaledBitmap(background, width, height, false); | |
107 | + | } | |
108 | + | ||
109 | + | public Drawable getNewDrawable(Context context) { | |
110 | + | if(newDrawable == null) { | |
111 | + | Bitmap big = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_8888); | |
112 | + | Canvas canvas = new Canvas(big); | |
113 | + | ||
114 | + | // Ensure we have the base icon | |
115 | + | getDrawable(context); | |
116 | + | ||
117 | + | Drawable star; | |
118 | + | if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { | |
119 | + | star = context.getResources().getDrawable(R.drawable.ic_star, context.getTheme()); | |
120 | + | } else { | |
121 | + | star = context.getResources().getDrawable(R.drawable.ic_star); | |
122 | + | } | |
123 | + | ||
124 | + | canvas.drawBitmap(drawableToBitmap(drawable, 64, 64), 0, 0, null); | |
125 | + | canvas.drawBitmap(drawableToBitmap(star, 22, 22), 39, 39, null); | |
126 | + | newDrawable = new BitmapDrawable(context.getResources(), big); | |
127 | + | } | |
128 | + | return newDrawable; | |
129 | + | } | |
130 | + | ||
84 | 131 | abstract int getDrawableId(); | |
85 | 132 | ||
86 | 133 | abstract public void remove(); |
app/src/main/res/drawable/ic_star.xml unknown status 1
1 | + | <vector xmlns:android="http://schemas.android.com/apk/res/android" | |
2 | + | android:width="16dp" | |
3 | + | android:height="16dp" | |
4 | + | android:viewportWidth="16" | |
5 | + | android:viewportHeight="16"> | |
6 | + | <path | |
7 | + | android:pathData="M16,12.7132 L10.2328,11.9042 6.2681,16 5.2885,10.4919 -0,8.1428 5.1618,5.5476l0.6962,-5.5476 4.1698,3.9042 5.7188,-1.0796 -2.5847,5.0081z" | |
8 | + | android:strokeWidth="0.26458332" | |
9 | + | android:fillColor="#ffdd55"/> | |
10 | + | </vector> |