Java tutorial
/* * Copyright 2012 Feedlr * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.chalmers.feedlr.adapter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Date; import com.chalmers.feedlr.R; import com.chalmers.feedlr.database.DatabaseHelper; import android.content.Context; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.os.AsyncTask; import android.support.v4.widget.SimpleCursorAdapter; import android.text.format.DateUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; /** * The class FeedAdapter is a Cursor adapter used to create feed item views * with. * * @author Daniel Larsson * */ public class FeedAdapter extends SimpleCursorAdapter { Context context; DatabaseHelper db; private int numberOfViews; // Used for tagging ImageViews public FeedAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); this.context = context; this.db = new DatabaseHelper(context); } /** * Holds the children views for recycling. */ static class ViewHolder { private TextView text; private TextView author; private TextView timestamp; private ImageView profilePicture; private ImageView source; } @Override public View getView(int position, View convertView, ViewGroup parent) { return super.getView(position, convertView, parent); } @Override public void bindView(View v, Context context, Cursor c) { super.bindView(v, context, c); // Holds the views, so that a recycled view does not have to find its // XML view ViewHolder viewHolder = (ViewHolder) v.getTag(); // Remove the recycled profile picture viewHolder.profilePicture.setVisibility(View.INVISIBLE); // Get user id int colNumUserId = c.getColumnIndex(DatabaseHelper.ITEM_COLUMN_USER_ID); Cursor cursor = db.getUser(c.getInt(colNumUserId) + ""); cursor.moveToFirst(); // Set source image int colNumSource = cursor.getColumnIndex(DatabaseHelper.USER_COLUMN_SOURCE); if (cursor.getString(colNumSource).equals("facebook")) { viewHolder.source.setBackgroundResource(R.drawable.source_facebook); } else { viewHolder.source.setBackgroundResource(R.drawable.source_twitter); } // Display profile picture int colNumURL = cursor.getColumnIndex(DatabaseHelper.USER_COLUMN_IMGURL); String imgURL = cursor.getString(colNumURL); viewHolder.profilePicture.setTag(numberOfViews++); new DownloadImageTask(viewHolder.profilePicture).execute(imgURL); // Display username int colNumUsername = cursor.getColumnIndex(DatabaseHelper.USER_COLUMN_USERNAME); if (cursor.getString(colNumUsername).length() > 18) { viewHolder.author.setTextSize(16); } viewHolder.author.setText(cursor.getString(colNumUsername)); // Display timestamp int colNumTimestamp = c.getColumnIndex(DatabaseHelper.ITEM_COLUMN_TIMESTAMP); Date timestampDate = new Date(c.getLong(colNumTimestamp)); String parsedTimestamp = DateUtils.getRelativeDateTimeString(context, timestampDate.getTime(), DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0).toString(); viewHolder.timestamp.setText(stripTimestamp(parsedTimestamp)); } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { super.newView(context, cursor, parent); LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); View tempView = inflater.inflate(R.layout.feed_item, null); // Find views ViewHolder viewHolder = new ViewHolder(); viewHolder.text = (TextView) tempView.findViewById(R.id.feed_item_text); viewHolder.author = (TextView) tempView.findViewById(R.id.feed_item_author); viewHolder.timestamp = (TextView) tempView.findViewById(R.id.feed_item_timestamp); viewHolder.profilePicture = (ImageView) tempView.findViewById(R.id.feed_item_author_image); viewHolder.source = (ImageView) tempView.findViewById(R.id.feed_item_source_image); // Set fonts Typeface robotoThinItalic = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-ThinItalic.ttf"); Typeface robotoMedium = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Medium.ttf"); Typeface robotoLight = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Light.ttf"); viewHolder.text.setTypeface(robotoLight); viewHolder.timestamp.setTypeface(robotoThinItalic); viewHolder.author.setTypeface(robotoMedium); tempView.setTag(viewHolder); return tempView; } /** * Strips timestamp string from unwanted information. * * @param timestamp * String containing original timestamp * * @return timestamp Strin stripped from unwanted information */ public String stripTimestamp(String timestamp) { if (timestamp.contains(",")) { return (timestamp.substring(0, timestamp.indexOf(','))); } else { return timestamp; } } /** * * @param squareBitmap * original image * @return image with rounded corners */ public static Bitmap getRoundedCornerBitmap(Bitmap squareBitmap) { Bitmap roundedBitmap = Bitmap.createBitmap(squareBitmap.getWidth(), squareBitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(roundedBitmap); final int color = 0xff424242; final Paint paint = new Paint(); final Rect rect = new Rect(0, 0, squareBitmap.getWidth(), squareBitmap.getHeight()); final RectF rectF = new RectF(rect); final float roundPx = 8; paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); canvas.drawRoundRect(rectF, roundPx, roundPx, paint); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(squareBitmap, rect, rect, paint); return roundedBitmap; } /** * DownloadImageTask is an inner class that handles the downloading and * setting of profile pictures. The class is asynchronized, so multiple * calls can be made without having to wait for the first one to return. * * * @author Daniel Larsson * */ private class DownloadImageTask extends AsyncTask<String, Void, Bitmap> { // Avarage time: 270 ms private ImageView profilePicture; private String tag; public DownloadImageTask(ImageView profilePicture) { this.profilePicture = profilePicture; this.tag = profilePicture.getTag().toString(); } protected Bitmap doInBackground(String... strings) { try { URL imgValue = new URL(strings[0]); Bitmap thumbNail = BitmapFactory.decodeStream(imgValue.openConnection().getInputStream()); Bitmap bitmapScaled = Bitmap.createScaledBitmap(thumbNail, 70, 70, true); return bitmapScaled; } catch (MalformedURLException e) { Log.e(getClass().getName(), e.getMessage()); } catch (IOException e) { Log.e(getClass().getName(), e.getMessage()); } return null; } protected void onPostExecute(Bitmap result) { if (profilePicture.getTag().toString().equals(tag)) { profilePicture.setImageBitmap(getRoundedCornerBitmap(result)); profilePicture.setVisibility(View.VISIBLE); } } } }