/*
* 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);
}
}
}
}