diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index a65986a14..c3b14d39f 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/app/src/main/java/com/ns/yc/lifehelper/ui/data/contract/DataFragmentContract.java b/app/src/main/java/com/ns/yc/lifehelper/ui/data/contract/DataFragmentContract.java index 09b23f7c2..649c05023 100644 --- a/app/src/main/java/com/ns/yc/lifehelper/ui/data/contract/DataFragmentContract.java +++ b/app/src/main/java/com/ns/yc/lifehelper/ui/data/contract/DataFragmentContract.java @@ -1,38 +1,35 @@ package com.ns.yc.lifehelper.ui.data.contract; +import com.ns.yc.lifehelper.model.bean.ImageIconBean; import com.ycbjie.library.base.mvp.BasePresenter; import com.ycbjie.library.base.mvp.BaseView; -import com.ns.yc.lifehelper.model.bean.ImageIconBean; -import com.ns.yc.lifehelper.ui.main.view.MainActivity; import java.util.ArrayList; import java.util.List; + /** - * ================================================ - * 作 者:杨充 - * 版 本:1.0 - * 创建日期:2017/3/18 - * 描 述:工具页面 - * 修订历史: - * v1.5 17年10月3日修改 - * ================================================ + *
+ * @author yangchong + * blog : https://github.com/yangchong211 + * time : 2016/03/22 + * desc : + * revise: v1.4 17年6月8日 + * v1.5 17年10月3日修改 + **/ public interface DataFragmentContract { - //View(activity/fragment)继承,需要实现的方法 interface View extends BaseView { void setGridView(String[] toolName, ArrayList
+ * @author yangchong + * blog : https://github.com/yangchong211 + * time : 2017/11/21 + * desc : 数据页面,使用阿里巴巴Vlayout框架 + * revise: v1.4 17年6月8日 + * v1.5 17年10月3日修改 + **/ public interface FindFragmentContract { diff --git a/douban/src/main/java/com/ycbjie/douban/view/activity/DouBookDetailActivity.java b/douban/src/main/java/com/ycbjie/douban/view/activity/DouBookDetailActivity.java index fad59a939..c42c9706b 100644 --- a/douban/src/main/java/com/ycbjie/douban/view/activity/DouBookDetailActivity.java +++ b/douban/src/main/java/com/ycbjie/douban/view/activity/DouBookDetailActivity.java @@ -20,6 +20,7 @@ import com.ycbjie.library.base.mvp.BaseActivity; import com.ycbjie.library.constant.Constant; import com.ycbjie.library.utils.image.ImageUtils; +import com.ycbjie.library.weight.CustomScrollView; import io.reactivex.Observer; import io.reactivex.android.schedulers.AndroidSchedulers; @@ -55,7 +56,7 @@ public class DouBookDetailActivity extends BaseActivity { private Constant.CollapsingToolbarLayoutState state; private String id; private String alt; - + private CustomScrollView scrollView; @Override protected void onDestroy() { @@ -91,6 +92,7 @@ private void initFindViewById() { toolbar = findViewById(R.id.toolbar); tvName = findViewById(R.id.tv_name); tvCasts = findViewById(R.id.tv_casts); + scrollView = findViewById(R.id.scrollView); } @SuppressLint("SetTextI18n") @@ -139,6 +141,21 @@ public void initListener() { toolbar.setBackgroundColor(getResources().getColor(R.color.colorTransparent)); } }); + scrollView.setListener(new CustomScrollView.ScrollListener() { + @Override + public int onScrollListener() { + switch (state){ + case INTERNEDIATE: + return CustomScrollView.STATES.INTERMEDIATE; + case COLLAPSED: + return CustomScrollView.STATES.COLLAPSED; + case EXPANDED: + return CustomScrollView.STATES.EXPANDED; + default: + return CustomScrollView.STATES.INTERMEDIATE; + } + } + }); } @Override diff --git a/douban/src/main/java/com/ycbjie/douban/view/activity/MovieTopActivity.java b/douban/src/main/java/com/ycbjie/douban/view/activity/MovieTopActivity.java index 7375ddd71..27c94ea2e 100644 --- a/douban/src/main/java/com/ycbjie/douban/view/activity/MovieTopActivity.java +++ b/douban/src/main/java/com/ycbjie/douban/view/activity/MovieTopActivity.java @@ -15,7 +15,7 @@ import com.ycbjie.library.base.mvp.BaseActivity; import com.ycbjie.douban.view.adapter.MovieTopAdapter; import com.ycbjie.douban.bean.DouHotMovieBean; -import com.ycbjie.library.weight.manager.FullyGridLayoutManager; +import com.ycbjie.library.weight.FullyGridLayoutManager; import org.yczbj.ycrefreshviewlib.YCRefreshView; import org.yczbj.ycrefreshviewlib.adapter.RecyclerArrayAdapter; diff --git a/douban/src/main/java/com/ycbjie/douban/view/fragment/DouBookFragment.java b/douban/src/main/java/com/ycbjie/douban/view/fragment/DouBookFragment.java index 6f6a4c915..381240495 100644 --- a/douban/src/main/java/com/ycbjie/douban/view/fragment/DouBookFragment.java +++ b/douban/src/main/java/com/ycbjie/douban/view/fragment/DouBookFragment.java @@ -17,7 +17,7 @@ import com.ycbjie.douban.view.activity.DouBookDetailActivity; import com.ycbjie.douban.view.adapter.DouBookAdapter; import com.ycbjie.library.base.mvp.BaseLazyFragment; -import com.ycbjie.library.weight.manager.FullyGridLayoutManager; +import com.ycbjie.library.weight.FullyGridLayoutManager; import org.yczbj.ycrefreshviewlib.YCRefreshView; import org.yczbj.ycrefreshviewlib.adapter.RecyclerArrayAdapter; diff --git a/douban/src/main/res/layout/activity_book_detail.xml b/douban/src/main/res/layout/activity_book_detail.xml index 70c23e882..1b5a4e119 100644 --- a/douban/src/main/res/layout/activity_book_detail.xml +++ b/douban/src/main/res/layout/activity_book_detail.xml @@ -6,14 +6,13 @@ android:layout_height="match_parent" android:fitsSystemWindows="true"> -
+ * @author yangchong + * blog : https://github.com/yangchong211 + * time : 2019/03/13 + * desc : 自定义具有弹簧效果的控件 + * revise: 1.支持滑动松手后控件带有弹簧效果 + * 2.可以设置下滑滑动的最大位移,超过最大值不让滑动 + * 3.设置view移动位移是滑动距离的比例相同,该比例可以设置 + * 4.页面销毁时,清除动画 + * 5.支持动态设置阻尼回弹次数,目前设置是2次,可以设置回弹速度 + * 6.需要解决和父布局的滑动冲突 + * 7.当滑动到顶部或者底部的时候,让父View消费事件 + *+ */ +public class CustomScrollView extends NestedScrollView { + + /** + * 手指开始移动的y + */ + private float startDragY; + /** + * 阻尼弹簧动画 + */ + private SpringAnimation springAnim; + /** + * 设置支持滑动最大的位移 + */ + private static final int MAX_MOVE = 400; + /** + * ScrollView的子View, 也是ScrollView的唯一一个子View + */ + private View contentView; + private float downX; + private float downY; + + /** + * 配合CoordinatorLayout使用,解决滑动卡顿和冲突 + */ + @Retention(RetentionPolicy.SOURCE) + public @interface STATES{ + int EXPANDED = 3; + int COLLAPSED = 2; + int INTERMEDIATE = 1; + } + + public CustomScrollView(@NonNull Context context) { + this(context,null); + } + + public CustomScrollView(@NonNull Context context, @Nullable AttributeSet attrs) { + this(context, attrs,0); + } + + public CustomScrollView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initAnimation(); + } + + private void initAnimation() { + springAnim = new SpringAnimation(this, SpringAnimation.TRANSLATION_Y, 0); + //刚度 默认1200 值越大回弹的速度越快 + //Stiffness刚度(劲度/弹性),刚度越大,形变产生的里也就越大,体现在效果上就是运动越快 + springAnim.getSpring().setStiffness(400.0f); + //阻尼 默认0.5 值越小,回弹之后来回的次数越多 + springAnim.getSpring().setDampingRatio(0.50f); + //设置时间 + springAnim.setStartVelocity(2000); + } + + /*** + * 根据 XML 生成视图工作完成.该函数在生成视图的最后调用,在所有子视图添加完之后. + * 即使子类覆盖了 onFinishInflate方法,也应该调用父类的方法,使该方法得以执行. + */ + @Override + protected void onFinishInflate() { + if (getChildCount() > 0) { + contentView = getChildAt(0); + } + super.onFinishInflate(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + //当view销毁的时候,需要关闭动画资源 + if (springAnim!=null){ + springAnim.cancel(); + springAnim = null; + } + } + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + switch (ev.getAction()) { + case MotionEvent.ACTION_DOWN: + downX = ev.getX(); + downY = ev.getY(); + //如果滑动到了最底部,就允许继续向上滑动,可以加载那个更多【listView,下一页等】 + getParent().requestDisallowInterceptTouchEvent(true); + break; + case MotionEvent.ACTION_MOVE: + float dx = ev.getX() - downX; + float dy = ev.getY() - downY; + boolean allowParentTouchEvent; + if (Math.abs(dy) > Math.abs(dx)) { + if (dy > 0) { + //位于顶部时下拉,让父View消费事件 + allowParentTouchEvent = isTop(); + } else { + //位于底部时上拉,让父View消费事件 + allowParentTouchEvent = isBottom(); + } + } else { + //水平方向滑动 + allowParentTouchEvent = true; + } + getParent().requestDisallowInterceptTouchEvent(!allowParentTouchEvent); + break; + default: + break; + } + return super.dispatchTouchEvent(ev); + } + + @SuppressLint("NewApi") + public boolean isTop() { + return !canScrollVertically(-1); + } + + public boolean isBottom() { + return !canScrollVertically(1); + } + + @SuppressLint("ClickableViewAccessibility") + @Override + public boolean onTouchEvent(MotionEvent e) { + switch (e.getAction()) { + //手指移动【主要是分为两种:向上滑动,向下滑动】 + case MotionEvent.ACTION_MOVE: + if (getScrollY() <= 0) { + if (listener!=null){ + int i = listener.onScrollListener(); + if (i==STATES.EXPANDED){ + //顶部下拉 + if (startDragY == 0) { + startDragY = e.getRawY(); + } + // 滑动距离 + int deltaY = (int) (e.getRawY() - startDragY); + if (deltaY > 0 && deltaY < MAX_MOVE) { + Log.e("CustomScrollView","onTouchEvent-----------------"+deltaY); + //设置view下滑的位移是手指滑动距离位移的三分之一 + setTranslationY((e.getRawY() - startDragY)); + return true; + } else if (deltaY>MAX_MOVE){ + Log.e("CustomScrollView","onTouchEvent-----------------"+deltaY); + setTranslationY(MAX_MOVE); + return true; + } else { + Log.e("CustomScrollView","onTouchEvent-----------------"+deltaY); + springAnim.cancel(); + setTranslationY(0); + } + } + } + } else if ((getScrollY() + getHeight()) >= contentView.getMeasuredHeight()) { + //底部上拉 + if (startDragY == 0) { + //时时y坐标 + startDragY = e.getRawY(); + } + // 滑动距离 + int deltaY = (int) (e.getRawY() - startDragY); + if (deltaY < 0) { + Log.e("CustomScrollView","1-----------------"+deltaY); + setTranslationY((e.getRawY() - startDragY) / 3); + return true; + } else { + Log.e("CustomScrollView","2-----------------"+deltaY); + springAnim.cancel(); + setTranslationY(0); + } + } + break; + //手指抬起 + case MotionEvent.ACTION_UP: + //手指滑动结束 + case MotionEvent.ACTION_CANCEL: + if (getTranslationY() != 0) { + //当手指抬起的时候,就开始动画 + springAnim.start(); + } + startDragY = 0; + break; + default: + break; + } + return super.onTouchEvent(e); + } + + public ScrollListener listener; + public interface ScrollListener{ + /** + * 滑动监听事件 + * @return STATES + */ + int onScrollListener(); + } + + public void setListener(ScrollListener listener){ + this.listener = listener; + } + +} diff --git a/library/src/main/java/com/ycbjie/library/weight/FlingBehavior.java b/library/src/main/java/com/ycbjie/library/weight/FlingBehavior.java new file mode 100644 index 000000000..fe6d3b163 --- /dev/null +++ b/library/src/main/java/com/ycbjie/library/weight/FlingBehavior.java @@ -0,0 +1,51 @@ +package com.ycbjie.library.weight; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.design.widget.AppBarLayout; +import android.support.design.widget.CoordinatorLayout; +import android.util.AttributeSet; +import android.view.View; + +public final class FlingBehavior extends AppBarLayout.Behavior { + + /** + * 是否处于惯性滑动状态 + */ + private boolean isFlinging = false; + + public FlingBehavior() { + + } + + public FlingBehavior(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout abl, + View target, int type) { + //如果不是惯性滑动,让他可以执行紧贴操作 + if (!isFlinging) { + super.onStopNestedScroll(coordinatorLayout, abl, target, type); + } + } + @Override + public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, + AppBarLayout child, View target, int dx, + int dy, int[] consumed, int type) { + super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type); + //type==1时处于非惯性滑动 + if (type == 1) { + isFlinging = false; + } + } + @Override + public boolean onNestedFling(@NonNull CoordinatorLayout coordinatorLayout, + @NonNull AppBarLayout child, @NonNull View target, + float velocityX, float velocityY, boolean consumed) { + //惯性滑动的时候设置为true + isFlinging = true; + return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed); + } +} diff --git a/library/src/main/java/com/ycbjie/library/weight/manager/FullyGridLayoutManager.java b/library/src/main/java/com/ycbjie/library/weight/FullyGridLayoutManager.java similarity index 99% rename from library/src/main/java/com/ycbjie/library/weight/manager/FullyGridLayoutManager.java rename to library/src/main/java/com/ycbjie/library/weight/FullyGridLayoutManager.java index 822f1fc21..ec8bf4aee 100644 --- a/library/src/main/java/com/ycbjie/library/weight/manager/FullyGridLayoutManager.java +++ b/library/src/main/java/com/ycbjie/library/weight/FullyGridLayoutManager.java @@ -1,4 +1,4 @@ -package com.ycbjie.library.weight.manager; +package com.ycbjie.library.weight; import android.content.Context; import android.support.v7.widget.GridLayoutManager; diff --git a/library/src/main/java/com/ycbjie/library/weight/manager/FullyLinearLayoutManager.java b/library/src/main/java/com/ycbjie/library/weight/manager/FullyLinearLayoutManager.java deleted file mode 100644 index 08bad2637..000000000 --- a/library/src/main/java/com/ycbjie/library/weight/manager/FullyLinearLayoutManager.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.ycbjie.library.weight.manager; - -import android.content.Context; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.util.Log; -import android.view.View; -import android.view.ViewGroup; - -/** - * Created by PC on 2017/4/13 - * 解决ScrollView嵌套RecyclerView的冲突 - * GridLayoutManager可以直接换成LinearLayoutManager - */ - -public class FullyLinearLayoutManager extends LinearLayoutManager { - - private static final String TAG = FullyLinearLayoutManager.class.getSimpleName(); - private int[] mMeasuredDimension = new int[2]; - - public FullyLinearLayoutManager(Context context, int orientation, boolean reverseLayout) { - super(context, orientation, reverseLayout); - } - - public FullyLinearLayoutManager(Context context) { - super(context); - } - - @Override - public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state, int widthSpec, int heightSpec) { - - final int widthMode = View.MeasureSpec.getMode(widthSpec); - final int heightMode = View.MeasureSpec.getMode(heightSpec); - final int widthSize = View.MeasureSpec.getSize(widthSpec); - final int heightSize = View.MeasureSpec.getSize(heightSpec); - - Log.i(TAG, "onMeasure called. \nwidthMode " + widthMode - + " \nheightMode " + heightSpec - + " \nwidthSize " + widthSize - + " \nheightSize " + heightSize - + " \ngetItemCount() " + getItemCount()); - - int width = 0; - int height = 0; - for (int i = 0; i < getItemCount(); i++) { - measureScrapChild(recycler, i, - View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), - View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED), - mMeasuredDimension); - - if (getOrientation() == HORIZONTAL) { - width = width + mMeasuredDimension[0]; - if (i == 0) { - height = mMeasuredDimension[1]; - } - } else { - height = height + mMeasuredDimension[1]; - if (i == 0) { - width = mMeasuredDimension[0]; - } - } - } - switch (widthMode) { - case View.MeasureSpec.EXACTLY: - width = widthSize; - case View.MeasureSpec.AT_MOST: - case View.MeasureSpec.UNSPECIFIED: - } - - switch (heightMode) { - case View.MeasureSpec.EXACTLY: - height = heightSize; - case View.MeasureSpec.AT_MOST: - case View.MeasureSpec.UNSPECIFIED: - } - setMeasuredDimension(width, height); - } - - private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec, int heightSpec, int[] measuredDimension) { - try { - View view = recycler.getViewForPosition(0);//fix 动态添加时报IndexOutOfBoundsException - if (view != null) { - RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams(); - int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec, getPaddingLeft() + getPaddingRight(), p.width); - int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec, getPaddingTop() + getPaddingBottom(), p.height); - view.measure(childWidthSpec, childHeightSpec); - measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin; - measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin; - recycler.recycleView(view); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - -} diff --git a/other/src/main/AndroidManifest.xml b/other/src/main/AndroidManifest.xml index 86ebcbfec..061978785 100644 --- a/other/src/main/AndroidManifest.xml +++ b/other/src/main/AndroidManifest.xml @@ -15,6 +15,7 @@