From a6292c300d8d0f8d6d613f152123e76873e17b61 Mon Sep 17 00:00:00 2001 From: Reza Torabi <136625739+rezatutor475@users.noreply.github.com> Date: Tue, 15 Apr 2025 19:25:57 +0330 Subject: [PATCH 1/2] Update MaterialButtonBehavior.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit قابلیت های بیشتر --- MaterialButtonBehavior.java | 172 +++++++++++++++++++++++++++++------- 1 file changed, 139 insertions(+), 33 deletions(-) diff --git a/MaterialButtonBehavior.java b/MaterialButtonBehavior.java index 2852d03..8445798 100644 --- a/MaterialButtonBehavior.java +++ b/MaterialButtonBehavior.java @@ -2,39 +2,47 @@ import android.animation.ValueAnimator; import android.content.Context; +import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.design.button.MaterialButton; import android.support.design.widget.CoordinatorLayout; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; +import android.util.SparseArray; import android.view.View; +import android.view.ViewGroup; import android.view.animation.DecelerateInterpolator; +import java.util.HashMap; +import java.util.Map; /** - * Created by ImanX. + * Created by ImanX. and developed by rezatutor475 */ public class MaterialButtonBehavior extends CoordinatorLayout.Behavior { private ValueAnimator valueAnimator = new ValueAnimator(); - private int expandWidth; - private int collapseWidth; + private int expandWidth; + private int collapseWidth; + private boolean isExpanded = true; + private int animationDuration = 170; + private final Map buttonOriginalWidths = new HashMap<>(); - public MaterialButtonBehavior() { - } + public MaterialButtonBehavior() {} public MaterialButtonBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override - public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull MaterialButton child, @NonNull View directTargetChild, @NonNull View target, int axes, int type) { + public boolean onStartNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull MaterialButton child, + @NonNull View directTargetChild, @NonNull View target, int axes, int type) { return true; } @Override public boolean layoutDependsOn(CoordinatorLayout parent, MaterialButton child, View dependency) { - if (expandWidth == 0 && child.getMeasuredWidth() != 0) { expandWidth = child.getMeasuredWidth(); + buttonOriginalWidths.put(child, expandWidth); } if (collapseWidth == 0 && child.getMinWidth() != 0) { @@ -42,45 +50,143 @@ public boolean layoutDependsOn(CoordinatorLayout parent, MaterialButton child, V } return dependency instanceof RecyclerView; + } + @Override + public void onNestedScroll(CoordinatorLayout coordinatorLayout, MaterialButton child, View target, + int dxConsumed, int dyConsumed, int dxUnconsumed, int dy) { + if (dyConsumed < 0 && !isExpanded) { + animateButtonWidth(child, expandWidth); + isExpanded = true; + } else if (dyConsumed > 0 && isExpanded) { + animateButtonWidth(child, collapseWidth); + isExpanded = false; + } } + private void animateButtonWidth(final View view, int targetWidth) { + if (valueAnimator != null && valueAnimator.isRunning()) return; - @Override - public void onNestedScroll(CoordinatorLayout coordinatorLayout, - MaterialButton child, View target, int dxConsumed, - int dyConsumed, int dxUnconsumed, int dy) { - if (dyConsumed < 0) { - //Scrolling down - measure(child, 170, expandWidth); + int currentWidth = view.getMeasuredWidth(); + valueAnimator = ValueAnimator.ofInt(currentWidth, targetWidth); + valueAnimator.setInterpolator(new DecelerateInterpolator()); + valueAnimator.setDuration(animationDuration); + valueAnimator.addUpdateListener(anim -> { + ViewGroup.LayoutParams params = view.getLayoutParams(); + params.width = (int) anim.getAnimatedValue(); + view.setLayoutParams(params); + }); + valueAnimator.start(); + } - } else if (dyConsumed > 0) { - // Scrolling up - measure(child, 170, collapseWidth); + public void expand(MaterialButton button) { + animateButtonWidth(button, expandWidth); + isExpanded = true; + } + public void collapse(MaterialButton button) { + animateButtonWidth(button, collapseWidth); + isExpanded = false; + } + public void toggle(MaterialButton button) { + if (isExpanded) { + collapse(button); + } else { + expand(button); } } - private void measure(final View v, int duration, int width) { + public void instantExpand(MaterialButton button) { + setButtonWidth(button, expandWidth); + isExpanded = true; + } - if (valueAnimator.isRunning()) { - return; + public void instantCollapse(MaterialButton button) { + setButtonWidth(button, collapseWidth); + isExpanded = false; + } + + public void setButtonWidth(MaterialButton button, int width) { + ViewGroup.LayoutParams params = button.getLayoutParams(); + params.width = width; + button.setLayoutParams(params); + } + + public void calibrateWidth(MaterialButton button) { + if (isExpanded) { + expandWidth = button.getMeasuredWidth(); + } else { + collapseWidth = button.getMeasuredWidth(); } + } + + public boolean isExpanded() { + return isExpanded; + } + public void setAnimationDuration(int duration) { + this.animationDuration = duration; + } - int preWidth = v.getMeasuredWidth(); - valueAnimator.setIntValues(preWidth, width); - valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - v.getLayoutParams().width = (int) animation.getAnimatedValue(); - v.requestLayout(); - } - }); - valueAnimator.setInterpolator(new DecelerateInterpolator()); - valueAnimator.setDuration(duration); - valueAnimator.start(); + public int getAnimationDuration() { + return animationDuration; } -} + public void show(MaterialButton button) { + button.setVisibility(View.VISIBLE); + } + + public void hide(MaterialButton button) { + button.setVisibility(View.INVISIBLE); + } + + public void fadeIn(MaterialButton button, int duration) { + button.setAlpha(0f); + button.setVisibility(View.VISIBLE); + button.animate().alpha(1f).setDuration(duration).start(); + } + + public void fadeOut(MaterialButton button, int duration) { + button.animate().alpha(0f).setDuration(duration) + .withEndAction(() -> button.setVisibility(View.INVISIBLE)).start(); + } + + public void toggleVisibility(MaterialButton button) { + if (button.getVisibility() == View.VISIBLE) { + hide(button); + } else { + show(button); + } + } + + public boolean isAnimationRunning() { + return valueAnimator != null && valueAnimator.isRunning(); + } + + public void stopAnimation() { + if (valueAnimator != null && valueAnimator.isRunning()) { + valueAnimator.cancel(); + } + } + + public void saveState(MaterialButton button, SparseArray container) { + button.saveHierarchyState(container); + } + + public void restoreState(MaterialButton button, SparseArray container) { + button.restoreHierarchyState(container); + } + + public void enable(MaterialButton button) { + button.setEnabled(true); + } + + public void disable(MaterialButton button) { + button.setEnabled(false); + } + + public boolean isEnabled(MaterialButton button) { + return button.isEnabled(); + } +} From 859a6dfe58b32b1ea5a9af8a5283ec56d6e0f1e1 Mon Sep 17 00:00:00 2001 From: Reza Torabi <136625739+rezatutor475@users.noreply.github.com> Date: Tue, 15 Apr 2025 19:28:47 +0330 Subject: [PATCH 2/2] Add files via upload --- Material Button Behavior.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 Material Button Behavior.xml diff --git a/Material Button Behavior.xml b/Material Button Behavior.xml new file mode 100644 index 0000000..948c77d --- /dev/null +++ b/Material Button Behavior.xml @@ -0,0 +1,12 @@ + + + + + +