package com.cheng.utils.view;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
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 ViewUtil#getListViewHeightBasedOnChildren(ListView)}</li>
* <li>{@link ViewUtil#getAbsListViewHeightBasedOnChildren(AbsListView)}</li>
* </ul>
* <ul>
* <strong>set view height</strong>
* <li>{@link ViewUtil#setViewHeight(View, int)} set view height</li>
* <li>{@link ViewUtil#setListViewHeightBasedOnChildren(ListView)}</li>
* <li>{@link ViewUtil#setAbsListViewHeightBasedOnChildren(AbsListView)}</li>
* </ul>
* <ul>
* <strong>get other info</strong>
* <li>{@link ViewUtil#getGridViewVerticalSpacing(GridView)} get GridView
* vertical spacing</li>
* </ul>
* <ul>
* <strong>set other info</strong>
* <li>{@link ViewUtil#setSearchViewOnClickListener(View, OnClickListener)}</li>
* </ul>
*/
public final class ViewUtil {
/**
* Don't let anyone instantiate this class.
*/
private ViewUtil() {
throw new Error("Do not need instantiate!");
}
/**
* 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;
}
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;
}
/**
* get Font height
*
* @param view
* @return
*/
public static int getFontHeight(TextView view) {
Paint paint = new Paint();
paint.setTextSize(view.getTextSize());
FontMetrics fm = paint.getFontMetrics();
return (int) (Math.ceil(fm.descent - fm.ascent));
}
/**
* 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;
}
/**
* Helps determine if the app is running in a Tablet context.
*
* @param context
* @return
*/
public static boolean isTablet(Context context) {
return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}
}