Espiandev/FlyInMenu — pull request #3 by metacons (2013-04-29 13:51:15+00:00)
Title: Compatibility backward

package com.espian.flyin.library;

import java.util.ArrayList;

import org.xmlpull.v1.XmlPullParser;

import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SearchView;
import android.widget.TextView;

import com.koctas.main.R;

public class FlyInMenu extends LinearLayout {

public static final int FLY_IN_WITH_ACTIVITY = 0;
public static final int FLY_IN_OVER_ACTIVITY = 1;

private ListView mListView;
private View mOutsideView;
private LinearLayout mMenuHolder;
private ViewStub mCustomStub;
private View mCustomView;
private View mWrappedSearchView;
private boolean hasSearchView = false;
private int flyType;
private int animStartFlyType;
private Activity mAct;

private OnFlyInItemClickListener callback;

private static ArrayList menuItems;

public FlyInMenu(Context context) {
super(context);
mAct = (Activity) context;
load();
}

public FlyInMenu(Context context, AttributeSet attrs) {
super(context, attrs);
mAct = (Activity) context;
load();
}

public void setType(int type) {
flyType = type;
}

private void load() {

if (isInEditMode())
return;

inflateLayout();

initUi();

}

private void inflateLayout() {

try {
LayoutInflater.from(getContext()).inflate(R.layout.fly_menu, this,
true);
} catch (Exception e) {

}

}

private void initUi() {

mListView = (ListView) findViewById(R.id.fly_listview);
mOutsideView = findViewById(R.id.fly_outside);
mCustomStub = (ViewStub) findViewById(R.id.fly_custom);
mMenuHolder = (LinearLayout) findViewById(R.id.fly_menu_holder);

mOutsideView.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
hideMenu();

}
});

mListView.setOnItemClickListener(new OnItemClickListener() {

@Override
public void onItemClick(AdapterView parent, View view,
int position, long id) {

boolean hide = true;
if (callback != null) {
hide = callback.onFlyInItemClick(menuItems.get(position),
position);
}

if (hide)
hideMenu();
}

});

}

public void setOnFlyInItemClickListener(OnFlyInItemClickListener callback) {
this.callback = callback;
}

/**
* Enabled the SearchView at the top of the Fly-in menu, providing the SDK
* is API level 11 (Honeycomb) or above. The SearchView can be accessed with
* {@link #getSearchView()}.
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public void enableSearchView() {
if (Build.VERSION.SDK_INT >= 11) {
SearchView s = new SearchView(getContext());
s.setIconifiedByDefault(false);
s.setSubmitButtonEnabled(true);
(mWrappedSearchView = s).setId(R.id.fly_searchview);
mMenuHolder.removeView(findViewById(R.id.fly_searchstub));
mMenuHolder.addView(mWrappedSearchView, 0);
hasSearchView = true;
}
}

/**
* Fetches the SearchView associated with the Fly-in menu. Note that calling
* this on an API level pre-11 (Honeycomb) will crash, so your logic must
* include a check on the API level if you target such platforms. The
* SearchView must first be initialised using {@link #enableSearchView}.
*
* @return the SearchView instance, or null if it hasn't been initialised
*/
public SearchView getSearchView() {
if (!hasSearchView)
return null;
return (SearchView) mWrappedSearchView;
}

/**
* Fetch the custom view at the bottom of the fly-in menu.
*
* @return the custom view, or null
*/
public View getCustomView() {
return mCustomView;
}

/**
* Set the custom view at the bottom of the fly-in menu, from a resource
*
* @param rid
* layout resource id of the view to inflate
*/
public void setCustomView(int rid) {
mCustomStub.setLayoutResource(rid);
mCustomView = mCustomStub.inflate();
mCustomView.setVisibility(isMenuVisible() ? View.VISIBLE : View.GONE);
requestLayout();
}

/**
* Set the custom view at the bottom of the fly-in menu
*
* @param view
* the view to set
*/
public void setCustomView(View view) {
mMenuHolder.removeView(mCustomStub);
mMenuHolder.addView(mCustomView = view);
mCustomView.setVisibility(isMenuVisible() ? View.VISIBLE : View.GONE);
requestLayout();
}

/**
* Set the menu items associated with the fly-in menu
*
* @param menu
* resource id of the menu to be inflated
*/
public void setMenuItems(int menu) {
setMenuItems(menu, -1);
}

public void setMenuItems(int menu, int resourceId) {

parseXml(menu);
if (menuItems != null && menuItems.size() > 0) {
mListView.setAdapter(new Adapter());

}

}

/**
* Sets the background of the fly-in menu
*/
public void setBackgroundResource(int resource) {
mMenuHolder.setBackgroundResource(resource);
}

private int getInteger(int id) {
return getResources().getInteger(id);
}

@TargetApi(11)
public void showMenu() {

if (flyType > 1)
flyType = 0;
mOutsideView.setVisibility(View.VISIBLE);
mMenuHolder.setVisibility(View.VISIBLE);
if (mCustomView != null) {
mCustomView.setVisibility(View.VISIBLE);
}

ViewGroup decorView = (ViewGroup) mAct.getWindow().getDecorView();
View v, x;
v = decorView.getChildAt(0);
x = decorView.getChildAt(1);

Interpolator decel = AnimationUtils.loadInterpolator(getContext(),
android.R.anim.decelerate_interpolator);
if (android.os.Build.VERSION.SDK_INT > 10) {

ObjectAnimator flyIn = ObjectAnimator
.ofFloat(x, "translationX",
getResources().getDimension(R.dimen.rbm_menu_width)
* -1, 0);
ObjectAnimator activity = ObjectAnimator.ofFloat(v, "translationX",
0, getResources().getDimension(R.dimen.rbm_menu_width));
flyIn.setInterpolator(decel);
activity.setInterpolator(decel);

animStartFlyType = flyType;
if (flyType == FLY_IN_WITH_ACTIVITY) {

AnimatorSet showFlyIn = new AnimatorSet();
showFlyIn.playTogether(flyIn, activity);
showFlyIn.setDuration(300).start();

} else {

flyIn.setInterpolator(decel);
flyIn.setDuration(300).start();

}
} else {
com.nineoldandroids.animation.ObjectAnimator flyIn = com.nineoldandroids.animation.ObjectAnimator
.ofFloat(x, "translationX",
getResources().getDimension(R.dimen.rbm_menu_width)
* -1, 0);

com.nineoldandroids.animation.ObjectAnimator activity = com.nineoldandroids.animation.ObjectAnimator.ofFloat(v, "translationX",
0, getResources().getDimension(R.dimen.rbm_menu_width));
flyIn.setInterpolator(decel);
activity.setInterpolator(decel);
animStartFlyType = flyType;
if (flyType == FLY_IN_WITH_ACTIVITY) {

com.nineoldandroids.animation.AnimatorSet showFlyIn = new com.nineoldandroids.animation.AnimatorSet();

showFlyIn.playTogether( com.nineoldandroids.animation.ObjectAnimator.ofFloat(x, "translationX",
getResources().getDimension(R.dimen.rbm_menu_width)
* -1, 0), com.nineoldandroids.animation.ObjectAnimator.ofFloat(v, "translationX",
0, getResources().getDimension(R.dimen.rbm_menu_width)));

showFlyIn.setDuration(300).start();

} else {

flyIn.setInterpolator(decel);
flyIn.setDuration(300).start();

}
}
}

@TargetApi(11)
public void hideMenu() {

ViewGroup decorView = (ViewGroup) mAct.getWindow().getDecorView();
View v, x;
v = decorView.getChildAt(0);
x = decorView.getChildAt(1);

Interpolator decel = AnimationUtils.loadInterpolator(getContext(),
android.R.anim.decelerate_interpolator);
if (android.os.Build.VERSION.SDK_INT > 10) {
ObjectAnimator flyIn = ObjectAnimator.ofFloat(x, "translationX", 0,
getResources().getDimension(R.dimen.rbm_menu_width) * -1);
ObjectAnimator activity = ObjectAnimator.ofFloat(v, "translationX",
getResources().getDimension(R.dimen.rbm_menu_width), 0);
flyIn.setInterpolator(decel);
activity.setInterpolator(decel);

if (animStartFlyType == FLY_IN_WITH_ACTIVITY) {

AnimatorSet showFlyIn = new AnimatorSet();
showFlyIn.playTogether(flyIn, activity);
showFlyIn.addListener(new VisibilityHelper());
showFlyIn.setDuration(300).start();

} else {

flyIn.setInterpolator(decel);
flyIn.addListener(new VisibilityHelper());
flyIn.setDuration(300).start();

}
}else {
com.nineoldandroids.animation.ObjectAnimator flyIn = com.nineoldandroids.animation.ObjectAnimator
.ofFloat(x, "translationX", 0,
getResources().getDimension(R.dimen.rbm_menu_width) * -1);

com.nineoldandroids.animation.ObjectAnimator activity = com.nineoldandroids.animation.ObjectAnimator.ofFloat(v, "translationX",
getResources().getDimension(R.dimen.rbm_menu_width), 0);
flyIn.setInterpolator(decel);
activity.setInterpolator(decel);
//	animStartFlyType = flyType;
if (flyType == FLY_IN_WITH_ACTIVITY) {

com.nineoldandroids.animation.AnimatorSet showFlyIn = new com.nineoldandroids.animation.AnimatorSet();

showFlyIn.playTogether( com.nineoldandroids.animation.ObjectAnimator.ofFloat(x, "translationX", 0,
getResources().getDimension(R.dimen.rbm_menu_width) * -1), com.nineoldandroids.animation.ObjectAnimator.ofFloat(v, "translationX",
getResources().getDimension(R.dimen.rbm_menu_width), 0));

showFlyIn.addListener(visibilityCompatibilty);
showFlyIn.setDuration(300).start();

} else {

flyIn.setInterpolator(decel);
flyIn.addListener(visibilityCompatibilty);
flyIn.setDuration(300).start();

}
}

}

