package com.aviary.android.feather.widget; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import com.aviary.android.feather.R; // TODO: Auto-generated Javadoc /** * The Class ImageButtonRadioGroup. */ public class ImageButtonRadioGroup extends LinearLayout { /** The m checked id. */ private int mCheckedId = -1; /** The m last button. */ private int mFirstButton, mCenterButton, mLastButton; /** The m child on checked change listener. */ private ImageButtonRadioButton.OnCheckedChangeListener mChildOnCheckedChangeListener; /** The m protect from checked change. */ private boolean mProtectFromCheckedChange = false; /** The m on checked change listener. */ private OnCheckedChangeListener mOnCheckedChangeListener; /** The m pass through listener. */ private PassThroughHierarchyChangeListener mPassThroughListener; /** * Instantiates a new image button radio group. * * @param context * the context */ public ImageButtonRadioGroup( Context context ) { super( context ); setOrientation( HORIZONTAL ); init(); } /** * Instantiates a new image button radio group. * * @param context * the context * @param attrs * the attrs */ public ImageButtonRadioGroup( Context context, AttributeSet attrs ) { super( context, attrs ); TypedArray attributes = context.obtainStyledAttributes( attrs, R.styleable.ImageButtonRadioGroup, /* * R.attr. * imageButtonRadioButtonStyle */0, 0 ); int value = attributes.getResourceId( R.styleable.ImageButtonRadioGroup_checkedButton, View.NO_ID ); if ( value != View.NO_ID ) { mCheckedId = value; } mFirstButton = attributes.getResourceId( R.styleable.ImageButtonRadioGroup_firstButton, View.NO_ID ); mLastButton = attributes.getResourceId( R.styleable.ImageButtonRadioGroup_lastButton, View.NO_ID ); mCenterButton = attributes.getResourceId( R.styleable.ImageButtonRadioGroup_centerButton, View.NO_ID ); final int index = attributes.getInt( R.styleable.ImageButtonRadioGroup_checkedButton, HORIZONTAL ); setOrientation( index ); attributes.recycle(); init(); } /** * Inits the. */ private void init() { mChildOnCheckedChangeListener = new CheckedStateTracker(); mPassThroughListener = new PassThroughHierarchyChangeListener(); super.setOnHierarchyChangeListener( mPassThroughListener ); } /* * (non-Javadoc) * * @see android.widget.LinearLayout#onLayout(boolean, int, int, int, int) */ @Override protected synchronized void onLayout( boolean changed, int l, int t, int r, int b ) { super.onLayout( changed, l, t, r, b ); if ( changed ) { for ( int i = 0; i < getChildCount(); i++ ) { View child = getChildAt( i ); if ( child instanceof ImageButtonRadioButton ) { ImageButtonRadioButton button = ( (ImageButtonRadioButton) child ); if ( i == 0 ) { button.setButton( mFirstButton ); } else if ( i == getChildCount() - 1 ) { button.setButton( mLastButton ); } else { button.setButton( mCenterButton ); } } } } } /* * (non-Javadoc) * * @see android.view.ViewGroup#setOnHierarchyChangeListener(android.view.ViewGroup.OnHierarchyChangeListener) */ @Override public void setOnHierarchyChangeListener( OnHierarchyChangeListener listener ) { // the user listener is delegated to our pass-through listener mPassThroughListener.mOnHierarchyChangeListener = listener; } /* * (non-Javadoc) * * @see android.view.View#onFinishInflate() */ @Override protected void onFinishInflate() { super.onFinishInflate(); if ( mCheckedId != -1 ) { mProtectFromCheckedChange = true; setCheckedStateForView( mCheckedId, true ); mProtectFromCheckedChange = false; setCheckedId( mCheckedId, true ); } } /* * (non-Javadoc) * * @see android.view.ViewGroup#addView(android.view.View, int, android.view.ViewGroup.LayoutParams) */ @Override public void addView( View child, int index, ViewGroup.LayoutParams params ) { if ( child instanceof ImageButtonRadioButton ) { final ImageButtonRadioButton button = (ImageButtonRadioButton) child; if ( button.isChecked() ) { mProtectFromCheckedChange = true; if ( mCheckedId != -1 ) { setCheckedStateForView( mCheckedId, false ); } mProtectFromCheckedChange = false; setCheckedId( button.getId(), true ); } } super.addView( child, index, params ); } /** * Check. * * @param id * the id */ public void check( int id ) { if ( id != -1 && ( id == mCheckedId ) ) { return; } if ( mCheckedId != -1 ) { setCheckedStateForView( mCheckedId, false ); } if ( id != -1 ) { setCheckedStateForView( id, true ); } setCheckedId( id, true ); } /** * Sets the checked id. * * @param id * the id * @param isChecked * the is checked */ private void setCheckedId( int id, boolean isChecked ) { if ( isChecked ) mCheckedId = id; else mCheckedId = -1; if ( mOnCheckedChangeListener != null ) { mOnCheckedChangeListener.onCheckedChanged( this, mCheckedId, isChecked ); } } /** * Sets the checked state for view. * * @param viewId * the view id * @param checked * the checked */ private void setCheckedStateForView( int viewId, boolean checked ) { View checkedView = findViewById( viewId ); if ( checkedView != null && checkedView instanceof ImageButtonRadioButton ) { ( (ImageButtonRadioButton) checkedView ).setChecked( checked ); } } /** * Gets the checked radio button id. * * @return the checked radio button id */ public int getCheckedRadioButtonId() { return mCheckedId; } /** * Clear check. */ public void clearCheck() { check( -1 ); } /** * Sets the on checked change listener. * * @param listener * the new on checked change listener */ public void setOnCheckedChangeListener( OnCheckedChangeListener listener ) { mOnCheckedChangeListener = listener; } /* * (non-Javadoc) * * @see android.widget.LinearLayout#generateLayoutParams(android.util.AttributeSet) */ @Override public LayoutParams generateLayoutParams( AttributeSet attrs ) { return new ImageButtonRadioGroup.LayoutParams( getContext(), attrs ); } /* * (non-Javadoc) * * @see android.widget.LinearLayout#checkLayoutParams(android.view.ViewGroup.LayoutParams) */ @Override protected boolean checkLayoutParams( ViewGroup.LayoutParams p ) { return p instanceof ImageButtonRadioGroup.LayoutParams; } /* * (non-Javadoc) * * @see android.widget.LinearLayout#generateDefaultLayoutParams() */ @Override protected LinearLayout.LayoutParams generateDefaultLayoutParams() { return new LayoutParams( LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT ); } /** * The Class LayoutParams. */ public static class LayoutParams extends LinearLayout.LayoutParams { /** * Instantiates a new layout params. * * @param c * the c * @param attrs * the attrs */ public LayoutParams( Context c, AttributeSet attrs ) { super( c, attrs ); } /** * Instantiates a new layout params. * * @param w * the w * @param h * the h */ public LayoutParams( int w, int h ) { super( w, h ); } /** * Instantiates a new layout params. * * @param w * the w * @param h * the h * @param initWeight * the init weight */ public LayoutParams( int w, int h, float initWeight ) { super( w, h, initWeight ); } /** * Instantiates a new layout params. * * @param p * the p */ public LayoutParams( ViewGroup.LayoutParams p ) { super( p ); } /** * Instantiates a new layout params. * * @param source * the source */ public LayoutParams( MarginLayoutParams source ) { super( source ); } /* * (non-Javadoc) * * @see android.view.ViewGroup.LayoutParams#setBaseAttributes(android.content.res.TypedArray, int, int) */ @Override protected void setBaseAttributes( TypedArray a, int widthAttr, int heightAttr ) { if ( a.hasValue( widthAttr ) ) { width = a.getLayoutDimension( widthAttr, "layout_width" ); } else { width = MATCH_PARENT; } if ( a.hasValue( heightAttr ) ) { height = a.getLayoutDimension( heightAttr, "layout_height" ); } else { height = MATCH_PARENT; } } } /** * The listener interface for receiving onCheckedChange events. The class that is interested in processing a onCheckedChange * event implements this interface, and the object created with that class is registered with a component using the component's * <code>addOnCheckedChangeListener<code> method. When * the onCheckedChange event occurs, that object's appropriate * method is invoked. * * @see OnCheckedChangeEvent */ public interface OnCheckedChangeListener { /** * On checked changed. * * @param group * the group * @param checkedId * the checked id * @param isChecked * the is checked */ public void onCheckedChanged( ImageButtonRadioGroup group, int checkedId, boolean isChecked ); } /** * The Class CheckedStateTracker. */ private class CheckedStateTracker implements com.aviary.android.feather.widget.ImageButtonRadioButton.OnCheckedChangeListener { /* * (non-Javadoc) * * @see * com.aviary.android.feather.widget.ImageButtonRadioButton.OnCheckedChangeListener#onCheckedChanged(com.aviary.android.feather * .widget.ImageButtonRadioButton, boolean) */ @Override public void onCheckedChanged( ImageButtonRadioButton buttonView, boolean isChecked ) { if ( mProtectFromCheckedChange ) { return; } mProtectFromCheckedChange = true; if ( mCheckedId != -1 ) { setCheckedStateForView( mCheckedId, false ); } mProtectFromCheckedChange = false; int id = buttonView.getId(); setCheckedId( id, isChecked ); } } /** * The listener interface for receiving passThroughHierarchyChange events. The class that is interested in processing a * passThroughHierarchyChange event implements this interface, and the object created with that class is registered with a * component using the component's <code>addPassThroughHierarchyChangeListener<code> method. When * the passThroughHierarchyChange event occurs, that object's appropriate * method is invoked. * * @see PassThroughHierarchyChangeEvent */ private class PassThroughHierarchyChangeListener implements ViewGroup.OnHierarchyChangeListener { /** The m on hierarchy change listener. */ private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener; /* * (non-Javadoc) * * @see android.view.ViewGroup.OnHierarchyChangeListener#onChildViewAdded(android.view.View, android.view.View) */ @Override public void onChildViewAdded( View parent, View child ) { if ( parent == ImageButtonRadioGroup.this && child instanceof ImageButtonRadioButton ) { int id = child.getId(); if ( id == View.NO_ID ) { id = child.hashCode(); child.setId( id ); } ( (ImageButtonRadioButton) child ).setOnCheckedChangeWidgetListener( mChildOnCheckedChangeListener ); } if ( mOnHierarchyChangeListener != null ) { mOnHierarchyChangeListener.onChildViewAdded( parent, child ); } } /* * (non-Javadoc) * * @see android.view.ViewGroup.OnHierarchyChangeListener#onChildViewRemoved(android.view.View, android.view.View) */ @Override public void onChildViewRemoved( View parent, View child ) { if ( parent == ImageButtonRadioGroup.this && child instanceof ImageButtonRadioButton ) { ( (ImageButtonRadioButton) child ).setOnCheckedChangeWidgetListener( null ); } if ( mOnHierarchyChangeListener != null ) { mOnHierarchyChangeListener.onChildViewRemoved( parent, child ); } } } }