Tweak height animations

multisite
Floens 10 years ago
parent 1db488d3de
commit 3c2da1c96e
  1. 2
      Clover/app/src/main/java/org/floens/chan/ui/layout/ReplyLayout.java
  2. 2
      Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
  3. 26
      Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadListLayout.java
  4. 1
      Clover/app/src/main/java/org/floens/chan/ui/settings/IntegerSettingView.java
  5. 6
      Clover/app/src/main/java/org/floens/chan/ui/settings/SettingsController.java
  6. 1
      Clover/app/src/main/java/org/floens/chan/ui/settings/StringSettingView.java
  7. 6
      Clover/app/src/main/java/org/floens/chan/ui/view/LoadView.java
  8. 24
      Clover/app/src/main/java/org/floens/chan/utils/AnimationUtils.java
  9. 3
      Clover/app/src/main/res/layout/layout_thread_list.xml

@ -175,7 +175,7 @@ public class ReplyLayout extends LoadView implements View.OnClickListener, Anima
} }
@Override @Override
public void onLayoutAnimationProgress(boolean vertical, View view, float progress) { public void onLayoutAnimationProgress(View view, boolean vertical, int from, int to, int value, float progress) {
if (view == nameOptions) { if (view == nameOptions) {
moreDropdown.setRotation(openingName ? progress : 1f - progress); moreDropdown.setRotation(openingName ? progress : 1f - progress);
} }

@ -331,7 +331,7 @@ public class ThreadLayout extends CoordinatorLayout implements ThreadPresenter.T
@Override @Override
public void showSearch(boolean show) { public void showSearch(boolean show) {
threadListLayout.showSearch(show); threadListLayout.openSearch(show);
} }
public void setSearchStatus(String query, boolean setEmptyText, boolean hideKeyboard) { public void setSearchStatus(String query, boolean setEmptyText, boolean hideKeyboard) {

@ -24,7 +24,7 @@ import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.widget.LinearLayout; import android.widget.FrameLayout;
import android.widget.TextView; import android.widget.TextView;
import org.floens.chan.R; import org.floens.chan.R;
@ -53,7 +53,7 @@ import static org.floens.chan.utils.AndroidUtils.getAttrColor;
/** /**
* A layout that wraps around a {@link RecyclerView} to manage showing posts. * A layout that wraps around a {@link RecyclerView} to manage showing posts.
*/ */
public class ThreadListLayout extends LinearLayout implements ReplyLayout.ReplyLayoutCallback { public class ThreadListLayout extends FrameLayout implements ReplyLayout.ReplyLayoutCallback {
public static final int MAX_SMOOTH_SCROLL_DISTANCE = 20; public static final int MAX_SMOOTH_SCROLL_DISTANCE = 20;
private ReplyLayout reply; private ReplyLayout reply;
@ -70,6 +70,7 @@ public class ThreadListLayout extends LinearLayout implements ReplyLayout.ReplyL
private int background; private int background;
private boolean searchOpen; private boolean searchOpen;
private int lastPostCount; private int lastPostCount;
private int recyclerViewTopPadding;
public ThreadListLayout(Context context, AttributeSet attrs) { public ThreadListLayout(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
@ -145,7 +146,8 @@ public class ThreadListLayout extends LinearLayout implements ReplyLayout.ReplyL
switch (postViewMode) { switch (postViewMode) {
case LIST: case LIST:
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext()); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
recyclerView.setPadding(0, topSpacing(), 0, 0); recyclerViewTopPadding = 0;
recyclerView.setPadding(0, recyclerViewTopPadding + topSpacing(), 0, 0);
recyclerView.setLayoutManager(linearLayoutManager); recyclerView.setLayoutManager(linearLayoutManager);
layoutManager = linearLayoutManager; layoutManager = linearLayoutManager;
@ -158,7 +160,8 @@ public class ThreadListLayout extends LinearLayout implements ReplyLayout.ReplyL
case CARD: case CARD:
GridLayoutManager gridLayoutManager = new GridLayoutManager(null, spanCount, GridLayoutManager.VERTICAL, false); GridLayoutManager gridLayoutManager = new GridLayoutManager(null, spanCount, GridLayoutManager.VERTICAL, false);
// The cards have a 4dp padding, this way there is always 8dp between the edges // The cards have a 4dp padding, this way there is always 8dp between the edges
recyclerView.setPadding(dp(4), dp(4) + topSpacing(), dp(4), dp(4)); recyclerViewTopPadding = dp(4);
recyclerView.setPadding(dp(4), recyclerViewTopPadding + topSpacing(), dp(4), dp(4));
recyclerView.setLayoutManager(gridLayoutManager); recyclerView.setLayoutManager(gridLayoutManager);
layoutManager = gridLayoutManager; layoutManager = gridLayoutManager;
@ -228,11 +231,13 @@ public class ThreadListLayout extends LinearLayout implements ReplyLayout.ReplyL
public void openReply(boolean open) { public void openReply(boolean open) {
if (showingThread != null && replyOpen != open) { if (showingThread != null && replyOpen != open) {
this.replyOpen = open; this.replyOpen = open;
AnimationUtils.animateHeight(reply, replyOpen, getWidth(), 500, reply); int height = AnimationUtils.animateHeight(reply, replyOpen, getWidth(), 500);
if (open) { if (open) {
reply.focusComment(); reply.focusComment();
recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerViewTopPadding + height, recyclerView.getPaddingRight(), recyclerView.getPaddingBottom());
} else { } else {
AndroidUtils.hideKeyboard(reply); AndroidUtils.hideKeyboard(reply);
recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerViewTopPadding + topSpacing(), recyclerView.getPaddingRight(), recyclerView.getPaddingBottom());
} }
threadListLayoutCallback.replyLayoutOpen(open); threadListLayoutCallback.replyLayoutOpen(open);
@ -248,13 +253,16 @@ public class ThreadListLayout extends LinearLayout implements ReplyLayout.ReplyL
postAdapter.showError(error); postAdapter.showError(error);
} }
public void showSearch(boolean show) { public void openSearch(boolean show) {
if (searchOpen != show) { if (searchOpen != show) {
searchOpen = show; searchOpen = show;
AnimationUtils.animateHeight(searchStatus, show); int height = AnimationUtils.animateHeight(searchStatus, show);
if (show) { if (show) {
searchStatus.setText(R.string.search_empty); searchStatus.setText(R.string.search_empty);
recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerViewTopPadding + height, recyclerView.getPaddingRight(), recyclerView.getPaddingBottom());
} else {
recyclerView.setPadding(recyclerView.getPaddingLeft(), recyclerViewTopPadding + topSpacing(), recyclerView.getPaddingRight(), recyclerView.getPaddingBottom());
} }
attachToolbarScroll(!(show || replyOpen)); attachToolbarScroll(!(show || replyOpen));
@ -278,7 +286,7 @@ public class ThreadListLayout extends LinearLayout implements ReplyLayout.ReplyL
} }
public boolean canChildScrollUp() { public boolean canChildScrollUp() {
if (replyOpen) { if (replyOpen || searchOpen) {
return true; return true;
} }
@ -322,7 +330,7 @@ public class ThreadListLayout extends LinearLayout implements ReplyLayout.ReplyL
postAdapter.cleanup(); postAdapter.cleanup();
reply.cleanup(); reply.cleanup();
openReply(false); openReply(false);
showSearch(false); openSearch(false);
showingThread = null; showingThread = null;
lastPostCount = 0; lastPostCount = 0;
} }

@ -65,6 +65,7 @@ public class IntegerSettingView extends SettingView implements View.OnClickListe
editText.setText(setting.get().toString()); editText.setText(setting.get().toString());
editText.setInputType(InputType.TYPE_CLASS_NUMBER); editText.setInputType(InputType.TYPE_CLASS_NUMBER);
editText.setSingleLine(true); editText.setSingleLine(true);
editText.setSelection(editText.getText().length());
container.addView(editText, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); container.addView(editText, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);

@ -74,7 +74,7 @@ public class SettingsController extends Controller implements AndroidUtils.OnMea
} }
private void setMargins() { private void setMargins() {
boolean tablet = context.getResources().getBoolean(R.bool.is_tablet); boolean tablet = AndroidUtils.isTablet(context);
int margin = 0; int margin = 0;
if (tablet) { if (tablet) {
@ -102,7 +102,7 @@ public class SettingsController extends Controller implements AndroidUtils.OnMea
protected void setSettingViewVisibility(SettingView settingView, boolean visible, boolean animated) { protected void setSettingViewVisibility(SettingView settingView, boolean visible, boolean animated) {
if (animated) { if (animated) {
AnimationUtils.animateHeight(settingView.view, visible); AnimationUtils.animateHeight(settingView.view, visible, ((View) settingView.view.getParent()).getWidth());
} else { } else {
settingView.view.setVisibility(visible ? View.VISIBLE : View.GONE); settingView.view.setVisibility(visible ? View.VISIBLE : View.GONE);
} }
@ -168,7 +168,7 @@ public class SettingsController extends Controller implements AndroidUtils.OnMea
bottom.setText(bottomText); bottom.setText(bottomText);
} }
AnimationUtils.animateHeight(bottom, bottomText != null); AnimationUtils.animateHeight(bottom, bottomText != null, ((View) view.getParent()).getWidth());
} else { } else {
bottom.setText(bottomText); bottom.setText(bottomText);
bottom.setVisibility(bottomText == null ? View.GONE : View.VISIBLE); bottom.setVisibility(bottomText == null ? View.GONE : View.VISIBLE);

@ -60,6 +60,7 @@ public class StringSettingView extends SettingView implements View.OnClickListen
editText.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN); editText.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN);
editText.setText(setting.get()); editText.setText(setting.get());
editText.setSingleLine(true); editText.setSingleLine(true);
editText.setSelection(editText.getText().length());
container.addView(editText, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); container.addView(editText, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);

@ -175,6 +175,12 @@ public class LoadView extends FrameLayout {
} }
} }
if (animateVertical) {
newSize += getPaddingTop() + getPaddingBottom();
} else {
newSize += getPaddingLeft() + getPaddingRight();
}
AnimationUtils.animateLayout(animateVertical, this, currentSize, newSize, layoutAnimationDuration, true, null); AnimationUtils.animateLayout(animateVertical, this, currentSize, newSize, layoutAnimationDuration, true, null);
} }
} else { } else {

@ -28,6 +28,10 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class AnimationUtils { public class AnimationUtils {
public static int interpolate(int a, int b, float x) {
return (int) (a + (b - a) * x);
}
public static void setHeight(View view, boolean expand, boolean animated) { public static void setHeight(View view, boolean expand, boolean animated) {
setHeight(view, expand, animated, -1); setHeight(view, expand, animated, -1);
} }
@ -42,16 +46,16 @@ public class AnimationUtils {
private static Map<View, ValueAnimator> layoutAnimations = new HashMap<>(); private static Map<View, ValueAnimator> layoutAnimations = new HashMap<>();
public static void animateHeight(final View view, boolean expand) { public static int animateHeight(final View view, boolean expand) {
animateHeight(view, expand, -1); return animateHeight(view, expand, -1);
} }
public static void animateHeight(final View view, final boolean expand, int knownWidth) { public static int animateHeight(final View view, final boolean expand, int knownWidth) {
animateHeight(view, expand, knownWidth, 300); return animateHeight(view, expand, knownWidth, 300);
} }
public static void animateHeight(final View view, final boolean expand, int knownWidth, int duration) { public static int animateHeight(final View view, final boolean expand, int knownWidth, int duration) {
animateHeight(view, expand, knownWidth, duration, null); return animateHeight(view, expand, knownWidth, duration, null);
} }
/** /**
@ -61,7 +65,7 @@ public class AnimationUtils {
* You can call this even when a height animation is currently running, it will resolve any issues.<br> * You can call this even when a height animation is currently running, it will resolve any issues.<br>
* <b>This does cause some lag on complex views because requestLayout is called on each frame.</b> * <b>This does cause some lag on complex views because requestLayout is called on each frame.</b>
*/ */
public static void animateHeight(final View view, final boolean expand, int knownWidth, int duration, final LayoutAnimationProgress progressCallback) { public static int animateHeight(final View view, final boolean expand, int knownWidth, int duration, final LayoutAnimationProgress progressCallback) {
final int fromHeight; final int fromHeight;
int toHeight; int toHeight;
if (expand) { if (expand) {
@ -78,6 +82,8 @@ public class AnimationUtils {
} }
animateLayout(true, view, fromHeight, toHeight, duration, true, progressCallback); animateLayout(true, view, fromHeight, toHeight, duration, true, progressCallback);
return toHeight;
} }
public static void animateLayout(final boolean vertical, final View view, final int from, final int to, int duration, final boolean wrapAfterwards, final LayoutAnimationProgress callback) { public static void animateLayout(final boolean vertical, final View view, final int from, final int to, int duration, final boolean wrapAfterwards, final LayoutAnimationProgress callback) {
@ -103,7 +109,7 @@ public class AnimationUtils {
view.requestLayout(); view.requestLayout();
if (callback != null) { if (callback != null) {
callback.onLayoutAnimationProgress(vertical, view, animation.getAnimatedFraction()); callback.onLayoutAnimationProgress(view, vertical, from, to, value, animation.getAnimatedFraction());
} }
} }
}); });
@ -145,6 +151,6 @@ public class AnimationUtils {
} }
public interface LayoutAnimationProgress { public interface LayoutAnimationProgress {
void onLayoutAnimationProgress(boolean vertical, View view, float progress); void onLayoutAnimationProgress(View view, boolean vertical, int from, int to, int value, float progress);
} }
} }

@ -43,8 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
<android.support.v7.widget.RecyclerView <android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view" android:id="@+id/recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent"
android:layout_weight="1"
android:clipToPadding="false" android:clipToPadding="false"
android:scrollbars="vertical" /> android:scrollbars="vertical" />

Loading…
Cancel
Save