package com.flipkart.chatheads.ui;
import android.content.Context;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
import com.flipkart.chatheads.R;
import java.util.ArrayList;
/**
* Created by kirankumar on 17/02/15.
*/
public class UpArrowLayout extends ViewGroup {
private final Point pointTo = new Point(0, 0);
private final ArrayList<View> mMatchParentChildren = new ArrayList<View>(1);
private ImageView arrowView;
private int arrowDrawable = R.drawable.chat_top_arrow;
public UpArrowLayout(Context context) {
super(context);
init();
}
public UpArrowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public UpArrowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public int getArrowDrawable() {
return arrowDrawable;
}
public void setArrowDrawable(int arrowDrawable) {
this.arrowDrawable = arrowDrawable;
init();
}
private void init() {
if (arrowView != null) {
removeView(arrowView);
}
arrowView = createArrowView();
addView(arrowView);
}
protected ImageView createArrowView() {
Drawable drawable = getResources().getDrawable(arrowDrawable);
ImageView imageView = new ImageView(getContext());
imageView.setImageDrawable(drawable);
return imageView;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount();
int measureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
arrowView.measure(measureSpec, measureSpec);
int arrowViewMeasuredHeight = arrowView.getMeasuredHeight();
int size = MeasureSpec.getSize(heightMeasureSpec);
if (size > arrowViewMeasuredHeight) {
size -= arrowViewMeasuredHeight + pointTo.y;
heightMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.getMode(heightMeasureSpec));
}
final boolean measureMatchParentChildren =
MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.EXACTLY ||
MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY;
int maxHeight = 0;
int maxWidth = 0;
int childState = 0;
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child == arrowView) continue;
if (child.getVisibility() != GONE) {
measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
maxWidth = Math.max(maxWidth,
child.getMeasuredWidth());
maxHeight = Math.max(maxHeight,
child.getMeasuredHeight());
childState = combineMeasuredStates(childState, child.getMeasuredState());
if (measureMatchParentChildren) {
if (lp.width == LayoutParams.MATCH_PARENT ||
lp.height == LayoutParams.MATCH_PARENT) {
mMatchParentChildren.add(child);
}
}
}
}
// Check against our minimum height and width
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
resolveSizeAndState(maxHeight, heightMeasureSpec,
childState << MEASURED_HEIGHT_STATE_SHIFT));
count = mMatchParentChildren.size();
if (count > 1) {
for (int i = 0; i < count; i++) {
final View child = mMatchParentChildren.get(i);
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
int childWidthMeasureSpec;
int childHeightMeasureSpec;
if (lp.width == LayoutParams.MATCH_PARENT) {
childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth() -
lp.leftMargin - lp.rightMargin,
MeasureSpec.EXACTLY);
} else {
childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
lp.leftMargin + lp.rightMargin,
lp.width);
}
if (lp.height == LayoutParams.MATCH_PARENT) {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight() -
lp.topMargin - lp.bottomMargin,
MeasureSpec.EXACTLY);
} else {
childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
lp.topMargin + lp.bottomMargin,
lp.height);
}
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
}
setMeasuredDimension(getMeasuredWidth(), getMeasuredHeight() + arrowViewMeasuredHeight + pointTo.y);
updatePointer();
}
protected void measureChildWithMargins(View child,
int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {
final LayoutParams lp = child.getLayoutParams();
final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, widthUsed, lp.width);
final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec,
+heightUsed, lp.height);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
public void pointTo(final int viewX, final int viewY) {
pointTo.x = viewX;
pointTo.y = viewY;
if (getMeasuredHeight() != 0 && getMeasuredWidth() != 0) {
updatePointer();
}
invalidate();
}
private void updatePointer() {
int x = (int) (pointTo.x - arrowView.getMeasuredWidth() / 2);
int y = pointTo.y;
if (x != arrowView.getTranslationX()) {
arrowView.setTranslationX(x);
}
if (y != arrowView.getTranslationY()) {
arrowView.setTranslationY(y);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
arrowView.layout(left, top, left + arrowView.getMeasuredWidth(), top + arrowView.getMeasuredHeight());
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child == arrowView) continue;
child.layout(left, top + arrowView.getMeasuredHeight() + pointTo.y, right, bottom);
}
}
protected LayoutParams generateDefaultLayoutParams() {
return new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new FrameLayout.LayoutParams(getContext(), attrs);
}
@Override
public void removeAllViews() {
super.removeAllViews();
addView(arrowView);
}
}