The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2006 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package android.text.style; |
| 18 | |
Tor Norbye | 7b9c912 | 2013-05-30 16:48:33 -0700 | [diff] [blame] | 19 | import android.annotation.DrawableRes; |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 20 | import android.annotation.NonNull; |
| 21 | import android.annotation.Nullable; |
Mathew Inwood | 9cf99fd | 2018-08-14 15:31:03 +0100 | [diff] [blame] | 22 | import android.annotation.UnsupportedAppUsage; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 23 | import android.content.Context; |
| 24 | import android.graphics.Bitmap; |
| 25 | import android.graphics.BitmapFactory; |
| 26 | import android.graphics.drawable.BitmapDrawable; |
| 27 | import android.graphics.drawable.Drawable; |
| 28 | import android.net.Uri; |
| 29 | import android.util.Log; |
| 30 | |
| 31 | import java.io.InputStream; |
| 32 | |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 33 | /** |
| 34 | * Span that replaces the text it's attached to with a {@link Drawable} that can be aligned with |
| 35 | * the bottom or with the baseline of the surrounding text. The drawable can be constructed from |
| 36 | * varied sources: |
| 37 | * <ul> |
| 38 | * <li>{@link Bitmap} - see {@link #ImageSpan(Context, Bitmap)} and |
| 39 | * {@link #ImageSpan(Context, Bitmap, int)} |
| 40 | * </li> |
| 41 | * <li>{@link Drawable} - see {@link #ImageSpan(Drawable, int)}</li> |
| 42 | * <li>resource id - see {@link #ImageSpan(Context, int, int)}</li> |
| 43 | * <li>{@link Uri} - see {@link #ImageSpan(Context, Uri, int)}</li> |
| 44 | * </ul> |
| 45 | * The default value for the vertical alignment is {@link DynamicDrawableSpan#ALIGN_BOTTOM} |
| 46 | * <p> |
| 47 | * For example, an <code>ImagedSpan</code> can be used like this: |
| 48 | * <pre> |
| 49 | * SpannableString string = SpannableString("Bottom: span.\nBaseline: span."); |
| 50 | * // using the default alignment: ALIGN_BOTTOM |
| 51 | * string.setSpan(ImageSpan(this, R.mipmap.ic_launcher), 7, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
| 52 | * string.setSpan(ImageSpan(this, R.mipmap.ic_launcher, DynamicDrawableSpan.ALIGN_BASELINE), |
| 53 | * 22, 23, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); |
| 54 | * </pre> |
| 55 | * <img src="{@docRoot}reference/android/images/text/style/imagespan.png" /> |
| 56 | * <figcaption>Text with <code>ImageSpan</code>s aligned bottom and baseline.</figcaption> |
| 57 | */ |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 58 | public class ImageSpan extends DynamicDrawableSpan { |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 59 | |
| 60 | @Nullable |
Mathew Inwood | 9cf99fd | 2018-08-14 15:31:03 +0100 | [diff] [blame] | 61 | @UnsupportedAppUsage |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 62 | private Drawable mDrawable; |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 63 | @Nullable |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 64 | private Uri mContentUri; |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 65 | @DrawableRes |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 66 | private int mResourceId; |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 67 | @Nullable |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 68 | private Context mContext; |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 69 | @Nullable |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 70 | private String mSource; |
| 71 | |
Dianne Hackborn | 0cd6376 | 2009-07-29 17:36:27 -0700 | [diff] [blame] | 72 | /** |
| 73 | * @deprecated Use {@link #ImageSpan(Context, Bitmap)} instead. |
| 74 | */ |
Dianne Hackborn | 4a51c20 | 2009-08-21 15:14:02 -0700 | [diff] [blame] | 75 | @Deprecated |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 76 | public ImageSpan(@NonNull Bitmap b) { |
Dianne Hackborn | 0cd6376 | 2009-07-29 17:36:27 -0700 | [diff] [blame] | 77 | this(null, b, ALIGN_BOTTOM); |
| 78 | } |
| 79 | |
| 80 | /** |
Elliot Waite | 54de774 | 2017-01-11 15:30:35 -0800 | [diff] [blame] | 81 | * @deprecated Use {@link #ImageSpan(Context, Bitmap, int)} instead. |
Dianne Hackborn | 0cd6376 | 2009-07-29 17:36:27 -0700 | [diff] [blame] | 82 | */ |
Dianne Hackborn | 4a51c20 | 2009-08-21 15:14:02 -0700 | [diff] [blame] | 83 | @Deprecated |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 84 | public ImageSpan(@NonNull Bitmap b, int verticalAlignment) { |
Dianne Hackborn | 0cd6376 | 2009-07-29 17:36:27 -0700 | [diff] [blame] | 85 | this(null, b, verticalAlignment); |
| 86 | } |
| 87 | |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 88 | /** |
| 89 | * Constructs an {@link ImageSpan} from a {@link Context} and a {@link Bitmap} with the default |
| 90 | * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM} |
| 91 | * |
| 92 | * @param context context used to create a drawable from {@param bitmap} based on the display |
| 93 | * metrics of the resources |
| 94 | * @param bitmap bitmap to be rendered |
| 95 | */ |
| 96 | public ImageSpan(@NonNull Context context, @NonNull Bitmap bitmap) { |
| 97 | this(context, bitmap, ALIGN_BOTTOM); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | /** |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 101 | * Constructs an {@link ImageSpan} from a {@link Context}, a {@link Bitmap} and a vertical |
| 102 | * alignment. |
| 103 | * |
| 104 | * @param context context used to create a drawable from {@param bitmap} based on |
| 105 | * the display metrics of the resources |
| 106 | * @param bitmap bitmap to be rendered |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 107 | * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 108 | * {@link DynamicDrawableSpan#ALIGN_BASELINE} |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 109 | */ |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 110 | public ImageSpan(@NonNull Context context, @NonNull Bitmap bitmap, int verticalAlignment) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 111 | super(verticalAlignment); |
Dianne Hackborn | 0cd6376 | 2009-07-29 17:36:27 -0700 | [diff] [blame] | 112 | mContext = context; |
| 113 | mDrawable = context != null |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 114 | ? new BitmapDrawable(context.getResources(), bitmap) |
| 115 | : new BitmapDrawable(bitmap); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 116 | int width = mDrawable.getIntrinsicWidth(); |
| 117 | int height = mDrawable.getIntrinsicHeight(); |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 118 | mDrawable.setBounds(0, 0, width > 0 ? width : 0, height > 0 ? height : 0); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | /** |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 122 | * Constructs an {@link ImageSpan} from a drawable with the default |
| 123 | * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}. |
| 124 | * |
| 125 | * @param drawable drawable to be rendered |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 126 | */ |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 127 | public ImageSpan(@NonNull Drawable drawable) { |
| 128 | this(drawable, ALIGN_BOTTOM); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 129 | } |
| 130 | |
| 131 | /** |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 132 | * Constructs an {@link ImageSpan} from a drawable and a vertical alignment. |
| 133 | * |
| 134 | * @param drawable drawable to be rendered |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 135 | * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 136 | * {@link DynamicDrawableSpan#ALIGN_BASELINE} |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 137 | */ |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 138 | public ImageSpan(@NonNull Drawable drawable, int verticalAlignment) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 139 | super(verticalAlignment); |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 140 | mDrawable = drawable; |
| 141 | } |
| 142 | |
| 143 | /** |
| 144 | * Constructs an {@link ImageSpan} from a drawable and a source with the default |
| 145 | * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM} |
| 146 | * |
| 147 | * @param drawable drawable to be rendered |
| 148 | * @param source drawable's Uri source |
| 149 | */ |
| 150 | public ImageSpan(@NonNull Drawable drawable, @NonNull String source) { |
| 151 | this(drawable, source, ALIGN_BOTTOM); |
| 152 | } |
| 153 | |
| 154 | /** |
| 155 | * Constructs an {@link ImageSpan} from a drawable, a source and a vertical alignment. |
| 156 | * |
| 157 | * @param drawable drawable to be rendered |
| 158 | * @param source drawable's uri source |
| 159 | * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or |
| 160 | * {@link DynamicDrawableSpan#ALIGN_BASELINE} |
| 161 | */ |
| 162 | public ImageSpan(@NonNull Drawable drawable, @NonNull String source, int verticalAlignment) { |
| 163 | super(verticalAlignment); |
| 164 | mDrawable = drawable; |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 165 | mSource = source; |
| 166 | } |
| 167 | |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 168 | /** |
| 169 | * Constructs an {@link ImageSpan} from a {@link Context} and a {@link Uri} with the default |
| 170 | * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM}. The Uri source can be retrieved via |
| 171 | * {@link #getSource()} |
| 172 | * |
| 173 | * @param context context used to create a drawable from {@param bitmap} based on the display |
| 174 | * metrics of the resources |
| 175 | * @param uri {@link Uri} used to construct the drawable that will be rendered |
| 176 | */ |
| 177 | public ImageSpan(@NonNull Context context, @NonNull Uri uri) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 178 | this(context, uri, ALIGN_BOTTOM); |
| 179 | } |
| 180 | |
| 181 | /** |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 182 | * Constructs an {@link ImageSpan} from a {@link Context}, a {@link Uri} and a vertical |
| 183 | * alignment. The Uri source can be retrieved via {@link #getSource()} |
| 184 | * |
| 185 | * @param context context used to create a drawable from {@param bitmap} based on |
| 186 | * the display |
| 187 | * metrics of the resources |
| 188 | * @param uri {@link Uri} used to construct the drawable that will be rendered. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 189 | * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 190 | * {@link DynamicDrawableSpan#ALIGN_BASELINE} |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 191 | */ |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 192 | public ImageSpan(@NonNull Context context, @NonNull Uri uri, int verticalAlignment) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 193 | super(verticalAlignment); |
| 194 | mContext = context; |
| 195 | mContentUri = uri; |
The Android Open Source Project | ba87e3e | 2009-03-13 13:04:22 -0700 | [diff] [blame] | 196 | mSource = uri.toString(); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 197 | } |
| 198 | |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 199 | /** |
| 200 | * Constructs an {@link ImageSpan} from a {@link Context} and a resource id with the default |
| 201 | * alignment {@link DynamicDrawableSpan#ALIGN_BOTTOM} |
| 202 | * |
| 203 | * @param context context used to retrieve the drawable from resources |
| 204 | * @param resourceId drawable resource id based on which the drawable is retrieved |
| 205 | */ |
| 206 | public ImageSpan(@NonNull Context context, @DrawableRes int resourceId) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 207 | this(context, resourceId, ALIGN_BOTTOM); |
| 208 | } |
| 209 | |
| 210 | /** |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 211 | * Constructs an {@link ImageSpan} from a {@link Context}, a resource id and a vertical |
| 212 | * alignment. |
| 213 | * |
| 214 | * @param context context used to retrieve the drawable from resources |
| 215 | * @param resourceId drawable resource id based on which the drawable is retrieved. |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 216 | * @param verticalAlignment one of {@link DynamicDrawableSpan#ALIGN_BOTTOM} or |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 217 | * {@link DynamicDrawableSpan#ALIGN_BASELINE} |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 218 | */ |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 219 | public ImageSpan(@NonNull Context context, @DrawableRes int resourceId, |
| 220 | int verticalAlignment) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 221 | super(verticalAlignment); |
| 222 | mContext = context; |
| 223 | mResourceId = resourceId; |
| 224 | } |
| 225 | |
| 226 | @Override |
| 227 | public Drawable getDrawable() { |
| 228 | Drawable drawable = null; |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 229 | |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 230 | if (mDrawable != null) { |
| 231 | drawable = mDrawable; |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 232 | } else if (mContentUri != null) { |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 233 | Bitmap bitmap = null; |
| 234 | try { |
| 235 | InputStream is = mContext.getContentResolver().openInputStream( |
| 236 | mContentUri); |
| 237 | bitmap = BitmapFactory.decodeStream(is); |
Dianne Hackborn | 11ea334 | 2009-07-22 21:48:55 -0700 | [diff] [blame] | 238 | drawable = new BitmapDrawable(mContext.getResources(), bitmap); |
The Android Open Source Project | ba87e3e | 2009-03-13 13:04:22 -0700 | [diff] [blame] | 239 | drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), |
| 240 | drawable.getIntrinsicHeight()); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 241 | is.close(); |
| 242 | } catch (Exception e) { |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 243 | Log.e("ImageSpan", "Failed to loaded content " + mContentUri, e); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 244 | } |
| 245 | } else { |
| 246 | try { |
Alan Viverette | 8eea3ea | 2014-02-03 18:40:20 -0800 | [diff] [blame] | 247 | drawable = mContext.getDrawable(mResourceId); |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 248 | drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), |
| 249 | drawable.getIntrinsicHeight()); |
| 250 | } catch (Exception e) { |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 251 | Log.e("ImageSpan", "Unable to find resource: " + mResourceId); |
| 252 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 253 | } |
| 254 | |
| 255 | return drawable; |
| 256 | } |
| 257 | |
| 258 | /** |
| 259 | * Returns the source string that was saved during construction. |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 260 | * |
| 261 | * @return the source string that was saved during construction |
| 262 | * @see #ImageSpan(Drawable, String) and this{@link #ImageSpan(Context, Uri)} |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 263 | */ |
Florina Muntenescu | 139e1b5 | 2018-01-24 15:52:00 +0000 | [diff] [blame] | 264 | @Nullable |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 265 | public String getSource() { |
| 266 | return mSource; |
| 267 | } |
The Android Open Source Project | 9066cfe | 2009-03-03 19:31:44 -0800 | [diff] [blame] | 268 | } |