package cn.trinea.android.common.util;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
/**
* ViewUtils
* <ul>
* <strong>get view height</strong>
* <li>{@link cn.trinea.android.common.util.ViewUtils#getListViewHeightBasedOnChildren(android.widget.ListView)}</li>
* <li>{@link cn.trinea.android.common.util.ViewUtils#getAbsListViewHeightBasedOnChildren(android.widget.AbsListView)}</li>
* </ul>
* <ul>
* <strong>set view height</strong>
* <li>{@link cn.trinea.android.common.util.ViewUtils#setViewHeight(android.view.View, int)} set view height</li>
* <li>{@link cn.trinea.android.common.util.ViewUtils#setListViewHeightBasedOnChildren(android.widget.ListView)}</li>
* <li>{@link cn.trinea.android.common.util.ViewUtils#setAbsListViewHeightBasedOnChildren(android.widget.AbsListView)}</li>
* </ul>
* <ul>
* <strong>get other info</strong>
* <li>{@link cn.trinea.android.common.util.ViewUtils#getGridViewVerticalSpacing(android.widget.GridView)} get GridView vertical spacing</li>
* </ul>
* <ul>
* <strong>set other info</strong>
* <li>{@link cn.trinea.android.common.util.ViewUtils#setSearchViewOnClickListener(android.view.View, android.view.View.OnClickListener)}</li>
* </ul>
*
* @author <a href="http://www.trinea.cn" target="_blank">Trinea</a> 2013-12-24
*/
public class ViewUtils {
private ViewUtils() {
throw new AssertionError();
}
/**
* get ListView height according to every children
*
* @param view
* @return
*/
public static int getListViewHeightBasedOnChildren(ListView view) {
int height = getAbsListViewHeightBasedOnChildren(view);
ListAdapter adapter;
int adapterCount;
if (view != null && (adapter = view.getAdapter()) != null && (adapterCount = adapter.getCount()) > 0) {
height += view.getDividerHeight() * (adapterCount - 1);
}
return height;
}
// /**
// * get GridView height according to every children
// *
// * @param view
// * @return
// */
// public static int getGridViewHeightBasedOnChildren(GridView view) {
// int height = getAbsListViewHeightBasedOnChildren(view);
// ListAdapter adapter;
// int adapterCount, numColumns = getGridViewNumColumns(view);
// if (view != null && (adapter = view.getAdapter()) != null && (adapterCount = adapter.getCount()) > 0
// && numColumns > 0) {
// int rowCount = (int)Math.ceil(adapterCount / (double)numColumns);
// height = rowCount * (height / adapterCount + getGridViewVerticalSpacing(view));
// }
// return height;
// }
//
// /**
// * get GridView columns number
// *
// * @param view
// * @return
// */
// public static int getGridViewNumColumns(GridView view) {
// if (view == null || view.getChildCount() <= 0) {
// return 0;
// }
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
// return getNumColumnsCompat11(view);
//
// } else {
// int columns = 0;
// int children = view.getChildCount();
// if (children > 0) {
// int width = view.getChildAt(0).getMeasuredWidth();
// if (width > 0) {
// columns = view.getWidth() / width;
// }
// }
// return columns;
// }
// }
//
// @TargetApi(11)
// private static int getNumColumnsCompat11(GridView view) {
// return view.getNumColumns();
// }
private static final String CLASS_NAME_GRID_VIEW = "android.widget.GridView";
private static final String FIELD_NAME_VERTICAL_SPACING = "mVerticalSpacing";
/**
* get GridView vertical spacing
*
* @param view
* @return
*/
public static int getGridViewVerticalSpacing(GridView view) {
// get mVerticalSpacing by android.widget.GridView
Class<?> demo = null;
int verticalSpacing = 0;
try {
demo = Class.forName(CLASS_NAME_GRID_VIEW);
Field field = demo.getDeclaredField(FIELD_NAME_VERTICAL_SPACING);
field.setAccessible(true);
verticalSpacing = (Integer)field.get(view);
return verticalSpacing;
} catch (Exception e) {
/**
* accept all exception, include ClassNotFoundException, NoSuchFieldException, InstantiationException,
* IllegalArgumentException, IllegalAccessException, NullPointException
*/
e.printStackTrace();
}
return verticalSpacing;
}
/**
* get AbsListView height according to every children
*
* @param view
* @return
*/
public static int getAbsListViewHeightBasedOnChildren(AbsListView view) {
ListAdapter adapter;
if (view == null || (adapter = view.getAdapter()) == null) {
return 0;
}
int height = 0;
for (int i = 0; i < adapter.getCount(); i++) {
View item = adapter.getView(i, null, view);
if (item instanceof ViewGroup) {
item.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
item.measure(0, 0);
height += item.getMeasuredHeight();
}
height += view.getPaddingTop() + view.getPaddingBottom();
return height;
}
/**
* set view height
*
* @param view
* @param height
*/
public static void setViewHeight(View view, int height) {
if (view == null) {
return;
}
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = height;
}
// /**
// * set GistView height which is calculated by {@link # getGridViewHeightBasedOnChildren(GridView)}
// *
// * @param view
// * @return
// */
// public static void setGridViewHeightBasedOnChildren(GridView view) {
// setViewHeight(view, getGridViewHeightBasedOnChildren(view));
// }
/**
* set ListView height which is calculated by {@link # getListViewHeightBasedOnChildren(ListView)}
*
* @param view
* @return
*/
public static void setListViewHeightBasedOnChildren(ListView view) {
setViewHeight(view, getListViewHeightBasedOnChildren(view));
}
/**
* set AbsListView height which is calculated by {@link # getAbsListViewHeightBasedOnChildren(AbsListView)}
*
* @param view
* @return
*/
public static void setAbsListViewHeightBasedOnChildren(AbsListView view) {
setViewHeight(view, getAbsListViewHeightBasedOnChildren(view));
}
/**
* set SearchView OnClickListener
*
* @param v
* @param listener
*/
public static void setSearchViewOnClickListener(View v, OnClickListener listener) {
if (v instanceof ViewGroup) {
ViewGroup group = (ViewGroup)v;
int count = group.getChildCount();
for (int i = 0; i < count; i++) {
View child = group.getChildAt(i);
if (child instanceof LinearLayout || child instanceof RelativeLayout) {
setSearchViewOnClickListener(child, listener);
}
if (child instanceof TextView) {
TextView text = (TextView)child;
text.setFocusable(false);
}
child.setOnClickListener(listener);
}
}
}
/**
* get descended views from parent.
*
* @param parent
* @param filter Type of views which will be returned.
* @param includeSubClass Whether returned list will include views which are subclass of filter or not.
* @return
*/
public static <T extends View> List<T> getDescendants(ViewGroup parent, Class<T> filter, boolean includeSubClass) {
List<T> descendedViewList = new ArrayList<T>();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
Class<? extends View> childsClass = child.getClass();
if ((includeSubClass && filter.isAssignableFrom(childsClass))
|| (!includeSubClass && childsClass == filter)) {
descendedViewList.add(filter.cast(child));
}
if (child instanceof ViewGroup) {
descendedViewList.addAll(getDescendants((ViewGroup)child, filter, includeSubClass));
}
}
return descendedViewList;
}
}