Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 180 additions & 17 deletions app/src/main/java/com/melnykov/letterimageview/LetterImageView.java
Original file line number Diff line number Diff line change
@@ -1,61 +1,143 @@
package com.melnykov.letterimageview;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.widget.ImageView;
import com.melnykov.initialsimageview.R;

import java.util.Random;

@SuppressWarnings({"UnusedDeclaration", "NullableProblems"})
public class LetterImageView extends ImageView {

public static final int SHAPE_RECTANGLE = 0;
public static final int SHAPE_OVAL = 1;

private static String[] colorsArray;
private static int defaultShape;

private char mLetter;
private Paint mTextPaint;
private Paint mBackgroundPaint;
private int mTextColor = Color.WHITE;
private boolean isOval;
private int shape;
private Rect textBounds;
private float textPadding = -1;
private int shapeColor = -1;

/**
* Initialize default parameters.
* @param context not null context
* @param colorsArrayRes resource ID of string-array with colors
* @param defaultShape default shape
*/
public static void init(final Context context, int colorsArrayRes, int defaultShape) throws Resources.NotFoundException {
LetterImageView.defaultShape = defaultShape;
LetterImageView.colorsArray = context.getResources().getStringArray(colorsArrayRes);
}

public LetterImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}

/**
* Init default values
*/
private void init() {
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(mTextColor);
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBackgroundPaint.setStyle(Paint.Style.FILL);
mBackgroundPaint.setColor(randomColor());
mBackgroundPaint.setColor(shapeColor = randomColor());
textBounds = new Rect();
// Set a default padding to 8dp
textPadding = 8 * getResources().getDisplayMetrics().density;
shape = defaultShape;
}

/**
* Get letter
* @return letter
*/
public char getLetter() {
return mLetter;
}

/**
* Set letter
* @param letter letter
*/
public void setLetter(char letter) {
mLetter = letter;
invalidate();
}

/**
* Get text color
* @return text color
*/
public int getTextColor() {
return mTextColor;
}

/**
* Set text color
* @param textColor text color
*/
public void setTextColor(int textColor) {
mTextColor = textColor;
invalidate();
}

/**
* Set shape of image view.<br/>
* Deprecated. Use {@link com.melnykov.letterimageview.LetterImageView#setShape(int) setShape} instead.
*/
@Deprecated
public void setOval(boolean oval) {
isOval = oval;
if (oval)
shape = SHAPE_OVAL;
else
shape = SHAPE_RECTANGLE;
}

/**
* Get shape of image view
* @return true if shape is oval
* @see com.melnykov.letterimageview.LetterImageView#setShape(int)
* @see com.melnykov.letterimageview.LetterImageView#getShape()
*/
@Deprecated
public boolean isOval() {
return isOval;
return shape == SHAPE_OVAL;
}

/**
* Set shape of image view
* @param shape shape constant
*/
public void setShape(int shape) {
if (
shape != SHAPE_RECTANGLE && // is rectangle
shape != SHAPE_OVAL && // is oval
!isCustomShape(shape) // is custom shape
)
// no, throw an error
throw new IllegalArgumentException("Shape value should be taken from constants");
this.shape = shape;
}

/**
* Get shape of image view
* @return shape of image view
*/
public int getShape() {
return shape;
}

