Compare commits

..

3 Commits

Author SHA1 Message Date
Eric Kuck 62a5a81107 Fixed typo 2016-04-12 14:33:03 -05:00
Eric Kuck d234dd4c75 Added external onActivityResult method to Controllers (for use with things like the Facebook SDK)
Removed CircularRevealChangeHandler from the core project
2016-04-12 14:18:01 -05:00
Eric Kuck a48b49cdbe All demos should now run on API < 21 2016-04-06 12:07:51 -05:00
12 changed files with 181 additions and 70 deletions
+3 -3
View File
@@ -20,14 +20,14 @@ Conductor is architecture-agnostic and does not try to force any design decision
## Installation
```gradle
compile 'com.bluelinelabs:conductor:1.1.2'
compile 'com.bluelinelabs:conductor:1.1.3'
// If you want the components that go along with
// Android's support libraries (currently just a PagerAdapter):
compile 'com.bluelinelabs:conductor-support:1.1.2'
compile 'com.bluelinelabs:conductor-support:1.1.3'
// If you want RxJava/RxAndroid lifecycle support:
compile 'com.bluelinelabs:conductor-rxlifecycle:1.1.2'
compile 'com.bluelinelabs:conductor-rxlifecycle:1.1.3'
```
## Components to Know
+1 -1
View File
@@ -3,7 +3,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
classpath 'com.android.tools.build:gradle:2.0.0'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
}
}
@@ -21,6 +21,7 @@ import android.view.ViewGroup;
import com.bluelinelabs.conductor.ControllerTransaction.ControllerChangeType;
import com.bluelinelabs.conductor.changehandler.SimpleSwapChangeHandler;
import com.bluelinelabs.conductor.internal.ClassUtils;
import com.bluelinelabs.conductor.internal.RouterRequiringFunc;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
@@ -71,6 +72,7 @@ public abstract class Controller {
private final List<ChildControllerTransaction> mChildControllers = new ArrayList<>();
private final List<LifecycleListener> mLifecycleListeners = new ArrayList<>();
private final ArrayList<String> mRequestedPermissions = new ArrayList<>();
private final ArrayList<RouterRequiringFunc> mOnRouterSetListeners = new ArrayList<>();
static Controller newInstance(Bundle bundle) {
final String className = bundle.getString(KEY_CLASS_NAME);
@@ -400,22 +402,40 @@ public abstract class Controller {
/**
* Calls startActivity(Intent) from this Controller's host Activity.
*/
public final void startActivity(Intent intent) {
getRouter().getLifecycleHandler().startActivity(intent);
public final void startActivity(final Intent intent) {
executeWithRouter(new RouterRequiringFunc() {
@Override public void execute() { mRouter.getLifecycleHandler().startActivity(intent); }
});
}
/**
* Calls startActivityForResult(Intent, int) from this Controller's host Activity.
*/
public final void startActivityForResult(Intent intent, int requestCode) {
getRouter().getLifecycleHandler().startActivityForResult(mInstanceId, intent, requestCode);
public final void startActivityForResult(final Intent intent, final int requestCode) {
executeWithRouter(new RouterRequiringFunc() {
@Override public void execute() { mRouter.getLifecycleHandler().startActivityForResult(mInstanceId, intent, requestCode); }
});
}
/**
* Calls startActivityForResult(Intent, int, Bundle) from this Controller's host Activity.
*/
public final void startActivityForResult(Intent intent, int requestCode, Bundle options) {
getRouter().getLifecycleHandler().startActivityForResult(mInstanceId, intent, requestCode, options);
public final void startActivityForResult(final Intent intent, final int requestCode, final Bundle options) {
executeWithRouter(new RouterRequiringFunc() {
@Override public void execute() { mRouter.getLifecycleHandler().startActivityForResult(mInstanceId, intent, requestCode, options); }
});
}
/**
* Registers this Controller to handle onActivityResult responses. Calling this method is NOT
* necessary when calling {@link #startActivityForResult(Intent, int)}
*
* @param requestCode The request code being registered for.
*/
public final void registerForActivityResult(final int requestCode) {
executeWithRouter(new RouterRequiringFunc() {
@Override public void execute() { mRouter.getLifecycleHandler().registerForActivityRequest(mInstanceId, requestCode); }
});
}
/**
@@ -434,9 +454,12 @@ public abstract class Controller {
* {@link #onRequestPermissionsResult(int, String[], int[])} will be forwarded back to this Controller by the system.
*/
@TargetApi(Build.VERSION_CODES.M)
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
public final void requestPermissions(@NonNull final String[] permissions, final int requestCode) {
mRequestedPermissions.addAll(Arrays.asList(permissions));
getRouter().getLifecycleHandler().requestPermissions(mInstanceId, permissions, requestCode);
executeWithRouter(new RouterRequiringFunc() {
@Override public void execute() { mRouter.getLifecycleHandler().requestPermissions(mInstanceId, permissions, requestCode); }
});
}
/**
@@ -625,11 +648,24 @@ public abstract class Controller {
final void setRouter(@NonNull Router router) {
mRouter = router;
for (RouterRequiringFunc listener : mOnRouterSetListeners) {
listener.execute();
}
mOnRouterSetListeners.clear();
for (ChildControllerTransaction child : mChildControllers) {
child.controller.setRouter(router);
}
}
final void executeWithRouter(@NonNull RouterRequiringFunc listener) {
if (mRouter != null) {
listener.execute();
} else {
mOnRouterSetListeners.add(listener);
}
}
private void addChildController(ChildControllerTransaction transaction, ControllerChangeHandler pushChangeHandler) {
if (transaction.controller.mParentController == null) {
transaction.controller.setRouter(mRouter);
@@ -825,6 +861,10 @@ public abstract class Controller {
mDestroyed = true;
if (mRouter != null) {
mRouter.getLifecycleHandler().unregisterForActivityRequests(mInstanceId);
}
onDestroy();
for (LifecycleListener lifecycleListener : mLifecycleListeners) {
@@ -41,19 +41,15 @@ public class Router {
}
/**
* This should be called by the host Activity when its onActivityResult method is called. The call will be forwarded
* to the {@link Controller} with the instanceId passed in.
* This should be called by the host Activity when its onActivityResult method is called if the instanceId
* of the controller that called startActivityForResult is not known.
*
* @param instanceId The instanceId of the Controller to which this result should be forwarded
* @param requestCode The Activity's onActivityResult requestCode
* @param resultCode The Activity's onActivityResult resultCode
* @param data The Activity's onActivityResult data
*/
public void onActivityResult(String instanceId, int requestCode, int resultCode, Intent data) {
Controller controller = getControllerWithInstanceId(instanceId);
if (controller != null) {
controller.onActivityResult(requestCode, resultCode, data);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
getLifecycleHandler().onActivityResult(requestCode, resultCode, data);
}
/**
@@ -350,6 +346,13 @@ public class Router {
}
}
public final void onActivityResult(String instanceId, int requestCode, int resultCode, Intent data) {
Controller controller = getControllerWithInstanceId(instanceId);
if (controller != null) {
controller.onActivityResult(requestCode, resultCode, data);
}
}
public final void onActivityStarted(Activity activity) {
for (RouterTransaction transaction : mBackStack) {
transaction.controller.activityStarted(activity);
@@ -188,13 +188,25 @@ public class LifecycleHandler extends Fragment implements ActivityLifecycleCallb
return super.onOptionsItemSelected(item);
}
public void startActivityForResult(String instanceId, Intent intent, int requestCode) {
public void registerForActivityRequest(String instanceId, int requestCode) {
mActivityRequestMap.put(requestCode, instanceId);
}
public void unregisterForActivityRequests(String instanceId) {
for (int i = mActivityRequestMap.size() - 1; i >= 0; i--) {
if (instanceId.equals(mActivityRequestMap.get(mActivityRequestMap.keyAt(i)))) {
mActivityRequestMap.removeAt(i);
}
}
}
public void startActivityForResult(String instanceId, Intent intent, int requestCode) {
registerForActivityRequest(instanceId, requestCode);
startActivityForResult(intent, requestCode);
}
public void startActivityForResult(String instanceId, Intent intent, int requestCode, Bundle options) {
mActivityRequestMap.put(requestCode, instanceId);
registerForActivityRequest(instanceId, requestCode);
startActivityForResult(intent, requestCode, options);
}
@@ -0,0 +1,5 @@
package com.bluelinelabs.conductor.internal;
public interface RouterRequiringFunc {
void execute();
}
@@ -1,4 +1,4 @@
package com.bluelinelabs.conductor.changehandler;
package com.bluelinelabs.conductor.demo.changehandler;
import android.animation.Animator;
import android.annotation.TargetApi;
@@ -9,6 +9,8 @@ import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import com.bluelinelabs.conductor.changehandler.AnimatorChangeHandler;
/**
* An {@link AnimatorChangeHandler} that will perform a circular reveal
*/
@@ -0,0 +1,36 @@
package com.bluelinelabs.conductor.demo.changehandler;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.os.Build;
import android.support.annotation.NonNull;
import android.view.View;
import android.view.ViewGroup;
public class CircularRevealChangeHandlerCompat extends CircularRevealChangeHandler {
public CircularRevealChangeHandlerCompat() { }
public CircularRevealChangeHandlerCompat(@NonNull View fromView, @NonNull View containerView) {
super(fromView, containerView);
}
@Override
protected Animator getAnimator(@NonNull ViewGroup container, View from, View to, boolean isPush, boolean toAddedToContainer) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return super.getAnimator(container, from, to, isPush, toAddedToContainer);
} else {
AnimatorSet animator = new AnimatorSet();
if (to != null && toAddedToContainer) {
animator.play(ObjectAnimator.ofFloat(to, View.ALPHA, 0, 1));
}
if (from != null) {
animator.play(ObjectAnimator.ofFloat(from, View.ALPHA, 0));
}
return animator;
}
}
}
@@ -15,12 +15,12 @@ import android.widget.TextView;
import com.bluelinelabs.conductor.Controller;
import com.bluelinelabs.conductor.ControllerChangeHandler;
import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.CircularRevealChangeHandler;
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler;
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler;
import com.bluelinelabs.conductor.demo.R;
import com.bluelinelabs.conductor.demo.changehandler.ArcFadeMoveChangeHandlerCompat;
import com.bluelinelabs.conductor.demo.changehandler.CircularRevealChangeHandlerCompat;
import com.bluelinelabs.conductor.demo.changehandler.FlipChangeHandler;
import com.bluelinelabs.conductor.demo.controllers.base.BaseController;
import com.bluelinelabs.conductor.demo.util.BundleBuilder;
@@ -35,7 +35,7 @@ public class TransitionDemoController extends BaseController {
public enum TransitionDemo {
VERTICAL("Vertical Slide Animation", R.layout.controller_transition_demo, R.color.blue_grey_300),
CIRCULAR("Circular Reveal Animation", R.layout.controller_transition_demo, R.color.red_300),
CIRCULAR("Circular Reveal Animation (on Lollipop and above, else Fade)", R.layout.controller_transition_demo, R.color.red_300),
FADE("Fade Animation", R.layout.controller_transition_demo, R.color.blue_300),
FLIP("Flip Animation", R.layout.controller_transition_demo, R.color.deep_orange_300),
HORIZONTAL("Horizontal Slide Animation", R.layout.controller_transition_demo, R.color.green_300),
@@ -122,7 +122,7 @@ public class TransitionDemoController extends BaseController {
return new VerticalChangeHandler();
case CIRCULAR:
TransitionDemoController demoController = (TransitionDemoController)from;
return new CircularRevealChangeHandler(demoController.mBtnNext, demoController.mContainerView);
return new CircularRevealChangeHandlerCompat(demoController.mBtnNext, demoController.mContainerView);
case FADE:
return new FadeChangeHandler();
case FLIP:
@@ -16,13 +16,12 @@
package com.bluelinelabs.conductor.demo.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build.VERSION_CODES;
import android.support.v4.view.NestedScrollingParent;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import java.util.ArrayList;
@@ -33,8 +32,30 @@ import java.util.List;
* Applies an elasticity factor to reduce movement as you approach the given dismiss distance.
* Optionally also scales down content during drag.
*/
@TargetApi(VERSION_CODES.LOLLIPOP)
public class ElasticDragDismissFrameLayout extends FrameLayout {
public class ElasticDragDismissFrameLayout extends FrameLayout implements NestedScrollingParent {
public static abstract class ElasticDragDismissCallback {
/**
* Called for each drag event.
*
* @param elasticOffset Indicating the drag offset with elasticity applied i.e. may
* exceed 1.
* @param elasticOffsetPixels The elastically scaled drag distance in pixels.
* @param rawOffset Value from [0, 1] indicating the raw drag offset i.e.
* without elasticity applied. A value of 1 indicates that the
* dismiss distance has been reached.
* @param rawOffsetPixels The raw distance the user has dragged
*/
public void onDrag(float elasticOffset, float elasticOffsetPixels,
float rawOffset, float rawOffsetPixels) { }
/**
* Called when dragging is released and has exceeded the threshold dismiss distance.
*/
public void onDragDismissed() { }
}
// configurable attribs
private float dragDismissDistance = Float.MAX_VALUE;
@@ -51,21 +72,16 @@ public class ElasticDragDismissFrameLayout extends FrameLayout {
private List<ElasticDragDismissCallback> callbacks;
public ElasticDragDismissFrameLayout(Context context) {
this(context, null, 0, 0);
this(context, null, 0);
}
public ElasticDragDismissFrameLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0, 0);
this(context, attrs, 0);
}
public ElasticDragDismissFrameLayout(Context context, AttributeSet attrs,
int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public ElasticDragDismissFrameLayout(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
super(context, attrs, defStyleAttr);
dragDismissDistance = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics());
dragDismissFraction = 0.7f;
@@ -73,29 +89,6 @@ public class ElasticDragDismissFrameLayout extends FrameLayout {
shouldScale = true;
}
public static abstract class ElasticDragDismissCallback {
/**
* Called for each drag event.
*
* @param elasticOffset Indicating the drag offset with elasticity applied i.e. may
* exceed 1.
* @param elasticOffsetPixels The elastically scaled drag distance in pixels.
* @param rawOffset Value from [0, 1] indicating the raw drag offset i.e.
* without elasticity applied. A value of 1 indicates that the
* dismiss distance has been reached.
* @param rawOffsetPixels The raw distance the user has dragged
*/
public void onDrag(float elasticOffset, float elasticOffsetPixels,
float rawOffset, float rawOffsetPixels) { }
/**
* Called when dragging is released and has exceeded the threshold dismiss distance.
*/
public void onDragDismissed() { }
}
@Override
public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
return (nestedScrollAxes & View.SCROLL_AXIS_VERTICAL) != 0;
@@ -126,7 +119,7 @@ public class ElasticDragDismissFrameLayout extends FrameLayout {
.scaleX(1f)
.scaleY(1f)
.setDuration(200L)
.setInterpolator(AnimationUtils.loadInterpolator(getContext(), android.R.interpolator.fast_out_slow_in))
.setInterpolator(new FastOutSlowInInterpolator())
.setListener(null)
.start();
totalDrag = 0;
@@ -135,6 +128,24 @@ public class ElasticDragDismissFrameLayout extends FrameLayout {
}
}
@Override
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
return false;
}
@Override
public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
return false;
}
@Override
public int getNestedScrollAxes() {
return 0;
}
@Override
public void onNestedScrollAccepted(View child, View target, int axes) { }
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
@@ -171,6 +182,9 @@ public class ElasticDragDismissFrameLayout extends FrameLayout {
draggingUp = true;
if (shouldScale) setPivotY(0f);
}
setPivotX(getWidth() / 2);
// how far have we dragged relative to the distance to perform a dismiss
// (01 where 1 = dismiss distance). Decreasing logarithmically as we approach the limit
float dragFraction = (float) Math.log10(1 + (Math.abs(totalDrag) / dragDismissDistance));
@@ -19,12 +19,11 @@
android:text="@string/drag_to_dismiss"
/>
<ScrollView
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:fillViewport="true"
android:nestedScrollingEnabled="true"
android:overScrollFooter="@android:color/transparent"
android:overScrollMode="never" >
@@ -36,7 +35,7 @@
android:padding="16dp"
/>
</ScrollView>
</android.support.v4.widget.NestedScrollView>
</LinearLayout>
</com.bluelinelabs.conductor.demo.widget.ElasticDragDismissFrameLayout>
+4 -4
View File
@@ -5,8 +5,8 @@ ext {
buildToolsVersion = '23.0.2'
versionCode = 1
versionName = '1.1.2'
publishedVersionName = '1.1.2'
versionName = '1.1.3'
publishedVersionName = '1.1.3'
supportV4 = 'com.android.support:support-v4:23.1.1'
supportDesign = 'com.android.support:design:23.1.1'
@@ -15,8 +15,8 @@ ext {
butterknife = 'com.jakewharton:butterknife:7.0.1'
leakCanary = 'com.squareup.leakcanary:leakcanary-android:1.4-beta1'
leakCanaryNoOp = 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta1'
leakCanary = 'com.squareup.leakcanary:leakcanary-android:1.4-beta2'
leakCanaryNoOp = 'com.squareup.leakcanary:leakcanary-android-no-op:1.4-beta2'
rxJava = 'io.reactivex:rxjava:1.1.0'
rxAndroid = 'io.reactivex:rxandroid:1.1.0'