Skip to content

Instantly share code, notes, and snippets.

@firexel
Created March 1, 2012 19:15
Show Gist options
  • Save firexel/1952421 to your computer and use it in GitHub Desktop.
Save firexel/1952421 to your computer and use it in GitHub Desktop.
package com.tornado.views;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import com.tornado.R;
import com.tornado.util.MathUtils;
import com.tornado.util.ViewUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: alex
* Date: 28.02.12
* Time: 12:38
*/
public class ChatIndicator extends View
{
private Drawable indicatorPrototype;
private List<Drawable> indicators = new ArrayList<Drawable>();
private int defaultHeight, selectedHeight;
private float position;
private static final int[][] STATE = new int[][]{
{},
{android.R.attr.state_expanded},
{android.R.attr.state_active},
{android.R.attr.state_expanded, android.R.attr.state_active}
} ;
public ChatIndicator(Context context)
{
this(context, null);
}
public ChatIndicator(Context context, AttributeSet attrs)
{
super(context, attrs);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ChatIndicator);
indicatorPrototype = array.getDrawable(R.styleable.ChatIndicator_indicator);
if (indicatorPrototype == null)
throw new IllegalStateException("Cannot create ChatIndicator without 'indicator' attribute");
final int minHeight = indicatorPrototype.getIntrinsicHeight();
defaultHeight = Math.max(array.getDimensionPixelSize(R.styleable.ChatIndicator_def_height, 8), minHeight);
selectedHeight = Math.max(array.getDimensionPixelSize(R.styleable.ChatIndicator_selected_height, 16), minHeight);
array.recycle();
}
public void setEnabled(int index, boolean enabled)
{
if (index >= indicators.size())
throw new ArrayIndexOutOfBoundsException(index);
Drawable indicator = indicators.get(index);
indicator.setState(getState(ViewUtils.contains(indicator.getState(), ViewUtils.STATE_EXPANDED), enabled));
}
public int[] getState(boolean expanded, boolean enabled)
{
return STATE[(expanded ? 0 : 1) + (enabled ? 0 : 2)];
}
public void setIndicatorsCount(int count)
{
while (indicators.size() < count) indicators.add(getIndicatorClone());
while (indicators.size() > count) indicators.remove(indicators.size() - 1);
setPosition(0);
}
private Drawable getIndicatorClone()
{
Drawable.ConstantState state = indicatorPrototype.getConstantState();
return state.newDrawable(getResources());
}
public void setPosition(float position)
{
position = MathUtils.crop(0, indicators.size(), position);
float width = getWidth();
int count = indicators.size();
this.position = position;
for (int i = 0; i < indicators.size(); i++)
{
int left = (int) (width / count * i);
int right = (int) (width / count * (i + 1));
int bottom;
float k = 1 - Math.abs(position - i);
if (k <= 0) bottom = defaultHeight;
else bottom = defaultHeight + (int) ((selectedHeight - defaultHeight) * k);
Drawable indicator = indicators.get(i);
indicator.setBounds(left, 0, right, bottom);
indicator.setState(getState(k >= 0.5f, ViewUtils.contains(indicator.getState(), ViewUtils.STATE_ACTIVE)));
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(widthSize, Math.max(selectedHeight, defaultHeight));
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
setPosition(position);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
for (Drawable indicator : indicators)
indicator.draw(canvas);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment