package cn.mutils.app.ui;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.view.animation.TranslateAnimation;
import android.widget.ViewFlipper;
import java.util.ArrayList;
import java.util.List;
import cn.mutils.app.event.listener.OnActivityResultListener;
import cn.mutils.app.event.listener.OnSelectedChangeListener;
import cn.mutils.app.ui.core.ICachedViewManager;
import cn.mutils.app.ui.core.IFragmenter;
import cn.mutils.app.ui.core.IStateView;
import cn.mutils.app.ui.core.IStateViewManager;
import cn.mutils.app.ui.core.UICore;
import cn.mutils.app.util.AppUtil;
import cn.mutils.core.event.Dispatcher;
@SuppressWarnings({"unused", "SimplifiableIfStatement", "RedundantIfStatement"})
@SuppressLint("ClickableViewAccessibility")
public class FragmenterFlipper extends ViewFlipper implements IStateView, IStateViewManager, ICachedViewManager {
protected Handler mAnimHandler;
protected boolean mCreateDispatched;
protected List<View> mCachedViews = new ArrayList<View>();
protected Animation mAnimPushLeftIn;
protected Animation mAnimPushLeftOut;
protected Animation mAnimPushRightIn;
protected Animation mAnimPushRightOut;
protected AnimationListener mAnimPushListener;
protected boolean mAnimEnabled = true;
/**
* -1 for default,-2 for flipping
*/
protected int mSelectedIndex = -1;
protected int mTargetIndex = -1;
protected OnSelectedChangeListener mOnSelectedChangeListener;
protected boolean mGestureDetectorEnabled;
protected GestureDetector mGestureDetector;
protected int mMinDistance;
protected int mMinVelocity;
protected OnGestureListener mGestureDetectorOnGestureListener;
protected OnTouchListener mOnTouchListener;
protected IStateViewManager mManager;
protected Dispatcher mDispatcher = new Dispatcher();
public FragmenterFlipper(Context context) {
super(context);
}
public FragmenterFlipper(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setAnimationEnable(boolean enable) {
this.mAnimEnabled = enable;
if (mAnimEnabled) {
if (mAnimPushLeftIn == null) {
this.setAnimation(0, 0, 0, 0);
}
}
}
public void setAnimation(int pushLeftIn, int pushLeftOut, int pushRightIn, int pushRightOut) {
mAnimEnabled = true;
Context context = this.getContext();
if (pushLeftIn == 0) {
mAnimPushLeftIn = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
mAnimPushLeftIn.setDuration(300);
} else {
mAnimPushLeftIn = AnimationUtils.loadAnimation(context, pushLeftIn);
}
if (pushLeftOut == 0) {
mAnimPushLeftOut = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, -1,
Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
mAnimPushLeftOut.setDuration(300);
} else {
mAnimPushLeftOut = AnimationUtils.loadAnimation(context, pushLeftOut);
}
if (pushRightIn == 0) {
mAnimPushRightIn = new TranslateAnimation(Animation.RELATIVE_TO_SELF, -1, Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
mAnimPushRightIn.setDuration(300);
} else {
mAnimPushRightIn = AnimationUtils.loadAnimation(context, pushRightIn);
}
if (pushRightOut == 0) {
mAnimPushRightOut = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 1,
Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0);
mAnimPushRightOut.setDuration(300);
} else {
mAnimPushRightOut = AnimationUtils.loadAnimation(context, pushRightOut);
}
if (mAnimPushListener == null) {
mAnimPushListener = new AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
if (mAnimHandler == null) {
mAnimHandler = new Handler(Looper.getMainLooper());
}
mAnimHandler.post(new Runnable() {
@Override
public void run() {
postSelecting();
}
});
}
};
}
mAnimPushLeftIn.setAnimationListener(mAnimPushListener);
mAnimPushRightIn.setAnimationListener(mAnimPushListener);
}
public void setOnSelectedChangeListener(OnSelectedChangeListener listener) {
mOnSelectedChangeListener = listener;
}
@Override
public IStateView getSelectedView() {
if (mSelectedIndex >= 0 && mSelectedIndex < mCachedViews.size()) {
View v = mCachedViews.get(mSelectedIndex);
if (v instanceof IStateView) {
return (IStateView) v;
}
}
return null;
}
public int getSelectedIndex() {
return this.mSelectedIndex;
}
public void setSelectedIndex(int selectedIndex) {
if (!mCreateDispatched) {
this.onCreate();
}
if (selectedIndex < 0 || selectedIndex >= this.mCachedViews.size()) {
return;
}
if (selectedIndex == mSelectedIndex || selectedIndex == mTargetIndex) {
return;
}
// first time
if (mSelectedIndex == -1) {
setInAnimation(null);
setOutAnimation(null);
mSelectedIndex = selectedIndex;
View v = mCachedViews.get(mSelectedIndex);
afterSelectedFirstTime();
this.setDisplayedChild(this.indexOfChild(v));
return;
}
preSelecting(selectedIndex);
if (!mAnimEnabled) {
postSelecting();
}
}
protected void afterSelectedFirstTime() {
}
protected void afterSelected() {
View view = mCachedViews.get(mSelectedIndex);
setInAnimation(null);
setOutAnimation(null);
for (int i = this.getChildCount() - 1; i >= 0; i--) {
View childView = this.getChildAt(i);
if (childView.equals(view)) {
continue;
}
if (childView instanceof IFragmenter) {
IFragmenter fragment = (IFragmenter) childView;
fragment.setLocked(false);
fragment.setFragmentVisible(false);
}
}
}
protected void afterCreated() {
}
protected void preSelecting(int target) {
View view;
boolean pushLeft = false;
if (mTargetIndex >= 0) {
pushLeft = target > mTargetIndex;
view = mCachedViews.get(mTargetIndex);
if (view instanceof IStateView) {
if (view instanceof IFragmenter) {
((IFragmenter) view).setLocked(true);
}
((IStateView) view).onStop();
}
}
mTargetIndex = target;
if (mSelectedIndex >= 0) {
pushLeft = target > mSelectedIndex;
view = mCachedViews.get(mSelectedIndex);
if (view instanceof IStateView) {
if (view instanceof IFragmenter) {
((IFragmenter) view).setLocked(true);
}
((IStateView) view).onPause();
((IStateView) view).onStop();
}
mSelectedIndex = -2;
}
view = mCachedViews.get(mTargetIndex);
if (view instanceof IStateView) {
if (view instanceof IFragmenter) {
((IFragmenter) view).setLocked(false);
}
((IStateView) view).onStart();
}
if (this.indexOfChild(view) < 0) {
setInAnimation(null);
setOutAnimation(null);
this.addView(view);
}
if (mAnimEnabled) {
if (pushLeft) {
setInAnimation(mAnimPushLeftIn);
setOutAnimation(mAnimPushLeftOut);
} else {
setInAnimation(mAnimPushRightIn);
setOutAnimation(mAnimPushRightOut);
}
} else {
setInAnimation(null);
setOutAnimation(null);
}
setDisplayedChild(this.indexOfChild(view));
}
protected void postSelecting() {
if (mTargetIndex < 0) {// onPause->onAnimationEnd
return;
}
View view = mCachedViews.get(mTargetIndex);
if (view instanceof IStateView) {
if (view instanceof IFragmenter) {
((IFragmenter) view).setLocked(false);
}
((IStateView) view).onResume();
}
mSelectedIndex = mTargetIndex;
afterSelected();
if (mOnSelectedChangeListener != null) {
mOnSelectedChangeListener.onChanged(this, mSelectedIndex);
}
mTargetIndex = -1;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
for (int i = 0, size = this.getChildCount(); i < size; i++) {
View v = this.getChildAt(i);
mCachedViews.add(v);
if (v instanceof IStateView) {
this.bind((IStateView) v);
}
}
}
public void setGestureDetectorEnabled(boolean v) {
mGestureDetectorEnabled = v;
if (mGestureDetectorEnabled) {
Context context = this.getContext();
mMinDistance = (int) AppUtil.getRawSize(context, TypedValue.COMPLEX_UNIT_DIP, 64);
mMinVelocity = (int) AppUtil.getRawSize(context, TypedValue.COMPLEX_UNIT_DIP, 16);
}
}
@Override
public void onCreate() {
if (mCreateDispatched) {
return;
}
mCreateDispatched = true;
if (mAnimEnabled) {
if (mAnimPushLeftIn == null) {
this.setAnimation(0, 0, 0, 0);
}
}
if (mGestureDetectorEnabled) {
if (mGestureDetectorOnGestureListener == null) {
mGestureDetectorOnGestureListener = new OnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (Math.abs(e1.getY() - e2.getY()) > mMinDistance) {
return false;
}
if (e1.getX() - e2.getX() > mMinDistance && Math.abs(velocityX) > mMinVelocity) {
setSelectedIndex(mSelectedIndex + 1);
} else if (e2.getX() - e1.getX() > mMinDistance && Math.abs(velocityX) > mMinVelocity) {
setSelectedIndex(mSelectedIndex - 1);
} else {
return false;
}
return true;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
};
}
mGestureDetector = new GestureDetector(getContext(), mGestureDetectorOnGestureListener);
if (mOnTouchListener == null) {
mOnTouchListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mGestureDetectorEnabled && !onInterceptGesture()) {
return mGestureDetector.onTouchEvent(event);
}
return false;
}
};
}
this.setOnTouchListener(mOnTouchListener);
}
for (View v : mCachedViews) {
if (v instanceof IStateView) {
UICore.dispatchCreate((IStateView) v);
}
}
afterCreated();
}
@Override
public void onStart() {
UICore.dispatchStart(this);
}
@Override
public void onResume() {
UICore.dispatchResume(this);
}
@Override
public void onPause() {
UICore.dispatchPause(this);
}
@Override
public void onStop() {
UICore.dispatchStop(this);
}
@Override
public void onDestroy() {
for (View v : mCachedViews) {
if (v instanceof IStateView) {
((IStateView) v).onDestroy();
}
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (mGestureDetectorEnabled && !onInterceptGesture()) {
return mGestureDetector.onTouchEvent(ev) && super.onInterceptTouchEvent(ev);
}
return super.onInterceptTouchEvent(ev);
}
public OnTouchListener getGestureListener() {
return mOnTouchListener;
}
@Override
public boolean onInterceptBackPressed() {
if (UICore.interceptBackPressed(this)) {
return true;
}
return false;
}
public boolean onInterceptGesture() {
IStateView view = getSelectedView();
if (view == null) {
return true;
}
if (view instanceof StateView) {
return ((StateView) view).onInterceptGesture();
} else {
return false;
}
}
@Override
public void startActivity(Intent intent) {
UICore.startActivity(this, intent);
}
@Override
public void startActivityForResult(Intent intent, int requestCode) {
UICore.startActivityForResult(this, intent, requestCode);
}
@Override
public void onActivityResult(Context context, int requestCode, int resultCode, Intent data) {
UICore.onActivityResult(this, requestCode, resultCode, data);
}
@Override
public IStateViewManager getManager() {
return mManager;
}
@Override
public void setManager(IStateViewManager manager) {
mManager = manager;
}
@Override
public void bind(IStateView stateView) {
stateView.setManager(this);
}
@Override
public void notify(Object message) {
if (mManager != null) {
mManager.notify(message);
}
}
@Override
public <T extends View> T findViewById(int id, Class<T> viewClass) {
return UICore.findViewById(this, id, viewClass);
}
@Override
public List<IStateView> getBindStateViews() {
return null;
}
@Override
public boolean redirectToSelectedView() {
return true;
}
@Override
public boolean isCreateDispatched() {
return mCreateDispatched;
}
@Override
public void setCreateDispatched(boolean dispatched) {
mCreateDispatched = dispatched;
}
@Override
public List<OnActivityResultListener> getOnActivityResultListeners() {
return mDispatcher.getListeners(OnActivityResultListener.EVENT_TYPE, OnActivityResultListener.class);
}
@Override
public void addOnActivityResultListener(OnActivityResultListener listener) {
mDispatcher.addListener(OnActivityResultListener.EVENT_TYPE, listener);
}
@Override
public void removeOnActivityResultListener(OnActivityResultListener listener) {
mDispatcher.removeListener(OnActivityResultListener.EVENT_TYPE, listener);
}
@Override
public List<View> getCachedViews() {
return mCachedViews;
}
}