@Override
Expand All @@ -64,15 +146,21 @@ protected void onDraw(Canvas canvas) {

if (getDrawable() == null) {
// Set a text font size based on the height of the view
mTextPaint.setTextSize(canvas.getHeight() - getTextPadding() * 2);
if (isOval()) {
canvas.drawCircle(canvas.getWidth() / 2f, canvas.getHeight() / 2f, Math.min(canvas.getWidth(), canvas.getHeight()) / 2f,
mBackgroundPaint);
} else {
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mBackgroundPaint);
mTextPaint.setTextSize(canvas.getHeight() - getTextPadding(true));
if (!drawShape(canvas)) {
// if children can't draw shape, try to draw it on our own
switch (shape) {
case SHAPE_RECTANGLE:
drawRectangle(canvas);
break;
case SHAPE_OVAL:
drawOval(canvas);
break;
default:
throw new IllegalArgumentException("Invalid shape value");
}
}
// Measure a text
Rect textBounds = new Rect();
mTextPaint.getTextBounds(String.valueOf(mLetter), 0, 1, textBounds);
float textWidth = mTextPaint.measureText(String.valueOf(mLetter));
float textHeight = textBounds.height();
Expand All @@ -82,14 +170,89 @@ protected void onDraw(Canvas canvas) {
}
}

private float getTextPadding() {
// Set a default padding to 8dp
return 8 * getResources().getDisplayMetrics().density;
private void drawRectangle(final Canvas canvas) {
canvas.drawRect(getPaddingLeft(), getPaddingTop(), canvas.getWidth() - getPaddingRight(),
canvas.getHeight() - getPaddingBottom(), mBackgroundPaint);
}

private void drawOval(final Canvas canvas) {
// check for padding
final int minSize = Math.min(canvas.getWidth(), canvas.getHeight());
final int padding;
if (minSize == canvas.getWidth())
padding = getPaddingRight() + getPaddingLeft();
else
padding = getPaddingTop() + getPaddingBottom();
float radius = (minSize - padding) / 2f;
canvas.drawCircle(canvas.getWidth() / 2f, canvas.getHeight() / 2f, radius, mBackgroundPaint);
}

/**
* Get text padding
* @param withImageViewPadding set true if need padding with image view's padding
* @return text padding
*/
public float getTextPadding(boolean withImageViewPadding) {
float padding = textPadding;
if (withImageViewPadding)
padding += getPaddingTop() + getPaddingBottom();
return padding;
}

/**
* Set additional text padding
* @param textPadding text padding
*/
public void setTextPadding(float textPadding) {
if (textPadding < 0)
throw new IllegalArgumentException("Text padding must be greater or equals zero");
this.textPadding = textPadding;
}

/**
* Get shape color
* @return shape color
*/
public int getShapeColor() {
return shapeColor;
}

/**
* Set shape color
* @param shapeColor shape color
*/
public void setShapeColor(int shapeColor) {
this.shapeColor = shapeColor;
mBackgroundPaint.setColor(shapeColor);
invalidate();
}

/**
* Generate random color
* @return random color or {@link Color#TRANSPARENT} if colors array not specified
*/
private int randomColor() {
if (colorsArray == null)
return Color.TRANSPARENT;
Random random = new Random();
String[] colorsArr = getResources().getStringArray(R.array.colors);
return Color.parseColor(colorsArr[random.nextInt(colorsArr.length)]);
return Color.parseColor(colorsArray[random.nextInt(colorsArray.length)]);
}

/**
* Draw custom shape. Place your custom implementation of drawShape here.
* @param canvas canvas
* @return true if shape was drawn
*/
protected boolean drawShape(Canvas canvas) {
return false;
}

/**
* Check if specified shape can be drawn
* @param shape shape constant
* @return true if shape can be drawn
*/
protected boolean isCustomShape(int shape) {
return false;
}
}
46 changes: 32 additions & 14 deletions app/src/main/java/com/melnykov/letterimageview/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,64 @@
import android.app.ListActivity;
import android.content.Context;
import android.os.Bundle;
import android.view.*;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.TextView;
import com.melnykov.initialsimageview.R;

import java.util.Arrays;
import java.util.List;
import com.melnykov.initialsimageview.R;


public class MainActivity extends ListActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

ListAdapter listAdapter = new SampleListAdapter(this, Arrays.asList(getResources().getStringArray(R.array.names)));
LetterImageView.init(this, R.array.colors, LetterImageView.SHAPE_OVAL);
Adapter listAdapter = new Adapter(this);
String[] names = getResources().getStringArray(R.array.names);
for (String name : names)
listAdapter.add(new Data(name));
setListAdapter(listAdapter);
}

private static class SampleListAdapter extends ArrayAdapter<String> {
private static class Adapter extends ArrayAdapter<Data> {

public SampleListAdapter(Context context, List<String> objects) {
super(context, R.layout.list_item, objects);
public Adapter(Context context) {
super(context, R.layout.list_item);
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
String name = getItem(position);
Data data = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false);
}

LetterImageView letterImageView = (LetterImageView) convertView.findViewById(R.id.iv_avatar);
letterImageView.setOval(true);
TextView textView = (TextView) convertView.findViewById(R.id.tv_name);
letterImageView.setLetter(name.charAt(0));
textView.setText(name);
if (position % 2 == 0)
letterImageView.setShape(LetterImageView.SHAPE_OVAL);
else
letterImageView.setShape(LetterImageView.SHAPE_RECTANGLE);
// store current color
if (data.color == 0)
data.color = letterImageView.getShapeColor();
letterImageView.setShapeColor(data.color);
letterImageView.setLetter(data.text.charAt(0));
textView.setText(data.text);

return convertView;
}
}

private static class Data {
private int color;
private String text;

private Data(String text) {
this.text = text;
}
}
}
27 changes: 15 additions & 12 deletions app/src/main/res/layout/list_item.xml
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_width="match_parent"
android:layout_height="wrap_content">

<com.melnykov.letterimageview.LetterImageView
android:id="@+id/iv_avatar"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_margin="8dp"/>
android:id="@+id/iv_avatar"
android:layout_width="70dp"
android:layout_height="70dp"
android:layout_margin="8dp"
android:padding="8dp" />

<TextView android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/iv_avatar"
android:layout_centerVertical="true"
android:textSize="24sp"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toEndOf="@+id/iv_avatar"
android:layout_toRightOf="@+id/iv_avatar"
android:textSize="24sp" />
</RelativeLayout>
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.9.+'
classpath 'com.android.tools.build:gradle:0.13.2'
}
}

Expand Down
Loading