com.nineoldandroids.animation.Animator.AnimatorListener visibilityCompatibilty = new com.nineoldandroids.animation.Animator.AnimatorListener() {

@Override
public void onAnimationStart(
com.nineoldandroids.animation.Animator animation) {

}

@Override
public void onAnimationRepeat(
com.nineoldandroids.animation.Animator animation) {

}

@Override
public void onAnimationEnd(com.nineoldandroids.animation.Animator animation) {
mOutsideView.setVisibility(View.GONE);
mMenuHolder.setVisibility(View.GONE);
if (mCustomView != null) {
mCustomView.setVisibility(View.GONE);
}
}

@Override
public void onAnimationCancel(
com.nineoldandroids.animation.Animator animation) {

}
};

/**
* Toggle the menu visibility: show it if it is hidden, and hide if it is
* shown.
*/
public void toggleMenu() {

if (mOutsideView.getVisibility() == View.GONE) {
showMenu();
} else {
hideMenu();
}
}

private void parseXml(int menu) {

menuItems = new ArrayList();

try {
XmlResourceParser xpp = getResources().getXml(menu);

xpp.next();
int eventType = xpp.getEventType();

while (eventType != XmlPullParser.END_DOCUMENT) {

if (eventType == XmlPullParser.START_TAG) {

String elemName = xpp.getName();

if (elemName.equals("item")) {

String textId = xpp.getAttributeValue(
"http://schemas.android.com/apk/res/android",
"title");
String iconId = xpp.getAttributeValue(
"http://schemas.android.com/apk/res/android",
"icon");
String resId = xpp.getAttributeValue(
"http://schemas.android.com/apk/res/android",
"id");
String enabled = xpp.getAttributeValue(
"http://schemas.android.com/apk/res/android",
"enabled");

FlyInMenuItem item = new FlyInMenuItem();
item.setItemId(Integer.valueOf(resId.replace("@", "")));
item.setTitle(resourceIdToString(textId));
item.setIcon(Integer.valueOf(iconId.replace("@", "")));
// item.setEnabled(Boolean.parseBoolean(enabled));

menuItems.add(item);

}

}

eventType = xpp.next();

}

} catch (Exception e) {
e.printStackTrace();
}

}

private String resourceIdToString(String text) {

if (!text.contains("@")) {
return text;
} else {

String id = text.replace("@", "");
int rid = Integer.valueOf(id);
return getResources().getString(rid);

}

}

public boolean isMenuVisible() {
return mOutsideView.getVisibility() == View.VISIBLE;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
SavedState ss = (SavedState) state;
super.onRestoreInstanceState(ss.getSuperState());

if (ss.bShowMenu)
showMenu();
else
hideMenu();
}

@Override
protected Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);

ss.bShowMenu = isMenuVisible();

return ss;
}

static class SavedState extends BaseSavedState {
boolean bShowMenu;

SavedState(Parcelable superState) {
super(superState);
}

private SavedState(Parcel in) {
super(in);
bShowMenu = (in.readInt() == 1);
}

@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(bShowMenu ? 1 : 0);
}

public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}

public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}

private class Adapter extends BaseAdapter {

private LayoutInflater inflater;

public Adapter() {
inflater = LayoutInflater.from(getContext());
}

@Override
public int getCount() {

return menuItems.size();
}

@Override
public Object getItem(int position) {

return null;
}

@Override
public long getItemId(int position) {

return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

if (convertView == null || convertView instanceof TextView)
convertView = inflater.inflate(R.layout.fly_item, null);

ImageView icon = (ImageView) convertView
.findViewById(R.id.rbm_item_icon);
TextView text = (TextView) convertView
.findViewById(R.id.rbm_item_text);
FlyInMenuItem item = menuItems.get(position);
text.setText(item.getTitle());
icon.setImageResource(item.getIconId());
convertView.setEnabled(item.isEnabled());

return convertView;

}

}

public class VisibilityHelper implements AnimatorListener {

@Override
public void onAnimationStart(Animator animation) {
}

@Override
public void onAnimationEnd(Animator animation) {

mOutsideView.setVisibility(View.GONE);
mMenuHolder.setVisibility(View.GONE);
if (mCustomView != null) {
mCustomView.setVisibility(View.GONE);
}
}

@Override
public void onAnimationCancel(Animator animation) {
}

@Override
public void onAnimationRepeat(Animator animation) {
}

}

}