├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── allrecycleview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── em │ │ └── sang │ │ └── com │ │ └── allrecycleview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── em │ │ │ └── sang │ │ │ └── com │ │ │ └── allrecycleview │ │ │ ├── BaiscRecycleView.java │ │ │ ├── BasicRefrushRecycleView.java │ │ │ ├── OverlapRecycleView.java │ │ │ ├── RefrushRecycleView.java │ │ │ ├── adapter │ │ │ ├── BasicAdapter.java │ │ │ ├── CustomBasicAdapter.java │ │ │ ├── DefaultAdapter.java │ │ │ └── RefrushAdapter.java │ │ │ ├── cutline │ │ │ ├── DividerGridItemDecoration.java │ │ │ └── RecycleViewDivider.java │ │ │ ├── holder │ │ │ ├── CustomHolder.java │ │ │ ├── CustomPeakHolder.java │ │ │ ├── FootHolder.java │ │ │ ├── HeardHolder.java │ │ │ └── SimpleHolder.java │ │ │ ├── inter │ │ │ ├── BodyInitListener.java │ │ │ ├── CustomAdapterListener.java │ │ │ ├── DefaultAdapterViewLisenter.java │ │ │ ├── DefaultRefrushListener.java │ │ │ ├── OverlapListener.java │ │ │ └── RefrushListener.java │ │ │ ├── layoutmanager │ │ │ └── OverlapManager.java │ │ │ └── listener │ │ │ └── OnToolsItemClickListener.java │ └── res │ │ ├── layout │ │ └── heard_refrush.xml │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── em │ └── sang │ └── com │ └── allrecycleview │ └── ExampleUnitTest.java ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── xiaonian │ │ └── sang │ │ └── alibehaver │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── xiaonian │ │ │ └── sang │ │ │ └── alibehaver │ │ │ ├── CustomBehavior.java │ │ │ ├── MainActivity.java │ │ │ ├── bean │ │ │ └── GrideBean.java │ │ │ ├── holder │ │ │ ├── GrideHolder.java │ │ │ ├── HomeCarouselHolder.java │ │ │ └── ItemHolder.java │ │ │ └── utils │ │ │ └── ToastUtil.java │ └── res │ │ ├── drawable │ │ ├── selector_color_gay.xml │ │ ├── tag_carousel.xml │ │ ├── tag_gray.xml │ │ └── tag_red.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── item.xml │ │ ├── item_home_carousel.xml │ │ └── recycleview_gride.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── add.png │ │ ├── home_banner1.png │ │ ├── home_banner2.png │ │ ├── home_banner3.png │ │ ├── home_banner4.png │ │ ├── home_banner5.jpg │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── life_recharge.png │ │ ├── main_card_bag.png │ │ ├── main_pay.png │ │ ├── main_recive.png │ │ ├── main_scan.png │ │ ├── phone_recharge.png │ │ └── search.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── xiaonian │ └── sang │ └── alibehaver │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── viewfractory ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── com │ └── sang │ └── viewfractory │ └── ExampleInstrumentedTest.java ├── main ├── AndroidManifest.xml ├── java │ └── com │ │ └── sang │ │ └── viewfractory │ │ ├── BasicView.java │ │ ├── factory │ │ └── ShapFactory.java │ │ ├── listener │ │ └── OnScrollSelectListener.java │ │ ├── utils │ │ ├── Apputils.java │ │ ├── BarUtils.java │ │ ├── Config.java │ │ ├── DeviceUtils.java │ │ ├── JLog.java │ │ ├── LockPatternUtil.java │ │ ├── ScrollUtils.java │ │ ├── ToastUtil.java │ │ ├── UnOverWriteException.java │ │ └── ViewUtils.java │ │ └── view │ │ ├── FloatView.java │ │ ├── HorizontalProgress.java │ │ ├── LockPatternView.java │ │ ├── MoveView.java │ │ ├── PickView.java │ │ ├── PickerScrollView.java │ │ ├── RefrushLinearLayout.java │ │ └── ShapeView.java └── res │ ├── drawable │ ├── bt_gry.xml │ ├── bt_tran.xml │ └── select_tv_bg.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ └── strings.xml └── test └── java └── com └── sang └── viewfractory └── ExampleUnitTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Android 39 | 40 | 41 | Android > Lint > Correctness 42 | 43 | 44 | Android > Lint > Performance 45 | 46 | 47 | Class structureJava 48 | 49 | 50 | Code maturity issuesJava 51 | 52 | 53 | Java 54 | 55 | 56 | Java language level migration aidsJava 57 | 58 | 59 | Javadoc issuesJava 60 | 61 | 62 | Performance issuesJava 63 | 64 | 65 | TestNGJava 66 | 67 | 68 | Threading issuesJava 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 90 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 最近在和项目经理都斗智斗勇的时候,突然被甩过来一个类似支付宝首页的功能需求,虽然网上有一些类似的功能,但是都是以前比较老一些的版本,于是决定自己来定制一个,老规矩,先上图 2 | 3 | ![GIF.gif](http://upload-images.jianshu.io/upload_images/2599466-3a7bd996bd887dac.gif?imageMogr2/auto-orient/strip) 4 | 5 | 要实现这样一个效果,首先想到的自然就是 CoordinatorLayout; 6 | 7 | 什么是CoordinatorLayout? 8 | CoordinatorLayout是用来协调其子view们之间动作的一个父view,而Behavior就是用来给CoordinatorLayout的子view们实现交互的。关于这个控件,大神们已经介绍的很详细了,这里我就不过多啰嗦,直接开撸了 9 | 10 | 关于Behavior 11 | 要自定义Behavior,首先要搞清楚两个核心View,child 和 dependency;他们分别代表的是要应用behavior的View 和触发behavior并与child进行互动的View。 12 | 13 | 要实现上面的的效果,需要实现以下几个关键方法 14 | - layoutDependsOn(CoordinatorLayout parent, View child, View dependency) 15 | 用来判断child是否有一个对应的dependency,如果有就返回true,默认情况下返回的是false 16 | 17 | - onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) 18 | 此方法可用于动态更改childView的布局,如果自定义Behaior,这个方法一定返回true,否则将使用默认Behavior的布局 19 | 20 | - onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) 21 | 此方法在dependencyView发生变化的时候调用,在这里,我们可以对child根据dependency的变化进行一定的操作 22 | 23 | - onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) 24 | 此方法表示开始滑动,最后一个参数表示的是滑动方向,并且只有在返回值为true的时候才能出发接下来的操作,在这里可以进行一些过滤操作,比如值接受垂直方向的滑动等 25 | 26 | - onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) 27 | 在onStartNestedScroll返回为true的时候调用,此时表示CoordinatorLayout已经拦截了滑动,在这里可以做一些滑动初始化的操作 28 | 29 | - onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) 30 | 在开始嵌套滑动之前,会执行此操作,dx、dy分别表示用户手指滑动的距离,consumed则表示在操作过程中,消耗掉的滑动距离,例如: 31 | ``` 32 | consumed[1] = dy; 33 | ``` 34 | 此时表示垂直方向的滑动被全部消耗,将不会被传递到下一步操作,相对应的child,如RecycleView将不能接受的滑动操作,不会进行滑动 35 | 36 | - onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) 37 | 此方法在嵌套滑动时候调用,可以多滑动过程进行操作 38 | 39 | 具体解析,请看我的个人文章:[来来来,随老夫撸一个支付宝玩玩——自定义Behavior的正确打开方式](http://www.jianshu.com/p/de8081d41b9c) 40 | -------------------------------------------------------------------------------- /allrecycleview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /allrecycleview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 24 5 | buildToolsVersion '25.0.0' 6 | 7 | defaultConfig { 8 | minSdkVersion 17 9 | targetSdkVersion 24 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | 15 | } 16 | lintOptions{ 17 | abortOnError false 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | } 26 | 27 | dependencies { 28 | compile fileTree(include: ['*.jar'], dir: 'libs') 29 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 30 | exclude group: 'com.android.support', module: 'support-annotations' 31 | }) 32 | compile 'com.android.support:appcompat-v7:24.2.1' 33 | testCompile 'junit:junit:4.12' 34 | compile 'com.android.support:recyclerview-v7:24.2.1' 35 | compile project(path: ':viewfractory') 36 | } 37 | -------------------------------------------------------------------------------- /allrecycleview/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\develop\SDK/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /allrecycleview/src/androidTest/java/em/sang/com/allrecycleview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("em.sang.com.allrecycleview.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /allrecycleview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/BaiscRecycleView.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview; 2 | 3 | 4 | import android.content.Context; 5 | import android.support.annotation.Nullable; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.support.v7.widget.StaggeredGridLayoutManager; 9 | import android.util.AttributeSet; 10 | 11 | /** 12 | * 13 | * 是时候撸点真正的代码了!!! 14 | * 15 | * 创建人:桑小年 16 | * 日期: 2017/6/2 17 | * 18 | * 功能描述:基础的类,包涵一些基本的功能 19 | */ 20 | 21 | public class BaiscRecycleView extends RecyclerView { 22 | public BaiscRecycleView(Context context) { 23 | super(context); 24 | initView(context, null, 0); 25 | } 26 | 27 | public BaiscRecycleView(Context context, @Nullable AttributeSet attrs) { 28 | super(context, attrs); 29 | initView(context, attrs, 0); 30 | } 31 | 32 | public BaiscRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) { 33 | super(context, attrs, defStyle); 34 | initView(context, attrs, defStyle); 35 | } 36 | protected void initView(Context context, @Nullable AttributeSet attrs, int defStyle) { 37 | } 38 | 39 | public boolean isFirst() { 40 | LayoutManager manager = getLayoutManager(); 41 | if (manager instanceof LinearLayoutManager) { 42 | LinearLayoutManager linearLayoutManager = ((LinearLayoutManager) manager); 43 | int position = linearLayoutManager.findFirstCompletelyVisibleItemPosition(); 44 | if (position == -1) { 45 | position = 0; 46 | } 47 | return 0 == position ; 48 | } else if (manager instanceof StaggeredGridLayoutManager) { 49 | 50 | int position = 0; 51 | try { 52 | position = ((StaggeredGridLayoutManager) manager).findFirstVisibleItemPositions(new int[2])[0]; 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | } 56 | 57 | if (position <= 0) { 58 | position = 0; 59 | } 60 | return 0 == position ; 61 | } else { 62 | return false; 63 | } 64 | } 65 | 66 | public boolean isLast() { 67 | int itemCount = getAdapter().getItemCount() - 1; 68 | LayoutManager manager = getLayoutManager(); 69 | if (manager instanceof LinearLayoutManager) { 70 | LinearLayoutManager linearLayoutManager = ((LinearLayoutManager) manager); 71 | return itemCount == linearLayoutManager.findLastVisibleItemPosition() ; 72 | } else if (manager instanceof StaggeredGridLayoutManager) { 73 | int i = 0; 74 | try { 75 | i = ((StaggeredGridLayoutManager) manager).findLastVisibleItemPositions(new int[2])[0]; 76 | } catch (Exception e) { 77 | e.printStackTrace(); 78 | } 79 | return itemCount == i; 80 | 81 | } else { 82 | return false; 83 | } 84 | } 85 | 86 | 87 | 88 | } 89 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/OverlapRecycleView.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.animation.TimeInterpolator; 6 | import android.animation.ValueAnimator; 7 | import android.app.Activity; 8 | import android.content.Context; 9 | import android.graphics.Bitmap; 10 | import android.support.annotation.Nullable; 11 | import android.support.v7.widget.RecyclerView; 12 | import android.util.AttributeSet; 13 | import android.view.MotionEvent; 14 | import android.view.View; 15 | import android.view.ViewGroup; 16 | import android.view.animation.LinearInterpolator; 17 | import android.view.animation.OvershootInterpolator; 18 | import android.widget.FrameLayout; 19 | import android.widget.ImageView; 20 | import android.widget.LinearLayout; 21 | import android.widget.TextView; 22 | 23 | import com.sang.viewfractory.utils.Apputils; 24 | import com.sang.viewfractory.utils.JLog; 25 | 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | import em.sang.com.allrecycleview.adapter.BasicAdapter; 30 | 31 | /** 32 | * Description: 33 | * 34 | * @Author:桑小年 35 | * @Data:2016/12/22 16:38 36 | */ 37 | public class OverlapRecycleView extends RecyclerView { 38 | 39 | private float downX, downY; 40 | private float childLeft, childTop; 41 | private List animations; 42 | private ViewGroup mDecorView; 43 | private int[] mDecorViewLocation; 44 | 45 | 46 | public OverlapRecycleView(Context context) { 47 | super(context); 48 | initView(); 49 | } 50 | 51 | public OverlapRecycleView(Context context, @Nullable AttributeSet attrs) { 52 | super(context, attrs); 53 | initView(); 54 | } 55 | 56 | public OverlapRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) { 57 | super(context, attrs, defStyle); 58 | initView(); 59 | } 60 | 61 | private void initView() { 62 | // setLayoutManager(new OverlapManager(getContext())); 63 | 64 | downY = downX = -1; 65 | mDecorViewLocation = new int[2]; 66 | mDecorView = (FrameLayout) ((Activity) getContext()).getWindow().getDecorView(); 67 | 68 | 69 | mDecorView.getLocationOnScreen(mDecorViewLocation); 70 | animations = new ArrayList<>(); 71 | } 72 | 73 | @Override 74 | public boolean onTouchEvent(MotionEvent e) { 75 | 76 | if (getChildCount() == 0) { 77 | return super.onTouchEvent(e); 78 | } 79 | 80 | if (downX == -1 || downY == -1) { 81 | downX = e.getX(); 82 | downY = e.getY(); 83 | } 84 | 85 | 86 | ViewGroup topView = (ViewGroup) getChildAt(getChildCount() - 1); 87 | TextView at = (TextView) topView.getChildAt(0); 88 | JLog.i(getChildCount() + "------" + at.getText()); 89 | 90 | 91 | float x = topView.getX(); 92 | float y = topView.getY(); 93 | if (childTop == 0 || childLeft == 0) { 94 | childTop = topView.getTop(); 95 | childLeft = topView.getLeft(); 96 | } 97 | 98 | switch (e.getAction()) { 99 | case MotionEvent.ACTION_DOWN: 100 | downX = e.getX(); 101 | downY = e.getY(); 102 | 103 | break; 104 | case MotionEvent.ACTION_MOVE: 105 | float currentX = e.getX(); 106 | float currentY = e.getY(); 107 | topView.setX(x + currentX - downX); 108 | topView.setY(y + currentY - downY); 109 | nextChildScale(getChildCount() - 2, getCurrentScaleByTopView(topView)); 110 | downX = currentX; 111 | downY = currentY; 112 | break; 113 | 114 | case MotionEvent.ACTION_UP: 115 | 116 | default: 117 | upAction(topView); 118 | downY = downX = -1; 119 | break; 120 | } 121 | 122 | 123 | return super.onTouchEvent(e); 124 | } 125 | 126 | private float caculateExitY(float x1, float y1, float x2, float y2, float x3) { 127 | return (y2 - y1) * (x3 - x1) / (x2 - x1) + y1; 128 | } 129 | 130 | private void upAction(final View topView) { 131 | float targtX = childLeft; 132 | float targtY = childTop; 133 | final boolean isChange; 134 | TimeInterpolator interpolator = new LinearInterpolator(); 135 | View view = topView; 136 | if (getCurrentScaleByTopView(topView) < 1) { 137 | interpolator = new OvershootInterpolator(); 138 | isChange = true; 139 | } else { 140 | //获取一个镜像 141 | view = getMirror(topView); 142 | isChange = false; 143 | if (topView.getX() > childLeft) { 144 | targtX = Apputils.getScreenWidth(getContext()) * 2; 145 | } else { 146 | targtX = -topView.getWidth() - Apputils.getScreenWidth(getContext()); 147 | } 148 | 149 | 150 | float offsetX = getX() - mDecorView.getX(); 151 | float offsetY = getY() - mDecorView.getY(); 152 | targtY = caculateExitY(childLeft + offsetX, childTop + offsetY, view.getX(), view.getY(), targtX); 153 | } 154 | 155 | 156 | final View finalView = view; 157 | finalView.animate().setDuration(500).x(targtX).y(targtY).setInterpolator(interpolator).setUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 158 | @Override 159 | public void onAnimationUpdate(ValueAnimator animation) { 160 | 161 | if (isChange) { 162 | nextChildScale(getChildCount() - 2, getCurrentScaleByTopView(topView)); 163 | } 164 | } 165 | }).setListener(new AnimatorListenerAdapter() { 166 | 167 | @Override 168 | public void onAnimationEnd(Animator animation) { 169 | super.onAnimationEnd(animation); 170 | if (!isChange) { 171 | mDecorView.removeView(finalView); 172 | } 173 | } 174 | }); 175 | } 176 | 177 | 178 | private ImageView getMirror(View view) { 179 | view.setDrawingCacheEnabled(true); 180 | Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache()); 181 | ImageView img = new ImageView(getContext()); 182 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(bitmap.getWidth(), bitmap.getHeight()); 183 | img.setImageBitmap(bitmap); 184 | view.setDrawingCacheEnabled(false); 185 | int[] imgs = new int[2]; 186 | view.getLocationOnScreen(imgs); 187 | img.setX(imgs[0] - mDecorViewLocation[0]); 188 | img.setY(imgs[1] - mDecorViewLocation[1]); 189 | view.setVisibility(GONE); 190 | delTopView(); 191 | mDecorView.addView(img, params); 192 | return img; 193 | } 194 | 195 | private void delTopView() { 196 | 197 | 198 | if (getAdapter().getItemCount() < 1) { 199 | return; 200 | } 201 | List bodyLists = ((BasicAdapter) getAdapter()).getBodyLists(); 202 | Object o = bodyLists.get(bodyLists.size()- 1); 203 | bodyLists.remove(o); 204 | // bodyLists.add(0,o); 205 | getAdapter().notifyDataSetChanged(); 206 | } 207 | 208 | private float getCurrentScaleByTopView(View topView) { 209 | float h = Math.abs((topView.getX() - childLeft) / topView.getWidth()); 210 | float v = Math.abs((topView.getY() - childTop) / topView.getHeight()); 211 | return (float) (0.9 + Math.max(h, v) / 4); 212 | } 213 | 214 | private void nextChildScale(int index, float scale) { 215 | if (scale >= 1) { 216 | scale = 1; 217 | } 218 | if (index < 0) { 219 | return; 220 | } 221 | View child = getChildAt(index); 222 | 223 | child.setScaleX(scale); 224 | child.setScaleY(scale); 225 | int gap = Apputils.dip2px(getContext(), 5); 226 | float off = child.getHeight() * (1 - scale) / 2; 227 | child.setTranslationY(gap + off); 228 | 229 | if (index < 1) { 230 | return; 231 | } 232 | View thirldView = getChildAt(index - 1); 233 | thirldView.setScaleY(scale - 0.1f); 234 | thirldView.setScaleX(scale - 0.1f); 235 | off = thirldView.getHeight() * (1 - scale + 0.1f) / 2; 236 | thirldView.setTranslationY(off + gap * 2); 237 | } 238 | 239 | 240 | public float getChildLeft() { 241 | return childLeft; 242 | } 243 | 244 | public float getChildTop() { 245 | return childTop; 246 | } 247 | 248 | 249 | } 250 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/RefrushRecycleView.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.Nullable; 5 | import android.util.AttributeSet; 6 | import android.view.ViewGroup; 7 | import android.widget.LinearLayout; 8 | 9 | import com.sang.viewfractory.utils.Apputils; 10 | import com.sang.viewfractory.utils.DeviceUtils; 11 | import com.sang.viewfractory.utils.JLog; 12 | import com.sang.viewfractory.view.RefrushLinearLayout; 13 | 14 | import em.sang.com.allrecycleview.adapter.BasicAdapter; 15 | import em.sang.com.allrecycleview.holder.SimpleHolder; 16 | 17 | 18 | /** 19 | * Description:上拉刷新和下拉加载控件,默认没有上拉加载 20 | *

21 | * Author:桑小年 22 | * Data:2016/12/1 14:42 23 | */ 24 | public class RefrushRecycleView extends BasicRefrushRecycleView { 25 | 26 | @Override 27 | public void setAdapter(Adapter adapter) { 28 | super.setAdapter(adapter); 29 | } 30 | 31 | public RefrushRecycleView(Context context) { 32 | super(context); 33 | 34 | } 35 | 36 | public RefrushRecycleView(Context context, @Nullable AttributeSet attrs) { 37 | super(context, attrs); 38 | 39 | } 40 | 41 | public RefrushRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) { 42 | super(context, attrs, defStyle); 43 | 44 | } 45 | 46 | @Override 47 | protected void initView(Context context, @Nullable AttributeSet attrs, int defStyle) { 48 | super.initView(context, attrs, defStyle); 49 | downY = -1; 50 | topView = new RefrushLinearLayout(context); 51 | boomView = new RefrushLinearLayout(context); 52 | setStyle(style); 53 | mearchTop = Apputils.getWidthAndHeight(topView)[1]; 54 | mearchBoom = Apputils.getWidthAndHeight(boomView)[1]; 55 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 56 | params.height = (int) min; 57 | topView.setLayoutParams(params); 58 | 59 | LinearLayout.LayoutParams boom = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 60 | boom.height = (int) min; 61 | boomView.setLayoutParams(boom); 62 | hasTop = true; 63 | hasBoom = false; 64 | 65 | 66 | } 67 | 68 | 69 | @Override 70 | protected int upChangeStateByHeight(int height) { 71 | int state; 72 | if (height > mearchTop) { 73 | state = LOAD_BEFOR; 74 | } else { 75 | state = LOAD_OVER; 76 | 77 | } 78 | return state; 79 | } 80 | 81 | @Override 82 | protected boolean isDownChangeStateByHeight() { 83 | if (style == STYLE_PULL) { 84 | return super.isDownChangeStateByHeight(); 85 | } else { 86 | return false; 87 | } 88 | } 89 | 90 | private long lastTime; 91 | 92 | @Override 93 | public void onScrolled(int dx, int dy) { 94 | super.onScrolled(dx, dy); 95 | if (downstate != LOADING_DOWN) { 96 | synchronized (RefrushRecycleView.class) { 97 | if (dy > DeviceUtils.getMinTouchSlop(getContext()) && style == STYLE_SLIPE) { 98 | if (!isFirst() && isLast() && downstate != LOADING_DOWN) { 99 | long l = System.currentTimeMillis() - lastTime; 100 | if (l > 1000) { 101 | JLog.i("-------------被叫用了---------------------"); 102 | lastTime = System.currentTimeMillis(); 103 | downRefrushState(LOADING_DOWN); 104 | } 105 | } 106 | } 107 | } 108 | } 109 | } 110 | 111 | 112 | @Override 113 | protected float getDownHeightByState(int upState) { 114 | if (style == STYLE_PULL) { 115 | return super.getDownHeightByState(upState); 116 | } else { 117 | return mearchBoom; 118 | } 119 | } 120 | 121 | @Override 122 | protected int downChangeStateByHeight(int height) { 123 | int state; 124 | if (height > mearchBoom) { 125 | state = LOAD_DOWN_BEFOR; 126 | } else { 127 | state = LOAD_DOWN_OVER; 128 | 129 | } 130 | return state; 131 | } 132 | 133 | @Override 134 | protected int getNextState(int refrush_state) { 135 | int load = refrush_state; 136 | switch (refrush_state) { 137 | case LOAD_DOWN_BEFOR: 138 | if (isNoTouch) { 139 | load = LOADING_DOWN; 140 | } 141 | break; 142 | case LOAD_BEFOR: 143 | if (isNoTouch) { 144 | load = LOADING; 145 | } 146 | break; 147 | case LOAD_SUCCESS: 148 | case LOAD_FAIL: 149 | load = LOAD_OVER; 150 | break; 151 | case LOADING: 152 | case LOADING_DOWN: 153 | case LOAD_OVER: 154 | case LOAD_DOWN_OVER: 155 | break; 156 | 157 | case LOAD_DOWN_SUCCESS: 158 | case LOAD_DOWN_FAIL: 159 | if (style != STYLE_SLIPE) { 160 | load = LOAD_DOWN_OVER; 161 | } 162 | break; 163 | } 164 | return load; 165 | } 166 | 167 | @Override 168 | public void addUpDataItem(Adapter adapter) { 169 | if (adapter instanceof BasicAdapter) { 170 | BasicAdapter basicAdapter = (BasicAdapter) adapter; 171 | if (getHasBoom()) { 172 | basicAdapter.addBoom(new SimpleHolder(boomView)); 173 | } 174 | if (getHasTop()) { 175 | basicAdapter.addTop(new SimpleHolder(topView)); 176 | } 177 | } 178 | } 179 | 180 | 181 | @Override 182 | public boolean canDrag() { 183 | return isLast() || isFirst(); 184 | } 185 | 186 | 187 | } 188 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/adapter/BasicAdapter.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.GridLayoutManager; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.support.v7.widget.StaggeredGridLayoutManager; 7 | import android.view.ViewGroup; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import em.sang.com.allrecycleview.holder.CustomHolder; 13 | import em.sang.com.allrecycleview.holder.CustomPeakHolder; 14 | import em.sang.com.allrecycleview.inter.CustomAdapterListener; 15 | 16 | 17 | /** 18 | * Description: 19 | *

20 | * Author: 桑小年 21 | *

22 | * Data: 2016/11/7 16:43 23 | */ 24 | public class BasicAdapter extends RecyclerView.Adapter { 25 | protected List lists = new ArrayList<>(); 26 | public int itemID; 27 | protected List heards = new ArrayList(); 28 | protected List foots = new ArrayList(); 29 | protected List tops = new ArrayList(); 30 | protected List booms = new ArrayList<>(); 31 | public CustomAdapterListener listener; 32 | 33 | public Context context; 34 | 35 | public static final int BODY = 100000; 36 | public static final int TOP = 100001; 37 | public static final int FOOT = 100002; 38 | 39 | 40 | 41 | 42 | protected BasicAdapter(Context context, List lists, int itemID, CustomAdapterListener listener) { 43 | if (lists != null) { 44 | this.lists = lists; 45 | } 46 | this.itemID = itemID; 47 | this.listener = listener; 48 | this.context = context; 49 | } 50 | 51 | @Override 52 | public int getItemViewType(int position) { 53 | if (listener != null) { 54 | return listener.getItemTypeByPosition(); 55 | } 56 | return 0; 57 | } 58 | 59 | @Override 60 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 61 | CustomHolder holder = null; 62 | if (listener != null) { 63 | holder = listener.getHolderByViewType(context, lists, viewType); 64 | } 65 | return holder; 66 | } 67 | 68 | @Override 69 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 70 | if (listener != null) { 71 | listener.onBindViewHolder(holder, position); 72 | } 73 | } 74 | 75 | @Override 76 | public int getItemCount() { 77 | return lists.size() + heards.size() + foots.size() + tops.size() + booms.size(); 78 | } 79 | 80 | 81 | /** 82 | * 添加头布局 83 | * 84 | * @param heardHolder 头布局的holder 85 | */ 86 | public void addHead(CustomPeakHolder heardHolder) { 87 | heards.add(heardHolder); 88 | } 89 | 90 | /** 91 | * 添加头布局 92 | * 93 | * @param heardHolder 头布局的holder 94 | */ 95 | public void addHead(int index, CustomPeakHolder heardHolder) { 96 | 97 | heards.add(index, heardHolder); 98 | } 99 | 100 | /** 101 | * 添加脚布局 102 | * 103 | * @param footHolder 104 | */ 105 | public void addFoots(CustomPeakHolder footHolder) { 106 | foots.add(footHolder); 107 | } 108 | 109 | /** 110 | * 添加顶部刷新局 111 | * 112 | * @param topHolder 113 | */ 114 | public void addTop(CustomPeakHolder topHolder) { 115 | tops.clear(); 116 | tops.add(topHolder); 117 | } 118 | 119 | 120 | 121 | /** 122 | * 添加顶部刷新局 123 | * 124 | * @param boomHolder 125 | */ 126 | public void addBoom(CustomPeakHolder boomHolder) { 127 | booms.clear(); 128 | booms.add(boomHolder); 129 | } 130 | 131 | 132 | 133 | public void onAttachedToRecyclerView(RecyclerView recyclerView) { 134 | super.onAttachedToRecyclerView(recyclerView); 135 | RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); 136 | if (manager instanceof GridLayoutManager) { 137 | final GridLayoutManager gridManager = ((GridLayoutManager) manager); 138 | gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { 139 | @Override 140 | public int getSpanSize(int position) { 141 | return (isHeader(position) || isFooter(position)) 142 | ? gridManager.getSpanCount() : 1; 143 | } 144 | 145 | 146 | }); 147 | } 148 | } 149 | 150 | @Override 151 | public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { 152 | super.onViewAttachedToWindow(holder); 153 | ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); 154 | if (lp != null 155 | && lp instanceof StaggeredGridLayoutManager.LayoutParams 156 | && (isHeader(holder.getLayoutPosition()) || isFooter(holder.getLayoutPosition()))) { 157 | StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp; 158 | p.setFullSpan(true); 159 | } 160 | } 161 | 162 | 163 | public boolean isFooter(int position) { 164 | return position >= heards.size() + lists.size() + tops.size() && position < tops.size() + heards.size() + lists.size() + foots.size() + booms.size(); 165 | } 166 | 167 | public boolean isHeader(int position) { 168 | return position >= 0 && position < heards.size() + tops.size(); 169 | } 170 | 171 | public List getBodyLists() { 172 | return lists; 173 | } 174 | 175 | public void upData(List list) { 176 | this.lists = list; 177 | notifyDataSetChanged(); 178 | 179 | } 180 | 181 | public List getHeards(){ 182 | return heards; 183 | } 184 | 185 | public List getFoots() { 186 | return foots; 187 | } 188 | 189 | public List getTops() { 190 | return tops; 191 | } 192 | 193 | public List getBooms() { 194 | return booms; 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/adapter/CustomBasicAdapter.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.ViewGroup; 6 | 7 | import java.util.List; 8 | 9 | import em.sang.com.allrecycleview.holder.CustomHolder; 10 | import em.sang.com.allrecycleview.holder.CustomPeakHolder; 11 | import em.sang.com.allrecycleview.inter.DefaultAdapterViewLisenter; 12 | 13 | 14 | /** 15 | * Description: 16 | * 17 | * @Author:桑小年 18 | * @Data:2016/11/7 16:43 19 | */ 20 | public class CustomBasicAdapter extends BasicAdapter { 21 | protected CustomBasicAdapter(Context context, List lists, int itemID, DefaultAdapterViewLisenter lisenter) { 22 | super(context, lists, itemID, lisenter); 23 | } 24 | 25 | @Override 26 | public int getItemViewType(int position) { 27 | if (listener != null) { 28 | return listener.getItemTypeByPosition(); 29 | } 30 | return 0; 31 | } 32 | 33 | @Override 34 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 35 | CustomHolder holder = null; 36 | if (listener!=null) { 37 | holder = listener.getHolderByViewType(context, lists, itemID); 38 | } 39 | return holder; 40 | } 41 | 42 | @Override 43 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 44 | if (position < heards.size()) { 45 | ((CustomHolder) holder).initView(position,lists,context); 46 | 47 | } else if (position < heards.size() + lists.size()) { 48 | ((CustomPeakHolder) holder).initView(position - heards.size(),context); 49 | 50 | } else { 51 | ((CustomPeakHolder) holder).initView(position - heards.size() - lists.size(),context); 52 | } 53 | 54 | } 55 | 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/adapter/DefaultAdapter.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.ViewGroup; 6 | 7 | import java.util.List; 8 | 9 | import em.sang.com.allrecycleview.holder.CustomHolder; 10 | import em.sang.com.allrecycleview.holder.CustomPeakHolder; 11 | import em.sang.com.allrecycleview.inter.DefaultAdapterViewLisenter; 12 | 13 | 14 | /** 15 | * Description:带有头布局的Adapter 16 | * 17 | * @Author:桑小年 18 | * @Data:2016/11/8 9:50 19 | */ 20 | public class DefaultAdapter extends CustomBasicAdapter { 21 | 22 | 23 | public DefaultAdapter(Context context, List lists, int itemID, DefaultAdapterViewLisenter lisenter) { 24 | super(context, lists, itemID, lisenter); 25 | } 26 | 27 | @Override 28 | public int getItemViewType(int position) { 29 | if (position < tops.size()) { 30 | return TOP; 31 | } else if (position < heards.size()+tops.size()) { 32 | return position; 33 | } else if (position < heards.size() + lists.size() + tops.size()) { 34 | return BODY; 35 | } else if (position extends DefaultAdapter { 23 | 24 | private int refrushPosition=0; 25 | 26 | public RefrushAdapter(Context context, List lists, int itemID, DefaultAdapterViewLisenter lisenter) { 27 | super(context, lists, itemID, lisenter); 28 | } 29 | 30 | public void setRefrushPosition(int position){ 31 | this.refrushPosition=position; 32 | } 33 | 34 | @Override 35 | public int getItemViewType(int position) { 36 | if (position == refrushPosition&&tops.size()>0) { 37 | return TOP; 38 | } else if (position < heards.size()+tops.size()) { 39 | if (positionrefrushPosition&&tops.size()>0){ 42 | return position; 43 | }else { 44 | return position; 45 | } 46 | } else if (position < heards.size() + lists.size() + tops.size()) { 47 | return BODY; 48 | } else if (position0) { 61 | id=position; 62 | ((CustomPeakHolder) holder).initView(id, context); 63 | } else if (position < heards.size()+tops.size()) { 64 | id= position-tops.size(); 65 | if (positionrefrushPosition&&tops.size()>0){ 68 | id= position-1; 69 | } 70 | ((CustomPeakHolder) holder).initView(id, context); 71 | } else if (position < heards.size() + lists.size() + tops.size()) { 72 | id=position-heards.size()-tops.size(); 73 | ((CustomHolder) holder).initView(id,lists, context); 74 | } else if (positionrefrushPosition&&tops.size()>0) { 96 | holder = (RecyclerView.ViewHolder) heards.get(viewType - tops.size()); 97 | }else { 98 | holder = (RecyclerView.ViewHolder) heards.get(viewType); 99 | } 100 | } else if (viewType == BODY) { 101 | holder= ((DefaultAdapterViewLisenter) listener).getBodyHolder(context, lists, itemID); 102 | } else if (viewType= childCount)// 如果是最后一列,则不需要绘制右边 126 | return true; 127 | } 128 | } 129 | return false; 130 | } 131 | 132 | private boolean isLastRaw(RecyclerView parent, int pos, int spanCount, 133 | int childCount) { 134 | 135 | LayoutManager layoutManager = parent.getLayoutManager(); 136 | if (layoutManager instanceof GridLayoutManager) { 137 | childCount = childCount - (childCount ) % spanCount; 138 | if (pos >= childCount)// 如果是最后一行,则不需要绘制底部 139 | return true; 140 | } else if (layoutManager instanceof StaggeredGridLayoutManager) { 141 | int orientation = ((StaggeredGridLayoutManager) layoutManager) 142 | .getOrientation(); 143 | // StaggeredGridLayoutManager 且纵向滚动 144 | if (orientation == StaggeredGridLayoutManager.VERTICAL) { 145 | childCount = childCount - childCount % spanCount; 146 | // 如果是最后一行,则不需要绘制底部 147 | if (pos >= childCount) 148 | return true; 149 | } else 150 | // StaggeredGridLayoutManager 且横向滚动 151 | { 152 | // 如果是最后一行,则不需要绘制底部 153 | if ((pos + 1) % spanCount == 0) { 154 | return true; 155 | } 156 | } 157 | } 158 | return false; 159 | } 160 | 161 | @Override 162 | public void getItemOffsets(Rect outRect, int itemPosition, 163 | RecyclerView parent) { 164 | int spanCount = getSpanCount(parent); 165 | int childCount = parent.getAdapter().getItemCount(); 166 | int heardSize = 0; 167 | if (parent.getAdapter() instanceof BasicAdapter) { 168 | BasicAdapter adapter = (BasicAdapter) parent.getAdapter(); 169 | heardSize = adapter.getTops().size() + adapter.getHeards().size(); 170 | } 171 | if (isLastRaw(parent, itemPosition-heardSize, spanCount, childCount))// 如果是最后一行,则不需要绘制底部 172 | { 173 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); 174 | } else if (isLastColum(parent, itemPosition-heardSize, spanCount, childCount))// 如果是最后一列,则不需要绘制右边 175 | { 176 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); 177 | } else { 178 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 179 | mDivider.getIntrinsicHeight()); 180 | } 181 | } 182 | } -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/cutline/RecycleViewDivider.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.cutline; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.Rect; 8 | import android.graphics.drawable.Drawable; 9 | import android.support.v4.content.ContextCompat; 10 | import android.support.v7.widget.LinearLayoutManager; 11 | import android.support.v7.widget.RecyclerView; 12 | import android.view.View; 13 | 14 | public class RecycleViewDivider extends RecyclerView.ItemDecoration { 15 | 16 | private Paint mPaint; 17 | private Drawable mDivider; 18 | private int mDividerHeight = 2;//分割线高度,默认为1px 19 | private int mOrientation;//列表的方向:LinearLayoutManager.VERTICAL或LinearLayoutManager.HORIZONTAL 20 | private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; 21 | 22 | /** 23 | * 默认分割线:高度为2px,颜色为灰色 24 | * 25 | * @param context 26 | * @param orientation 列表方向 27 | */ 28 | public RecycleViewDivider(Context context, int orientation) { 29 | if (orientation != LinearLayoutManager.VERTICAL && orientation != LinearLayoutManager.HORIZONTAL) { 30 | throw new IllegalArgumentException("请输入正确的参数!"); 31 | } 32 | mOrientation = orientation; 33 | 34 | final TypedArray a = context.obtainStyledAttributes(ATTRS); 35 | mDivider = a.getDrawable(0); 36 | 37 | a.recycle(); 38 | } 39 | 40 | /** 41 | * 自定义分割线 42 | * 43 | * @param context 44 | * @param orientation 列表方向 45 | * @param drawableId 分割线图片 46 | */ 47 | public RecycleViewDivider(Context context, int orientation, int drawableId) { 48 | this(context, orientation); 49 | mDivider = ContextCompat.getDrawable(context, drawableId); 50 | 51 | mDividerHeight = mDivider.getIntrinsicHeight(); 52 | } 53 | 54 | /** 55 | * 自定义分割线 56 | * 57 | * @param context 58 | * @param orientation 列表方向 59 | * @param dividerHeight 分割线高度 60 | * @param dividerColor 分割线颜色 61 | */ 62 | public RecycleViewDivider(Context context, int orientation, int dividerHeight, int dividerColor) { 63 | this(context, orientation); 64 | mDividerHeight = dividerHeight; 65 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 66 | mPaint.setColor(dividerColor); 67 | mPaint.setStyle(Paint.Style.FILL); 68 | } 69 | 70 | 71 | //获取分割线尺寸 72 | @Override 73 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 74 | super.getItemOffsets(outRect, view, parent, state); 75 | outRect.set(0, 0, 0, mDividerHeight); 76 | } 77 | 78 | //绘制分割线 79 | @Override 80 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 81 | super.onDraw(c, parent, state); 82 | 83 | 84 | if (mOrientation == LinearLayoutManager.VERTICAL) { 85 | drawVertical(c, parent); 86 | } else { 87 | drawHorizontal(c, parent); 88 | } 89 | } 90 | 91 | //绘制横向 item 分割线 92 | private void drawHorizontal(Canvas canvas, RecyclerView parent) { 93 | final int left = parent.getPaddingLeft(); 94 | final int right = parent.getMeasuredWidth() - parent.getPaddingRight(); 95 | final int childSize = parent.getChildCount(); 96 | for (int i = 0; i < childSize; i++) { 97 | final View child = parent.getChildAt(i); 98 | RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams(); 99 | final int top = child.getBottom() + layoutParams.bottomMargin; 100 | final int bottom = top + mDividerHeight; 101 | if (mDivider != null) { 102 | mDivider.setBounds(left, top, right, bottom); 103 | mDivider.draw(canvas); 104 | } 105 | if (mPaint != null) { 106 | canvas.drawRect(left, top, right, bottom, mPaint); 107 | } 108 | } 109 | } 110 | 111 | //绘制纵向 item 分割线 112 | private void drawVertical(Canvas canvas, RecyclerView parent) { 113 | final int top = parent.getPaddingTop(); 114 | final int bottom = parent.getMeasuredHeight() - parent.getPaddingBottom(); 115 | final int childSize = parent.getChildCount(); 116 | for (int i = 0; i < childSize; i++) { 117 | final View child = parent.getChildAt(i); 118 | RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) child.getLayoutParams(); 119 | final int left = child.getRight() + layoutParams.rightMargin; 120 | final int right = left + mDividerHeight; 121 | if (mDivider != null) { 122 | mDivider.setBounds(left, top, right, bottom); 123 | mDivider.draw(canvas); 124 | } 125 | if (mPaint != null) { 126 | canvas.drawRect(left, top, right, bottom, mPaint); 127 | } 128 | } 129 | } 130 | } -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/holder/CustomHolder.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.holder; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | 8 | import java.util.List; 9 | 10 | import em.sang.com.allrecycleview.listener.OnToolsItemClickListener; 11 | 12 | /** 13 | * Description: 14 | * 15 | * @Author:桑小年 16 | * @Data:2016/11/7 16:46 17 | */ 18 | public class CustomHolder extends RecyclerView.ViewHolder { 19 | 20 | 21 | public Context context; 22 | public View itemView; 23 | protected List datas; 24 | protected int itemID; 25 | public OnToolsItemClickListener listener; 26 | public void setOnTOnToolsItemClickListener(OnToolsItemClickListener listener){ 27 | this.listener=listener; 28 | } 29 | 30 | 31 | public CustomHolder(View itemView) { 32 | super(itemView); 33 | } 34 | 35 | public CustomHolder(List datas, View itemView ){ 36 | this(itemView); 37 | this.datas = datas; 38 | this.itemView = itemView; 39 | 40 | } 41 | 42 | public CustomHolder(Context context, List lists, int itemID) { 43 | this(lists,LayoutInflater.from(context).inflate(itemID,null)); 44 | this.context =context; 45 | this.itemID=itemID; 46 | } 47 | 48 | /** 49 | * body中使用的初始化方法 50 | * @param position 51 | * @param datas 52 | * @param context 53 | */ 54 | public void initView(int position,List datas,Context context) { 55 | 56 | } 57 | 58 | 59 | 60 | 61 | /** 62 | * 获取跟布局 63 | * @return 64 | */ 65 | public View getItemView(){ 66 | return itemView; 67 | } 68 | 69 | public Context getContext() { 70 | return context; 71 | } 72 | 73 | public List getDatas() { 74 | return datas; 75 | } 76 | 77 | public int getItemID() { 78 | return itemID; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/holder/CustomPeakHolder.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.holder; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Description:头布局和叫布局使用的类 12 | * 13 | * @Author:桑小年 14 | * @Data:2016/11/7 16:46 15 | */ 16 | public class CustomPeakHolder extends CustomHolder { 17 | 18 | 19 | public CustomPeakHolder(View itemView) { 20 | super(itemView); 21 | } 22 | 23 | public CustomPeakHolder(List datas, View itemView) { 24 | super(datas, itemView); 25 | } 26 | 27 | public CustomPeakHolder(Context context, List lists, int itemID) { 28 | super(context, lists, itemID); 29 | } 30 | 31 | /** 32 | * 叫布局和头布局使用的方法 33 | * @param position 34 | * @param context 35 | */ 36 | public void initView(int position,Context context) { 37 | 38 | } 39 | 40 | 41 | /** 42 | * 获取跟布局 43 | * @return 44 | */ 45 | public View getItemView(){ 46 | return itemView; 47 | } 48 | 49 | 50 | 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/holder/FootHolder.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.holder; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Description: 10 | * 11 | * @Author:桑小年 12 | * @Data:2016/11/8 11:58 13 | */ 14 | public class FootHolder extends CustomPeakHolder { 15 | 16 | 17 | public FootHolder(View itemView) { 18 | super(itemView); 19 | } 20 | 21 | public FootHolder(List datas, View itemView) { 22 | super(datas, itemView); 23 | } 24 | 25 | public FootHolder(Context context, List lists, int itemID) { 26 | super(context, lists, itemID); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/holder/HeardHolder.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.holder; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | 6 | import java.util.List; 7 | 8 | import static android.R.attr.data; 9 | 10 | /** 11 | * Description: 12 | * 13 | * @Author:桑小年 14 | * @Data:2016/11/8 11:58 15 | */ 16 | public class HeardHolder extends CustomPeakHolder { 17 | public HeardHolder(View itemView) { 18 | super(itemView); 19 | } 20 | 21 | public HeardHolder(List datas, View itemView) { 22 | super(datas, itemView); 23 | } 24 | 25 | public HeardHolder(Context context, List lists, int itemID) { 26 | super(context, lists, itemID); 27 | } 28 | 29 | } 30 | 31 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/holder/SimpleHolder.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.holder; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | 7 | /** 8 | * Description: 9 | * 10 | * @Author:桑小年 11 | * @Data:2016/12/2 11:46 12 | */ 13 | public class SimpleHolder extends CustomPeakHolder { 14 | public SimpleHolder(View itemView) { 15 | super(itemView); 16 | } 17 | public SimpleHolder(Context context,int itemId) { 18 | super(LayoutInflater.from(context).inflate(itemId,null)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/inter/BodyInitListener.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.inter; 2 | 3 | import android.content.Context; 4 | 5 | import java.util.List; 6 | 7 | import em.sang.com.allrecycleview.holder.CustomHolder; 8 | 9 | public interface BodyInitListener { 10 | 11 | public CustomHolder getHolderByViewType(Context context, List lists, int itemID); 12 | } 13 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/inter/CustomAdapterListener.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.inter; 2 | 3 | 4 | import android.content.Context; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.View; 7 | 8 | import java.util.List; 9 | 10 | import em.sang.com.allrecycleview.holder.CustomHolder; 11 | 12 | public interface CustomAdapterListener extends BodyInitListener{ 13 | 14 | void initView(T data,View itemView); 15 | 16 | /** 17 | * 根据position获取itemType 18 | * @return itemType 19 | */ 20 | int getItemTypeByPosition(); 21 | 22 | /** 23 | * 根据类型获取相应的ViewHolder 24 | * @param context 上下文 25 | * @param lists 数据集合 26 | * @param itemID 布局ID 27 | * @return 28 | */ 29 | CustomHolder getHolderByViewType(Context context, List lists, int itemID); 30 | 31 | /** 32 | * 绑定holder 33 | * @param holder 34 | * @param position 35 | */ 36 | void onBindViewHolder(RecyclerView.ViewHolder holder, int position); 37 | } 38 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/inter/DefaultAdapterViewLisenter.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.inter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.View; 6 | 7 | import java.util.List; 8 | 9 | import em.sang.com.allrecycleview.holder.CustomHolder; 10 | import em.sang.com.allrecycleview.holder.CustomPeakHolder; 11 | 12 | /** 13 | * Description: 14 | * 15 | * @Author:桑小年 16 | * @Data:2016/11/8 16:10 17 | */ 18 | public class DefaultAdapterViewLisenter implements CustomAdapterListener { 19 | @Override 20 | public void initView(T data, View itemView) { 21 | 22 | } 23 | 24 | @Override 25 | public int getItemTypeByPosition() { 26 | return 0; 27 | } 28 | 29 | 30 | @Override 31 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 32 | 33 | } 34 | 35 | /** 36 | * 获取头布局holder 37 | * @param context 上下文 38 | * @param position 位置 39 | * @return holder 40 | */ 41 | public CustomPeakHolder getHeardHolder(Context context, int position){return null;} 42 | /** 43 | * 获取普通布局holder 44 | * @param context 上下文 45 | * @param lists 数据 46 | * @param itemID 布局ID 47 | * @return holder 48 | */ 49 | public CustomHolder getBodyHolder(Context context, List lists, int itemID){return null;} 50 | /** 51 | * 获取脚局holder 52 | * @param context 上下文 53 | * @param position 脚布局位置,从0开始 54 | * @return holder 55 | */ 56 | public CustomHolder getFootdHolder(Context context, int position){return null;} 57 | 58 | @Override 59 | public CustomHolder getHolderByViewType(Context context, List lists, int itemID) { 60 | return null; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/inter/DefaultRefrushListener.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.inter; 2 | 3 | /** 4 | * Description: 5 | * 6 | * @Author:桑小年 7 | * @Data:2016/12/6 16:55 8 | */ 9 | public class DefaultRefrushListener implements RefrushListener { 10 | @Override 11 | public void onLoading() { 12 | } 13 | 14 | @Override 15 | public void onLoadDowning() { 16 | 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/inter/OverlapListener.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.inter; 2 | 3 | 4 | public interface OverlapListener { 5 | 6 | void remove(); 7 | } 8 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/inter/RefrushListener.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.inter; 2 | 3 | 4 | public interface RefrushListener { 5 | /** 6 | * 下拉刷新 7 | */ 8 | void onLoading(); 9 | 10 | /** 11 | * 下拉加载 12 | */ 13 | void onLoadDowning(); 14 | } 15 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/layoutmanager/OverlapManager.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.layoutmanager; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.LinearLayoutManager; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | 9 | import com.sang.viewfractory.utils.Apputils; 10 | 11 | 12 | /** 13 | * Description: 14 | * 15 | * @ Author :桑小年 16 | * @ Data :2016/12/22 15:52 17 | */ 18 | public class OverlapManager extends LinearLayoutManager { 19 | 20 | private int offSet; 21 | 22 | public OverlapManager(Context context) { 23 | super(context); 24 | initView(context); 25 | } 26 | 27 | public OverlapManager(Context context, int orientation, boolean reverseLayout) { 28 | super(context, orientation, reverseLayout); 29 | initView(context); 30 | } 31 | 32 | public OverlapManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 33 | super(context, attrs, defStyleAttr, defStyleRes); 34 | initView(context); 35 | } 36 | 37 | private void initView(Context context) { 38 | offSet = Apputils.dip2px(context, 5); 39 | } 40 | 41 | @Override 42 | public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { 43 | super.onLayoutChildren(recycler, state); 44 | detachAndScrapAttachedViews(recycler); 45 | int childCount = getItemCount(); 46 | for (int i = 0; i < childCount; i++) { 47 | View child = recycler.getViewForPosition(i); 48 | measureChildWithMargins(child, 0, 0); 49 | int childWidth = getDecoratedMeasuredWidth(child); 50 | int childHeight = getDecoratedMeasuredHeight(child); 51 | int startX = (getWidth() - childWidth) / 2; 52 | int startY = (getHeight() - childHeight) / 2; 53 | 54 | if (i < childCount - 1) { 55 | child.setScaleX(0.8f); 56 | child.setScaleY(0.8f); 57 | } 58 | addView(child); 59 | layoutDecorated(child, startX, startY, startX + childWidth, startY + childHeight); 60 | if (i == childCount - 1) { 61 | child.setTranslationY(0); 62 | } else if (i == childCount - 2) { 63 | child.setScaleX(0.9f); 64 | child.setScaleY(0.9f); 65 | child.setTranslationY(childHeight * 0.1f / 2 + offSet); 66 | } else if (i == childCount - 3) { 67 | child.setScaleX(0.8f); 68 | child.setScaleY(0.8f); 69 | child.setTranslationY(childHeight * 0.2f / 2 + offSet * 2); 70 | } 71 | 72 | 73 | } 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /allrecycleview/src/main/java/em/sang/com/allrecycleview/listener/OnToolsItemClickListener.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview.listener; 2 | 3 | 4 | public interface OnToolsItemClickListener { 5 | 6 | void onItemClick(int position, T item); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /allrecycleview/src/main/res/layout/heard_refrush.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /allrecycleview/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AllRecycleView 3 | 没有更多数据了 4 | 没有数据 5 | 6 | -------------------------------------------------------------------------------- /allrecycleview/src/test/java/em/sang/com/allrecycleview/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package em.sang.com.allrecycleview; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() throws Exception { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | defaultConfig { 7 | applicationId "com.xiaonian.sang.alibehaver" 8 | minSdkVersion 21 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support:appcompat-v7:25.3.1' 28 | compile 'com.android.support.constraint:constraint-layout:1.0.1' 29 | testCompile 'junit:junit:4.12' 30 | compile 'com.android.support:design:26.0.0-alpha1' 31 | compile project(':allrecycleview') 32 | } 33 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\workSoft\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/xiaonian/sang/alibehaver/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.xiaonian.sang.alibehaver; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.xiaonian.sang.alibehaver", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaonian/sang/alibehaver/CustomBehavior.java: -------------------------------------------------------------------------------- 1 | package com.xiaonian.sang.alibehaver; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.content.Context; 5 | import android.support.design.widget.CoordinatorLayout; 6 | import android.support.v4.view.ViewCompat; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.RelativeLayout; 11 | 12 | 13 | import java.lang.ref.WeakReference; 14 | 15 | import em.sang.com.allrecycleview.BasicRefrushRecycleView; 16 | 17 | /** 18 | * Description:用于首页,模仿支付宝效果 19 | * 20 | * @Author:桑小年 21 | * @Data:2016/12/28 11:53 22 | */ 23 | public class CustomBehavior extends CoordinatorLayout.Behavior { 24 | 25 | 26 | private WeakReference dependentView; 27 | private WeakReference childeView; 28 | private boolean isScroll; 29 | private boolean isExpand; 30 | private int heardSize = -1; 31 | private int minHeard = -1; 32 | 33 | public CustomBehavior(Context context, AttributeSet attrs) { 34 | super(context, attrs); 35 | 36 | } 37 | 38 | @Override 39 | public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { 40 | if (child != null) { 41 | childeView = new WeakReference(child); 42 | } 43 | if (dependency != null && dependency instanceof RelativeLayout) { 44 | dependentView = new WeakReference<>(dependency); 45 | return true; 46 | } 47 | return super.layoutDependsOn(parent, child, dependency); 48 | } 49 | 50 | @Override 51 | public boolean onLayoutChild(CoordinatorLayout parent, View child, int layoutDirection) { 52 | 53 | 54 | child.layout(0, 0, parent.getWidth(), (parent.getHeight() - dependentView.get().getHeight())); 55 | if (heardSize == -1) { 56 | heardSize = dependentView.get().getHeight(); 57 | minHeard = dependentView.get().findViewById(R.id.rl_icon).getHeight(); 58 | child.setTranslationY(heardSize); 59 | } 60 | 61 | return true; 62 | 63 | } 64 | 65 | @Override 66 | public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { 67 | View view = dependentView.get(); 68 | 69 | float translationY = child.getTranslationY(); 70 | 71 | float min = minHeard*1.0f/heardSize; 72 | float pro = (translationY) / heardSize; 73 | View child1 = view.findViewById(R.id.ll); 74 | child1.setPivotY(0); 75 | child1.setPivotX(0); 76 | View titleView = dependentView.get().findViewById(R.id.rl_icon); 77 | titleView.setPivotY(0); 78 | titleView.setPivotX(0); 79 | titleView.setAlpha(1 - pro); 80 | if (pro<=min+0.1){ 81 | titleView.setAlpha(1); 82 | } 83 | if (pro>0.95){ 84 | titleView.setVisibility(View.GONE); 85 | }else { 86 | titleView.setVisibility(View.VISIBLE); 87 | 88 | } 89 | if (pro >= min && pro <= 1) { 90 | 91 | child1.setAlpha(pro); 92 | if (pro < 0.7) { 93 | child1.setVisibility(View.GONE); 94 | } else { 95 | child1.setVisibility(View.VISIBLE); 96 | } 97 | 98 | return true; 99 | } 100 | 101 | return super.onDependentViewChanged(parent, child, dependency); 102 | } 103 | 104 | @Override 105 | public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { 106 | 107 | return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL; 108 | } 109 | 110 | @Override 111 | public void onNestedScrollAccepted(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { 112 | clearAnimotor(); 113 | isScroll = false; 114 | } 115 | 116 | @Override 117 | public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { 118 | View view = dependentView.get(); 119 | ViewGroup.LayoutParams params = view.getLayoutParams(); 120 | int height = (int) child.getTranslationY(); 121 | if (dy > 0 && height > minHeard) { 122 | if (height <= heardSize) { 123 | int h = height - dy; 124 | int H = (h < minHeard) ? minHeard : h; 125 | params.height = H; 126 | view.setLayoutParams(params); 127 | child.setTranslationY(H); 128 | consumed[1] = dy; 129 | } 130 | 131 | 132 | } 133 | 134 | 135 | } 136 | 137 | @Override 138 | public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { 139 | if (dyUnconsumed > 0) { 140 | return; 141 | } 142 | View view = dependentView.get(); 143 | ViewGroup.LayoutParams params = view.getLayoutParams(); 144 | int height = (int) child.getTranslationY(); 145 | if (dyUnconsumed < 0&¶ms!=null) { 146 | int h = height - dyUnconsumed; 147 | 148 | if (h >= 0 &&h<= heardSize) { 149 | params.height = h; 150 | view.setLayoutParams(params); 151 | child.setTranslationY(h); 152 | if (child instanceof BasicRefrushRecycleView){ 153 | BasicRefrushRecycleView recycleView = (BasicRefrushRecycleView) child; 154 | recycleView.setViewHeight(recycleView.getEndView(),0); 155 | } 156 | } 157 | 158 | } 159 | } 160 | 161 | @Override 162 | public boolean onNestedPreFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY) { 163 | return onStopDrag(child, velocityY); 164 | 165 | } 166 | 167 | private boolean onStopDrag(View child, float velocityY) { 168 | int height = dependentView.get().getHeight(); 169 | if (height>minHeard){ 170 | return true; 171 | }else { 172 | return false; 173 | } 174 | 175 | } 176 | 177 | 178 | @Override 179 | public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed) { 180 | return true; 181 | } 182 | 183 | 184 | @Override 185 | public void onStopNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target) { 186 | 187 | int height = dependentView.get().getHeight(); 188 | float translationY = childeView.get().getTranslationY(); 189 | if (translationY > height) { 190 | isExpand = true; 191 | } else { 192 | isExpand = false; 193 | } 194 | 195 | if (isExpand) { 196 | float pro = ((translationY - height) * 1.0f / heardSize); 197 | creatExpendAnimator(translationY, height, (int) (500 * pro)); 198 | } 199 | 200 | 201 | if (!isScroll && height > minHeard && height < heardSize) { 202 | childeView.get().setScrollY(0); 203 | if (height < 0.7 * heardSize) {//上滑 204 | float pro = (height - minHeard) * 1.0f / (heardSize - minHeard); 205 | creatAnimation(height, minHeard, (int) (500 * pro)); 206 | } else {//下滑 207 | float pro = (heardSize - height) * 1.0f / (heardSize - minHeard); 208 | creatAnimation(height, heardSize, (int) (500 * pro)); 209 | } 210 | isScroll = true; 211 | } 212 | 213 | 214 | } 215 | 216 | 217 | private ValueAnimator animator; 218 | 219 | private void creatAnimation(float start, float end, int duration) { 220 | clearAnimotor(); 221 | animator = ValueAnimator.ofFloat(start, end); 222 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 223 | @Override 224 | public void onAnimationUpdate(ValueAnimator animation) { 225 | float value = (float) animation.getAnimatedValue(); 226 | View view = dependentView.get(); 227 | ViewGroup.LayoutParams params = view.getLayoutParams(); 228 | params.height = (int) value; 229 | view.setLayoutParams(params); 230 | childeView.get().setTranslationY(value); 231 | 232 | } 233 | }); 234 | animator.setDuration(duration); 235 | animator.start(); 236 | 237 | 238 | } 239 | 240 | private void creatExpendAnimator(float start, float end, int duration) { 241 | clearAnimotor(); 242 | animator = ValueAnimator.ofFloat(start, end); 243 | animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 244 | @Override 245 | public void onAnimationUpdate(ValueAnimator animation) { 246 | float value = (float) animation.getAnimatedValue(); 247 | // View view = dependentView.get(); 248 | // ViewGroup.LayoutParams params = view.getLayoutParams(); 249 | // params.height = (int) value; 250 | // view.setLayoutParams(params); 251 | childeView.get().setTranslationY(value); 252 | 253 | } 254 | }); 255 | animator.setDuration(duration); 256 | animator.start(); 257 | } 258 | 259 | 260 | private void clearAnimotor() { 261 | if (animator != null) { 262 | animator.cancel(); 263 | } 264 | 265 | 266 | isScroll = false; 267 | } 268 | 269 | } 270 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaonian/sang/alibehaver/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.xiaonian.sang.alibehaver; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.os.SystemClock; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.os.Bundle; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.widget.TextView; 10 | 11 | import com.sang.viewfractory.utils.ToastUtil; 12 | import com.xiaonian.sang.alibehaver.bean.GrideBean; 13 | import com.xiaonian.sang.alibehaver.holder.GrideHolder; 14 | import com.xiaonian.sang.alibehaver.holder.HomeCarouselHolder; 15 | import com.xiaonian.sang.alibehaver.holder.ItemHolder; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | import em.sang.com.allrecycleview.RefrushRecycleView; 21 | import em.sang.com.allrecycleview.adapter.RefrushAdapter; 22 | import em.sang.com.allrecycleview.holder.CustomHolder; 23 | import em.sang.com.allrecycleview.inter.DefaultAdapterViewLisenter; 24 | import em.sang.com.allrecycleview.inter.DefaultRefrushListener; 25 | import em.sang.com.allrecycleview.listener.OnToolsItemClickListener; 26 | 27 | import static android.drm.DrmStore.Playback.STOP; 28 | import static java.lang.reflect.Modifier.NATIVE; 29 | 30 | public class MainActivity extends AppCompatActivity implements OnToolsItemClickListener { 31 | 32 | private RefrushRecycleView refrushRecycleView; 33 | private RefrushAdapter adapter; 34 | private List lists; 35 | private GrideHolder holder_up; 36 | private HomeCarouselHolder carouselHolder; 37 | 38 | @Override 39 | protected void onCreate(Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | setContentView(R.layout.activity_main); 42 | ToastUtil.init(this); 43 | initView(); 44 | } 45 | 46 | private void initView() { 47 | refrushRecycleView = (RefrushRecycleView) findViewById(R.id.rc_home); 48 | lists=new ArrayList<>(); 49 | for (int i = 0; i < 20; i++) { 50 | lists.add("ITEM"+i); 51 | } 52 | 53 | adapter = new RefrushAdapter<>(this, lists, R.layout.item, new DefaultAdapterViewLisenter() { 54 | @Override 55 | public CustomHolder getBodyHolder(Context context, List lists, int itemID) { 56 | return new ItemHolder( context, lists, itemID); 57 | } 58 | }); 59 | 60 | 61 | //显示下拉刷新 62 | refrushRecycleView.setHasTop(true); 63 | refrushRecycleView.setRefrushListener(new DefaultRefrushListener() { 64 | @Override 65 | public void onLoading() { 66 | super.onLoading(); 67 | new Thread(new Runnable() { 68 | @Override 69 | public void run() { 70 | SystemClock.sleep(1000); 71 | refrushRecycleView.post(new Runnable() { 72 | @Override 73 | public void run() { 74 | refrushRecycleView.loadSuccess(); 75 | } 76 | }); 77 | 78 | } 79 | }).start(); 80 | 81 | } 82 | }); 83 | /** 84 | * 设置下拉刷新位置 85 | */ 86 | adapter.setRefrushPosition(1); 87 | 88 | //上侧九宫格 89 | 90 | List UP = new ArrayList<>(); 91 | UP.add(new GrideBean(getString(R.string.phone), R.mipmap.phone_recharge)); 92 | UP.add(new GrideBean(getString(R.string.life_recharge), R.mipmap.life_recharge)); 93 | UP.add(new GrideBean(getString(R.string.traffic), R.mipmap.phone_recharge)); 94 | UP.add(new GrideBean(getString(R.string.tick), R.mipmap.life_recharge)); 95 | UP.add(new GrideBean(getString(R.string.game_recharge), R.mipmap.phone_recharge)); 96 | UP.add(new GrideBean(getString(R.string.gas_recharge), R.mipmap.life_recharge)); 97 | UP.add(new GrideBean(getString(R.string.lottery), R.mipmap.phone_recharge)); 98 | UP.add(new GrideBean(getString(R.string.gongyi), R.mipmap.life_recharge)); 99 | UP.add(new GrideBean(getString(R.string.share_media), R.mipmap.phone_recharge)); 100 | UP.add(new GrideBean(getString(R.string.credit_payment), R.mipmap.life_recharge)); 101 | UP.add(new GrideBean(getString(R.string.train), R.mipmap.phone_recharge)); 102 | 103 | holder_up = new GrideHolder(this, UP, R.layout.item); 104 | holder_up.setOnTOnToolsItemClickListener(this); 105 | adapter.addHead(holder_up); 106 | 107 | 108 | List list = new ArrayList<>(); 109 | list.add(new GrideBean("", R.mipmap.home_banner1)); 110 | list.add(new GrideBean("", R.mipmap.home_banner2)); 111 | list.add(new GrideBean("", R.mipmap.home_banner3)); 112 | list.add(new GrideBean("", R.mipmap.home_banner4)); 113 | list.add(new GrideBean("", R.mipmap.home_banner5)); 114 | 115 | //中间广告条 116 | carouselHolder = new HomeCarouselHolder(this, list, R.layout.item_home_carousel); 117 | adapter.addHead(carouselHolder); 118 | 119 | 120 | LinearLayoutManager manager = new LinearLayoutManager(this); 121 | manager.setOrientation(LinearLayoutManager.VERTICAL); 122 | refrushRecycleView.setLayoutManager(manager); 123 | refrushRecycleView.setAdapter(adapter); 124 | } 125 | 126 | 127 | @Override 128 | public void onItemClick(int position, GrideBean item) { 129 | ToastUtil.showTextToast(item.title); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaonian/sang/alibehaver/bean/GrideBean.java: -------------------------------------------------------------------------------- 1 | package com.xiaonian.sang.alibehaver.bean; 2 | 3 | 4 | /** 5 | * 是时候撸点真正的代码了!!! 6 | *

7 | * 创建人:桑小年 8 | * 日期: 2017/6/2. 9 | *

10 | * 功能描述:用于在九宫格时候使用的bean,两个变量分别代表文字和图片 11 | */ 12 | 13 | public class GrideBean { 14 | public String title; 15 | public int imgId; 16 | 17 | 18 | public GrideBean(String title, int imgId) { 19 | this.title = title; 20 | this.imgId = imgId; 21 | } 22 | 23 | 24 | public GrideBean() { 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaonian/sang/alibehaver/holder/GrideHolder.java: -------------------------------------------------------------------------------- 1 | package com.xiaonian.sang.alibehaver.holder; 2 | 3 | import android.content.Context; 4 | import android.graphics.drawable.Drawable; 5 | import android.support.v4.content.ContextCompat; 6 | import android.support.v7.widget.GridLayoutManager; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.view.View; 10 | import android.widget.TextView; 11 | 12 | 13 | import com.xiaonian.sang.alibehaver.R; 14 | import com.xiaonian.sang.alibehaver.bean.GrideBean; 15 | 16 | import java.util.List; 17 | 18 | import em.sang.com.allrecycleview.adapter.DefaultAdapter; 19 | import em.sang.com.allrecycleview.holder.CustomHolder; 20 | import em.sang.com.allrecycleview.holder.HeardHolder; 21 | import em.sang.com.allrecycleview.inter.DefaultAdapterViewLisenter; 22 | 23 | /** 24 | * 是时候撸点真正的代码了!!! 25 | *

26 | * 创建人:桑小年 27 | * 日期: 2017/6/2. 28 | *

29 | * 功能描述: 30 | */ 31 | 32 | public class GrideHolder extends HeardHolder { 33 | 34 | 35 | public GrideHolder(View itemView) { 36 | super(itemView); 37 | } 38 | 39 | public GrideHolder(List datas, View itemView) { 40 | super(datas, itemView); 41 | } 42 | 43 | public GrideHolder(Context context, List lists, int itemID) { 44 | super(context, lists, R.layout.recycleview_gride); 45 | this.itemID = itemID; 46 | } 47 | 48 | int span = 4; 49 | 50 | public void setSpan(int span) { 51 | this.span = span; 52 | } 53 | 54 | @Override 55 | public void initView(int position, Context context) { 56 | RecyclerView view = (RecyclerView) itemView.findViewById(R.id.rc_gv); 57 | GridLayoutManager manager = new GridLayoutManager(context, span); 58 | manager.setOrientation(LinearLayoutManager.VERTICAL); 59 | view.setLayoutManager(manager); 60 | 61 | view.setAdapter(new DefaultAdapter(context, getDatas(), getItemID(), new DefaultAdapterViewLisenter() { 62 | @Override 63 | public CustomHolder getBodyHolder(Context context, List lists, int itemID) { 64 | return new CustomHolder(context, lists, itemID) { 65 | @Override 66 | public void initView(final int position, List datas, Context context) { 67 | final T data = datas.get(position); 68 | initItemView(itemView,data); 69 | itemView.setOnClickListener(new View.OnClickListener() { 70 | @Override 71 | public void onClick(View v) { 72 | if (GrideHolder.this.listener != null) { 73 | GrideHolder.this.listener.onItemClick(position, data); 74 | } 75 | } 76 | }); 77 | } 78 | }; 79 | } 80 | })); 81 | 82 | } 83 | 84 | public void initItemView(View itemView,T data){ 85 | if (data instanceof GrideBean) { 86 | GrideBean bean = (GrideBean) data; 87 | TextView view = (TextView) itemView.findViewById(R.id.tv); 88 | if (bean.title != null) { 89 | view.setText(bean.title); 90 | } 91 | if (bean.imgId > 0) { 92 | Drawable drawable = ContextCompat.getDrawable(context, bean.imgId); 93 | drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight()); 94 | view.setCompoundDrawables(null, drawable, null, null); 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaonian/sang/alibehaver/holder/HomeCarouselHolder.java: -------------------------------------------------------------------------------- 1 | package com.xiaonian.sang.alibehaver.holder; 2 | 3 | import android.content.Context; 4 | import android.os.Handler; 5 | import android.os.Message; 6 | import android.support.v4.view.PagerAdapter; 7 | import android.support.v4.view.ViewPager; 8 | import android.view.MotionEvent; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.ImageView; 12 | import android.widget.LinearLayout; 13 | 14 | import com.sang.viewfractory.utils.Apputils; 15 | import com.xiaonian.sang.alibehaver.R; 16 | import com.xiaonian.sang.alibehaver.bean.GrideBean; 17 | 18 | import java.util.List; 19 | 20 | import em.sang.com.allrecycleview.holder.CustomPeakHolder; 21 | 22 | /** 23 | * Description:首页轮播图 24 | * 25 | * @Author:桑小年 26 | * @Data:2017/1/3 11:17 27 | */ 28 | public class HomeCarouselHolder extends CustomPeakHolder { 29 | 30 | ViewPager vp; 31 | LinearLayout ll_tag; 32 | private Handler handler = new Handler() { 33 | @Override 34 | public void handleMessage(Message msg) { 35 | super.handleMessage(msg); 36 | int count = vp.getCurrentItem() + 1; 37 | if (count >= vp.getAdapter().getCount()) { 38 | count = 0; 39 | } 40 | 41 | try { 42 | vp.setCurrentItem(count); 43 | } catch (Exception e) { 44 | e.printStackTrace(); 45 | } 46 | 47 | handler.sendEmptyMessageDelayed(0, 5 * 1000); 48 | } 49 | }; 50 | 51 | public HomeCarouselHolder(Context context, List lists, int itemID) { 52 | super(context, lists, itemID); 53 | 54 | } 55 | 56 | 57 | 58 | CarousAdapter adapter; 59 | // @Override 60 | public void initView(int position, Context context) { 61 | 62 | if (datas == null || datas.size() == 0) { 63 | return; 64 | } 65 | vp = (ViewPager) itemView.findViewById(R.id.vp_home_carousel); 66 | ll_tag = (LinearLayout) itemView.findViewById(R.id.ll_home_tag); 67 | ll_tag.removeAllViews(); 68 | for (int i = 0; i < datas.size(); i++) { 69 | ImageView tag = new ImageView(context); 70 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 71 | params.setMargins(0, 0, Apputils.dip2px(context, 7), 0); 72 | tag.setLayoutParams(params); 73 | tag.setImageResource(R.drawable.tag_carousel); 74 | ll_tag.addView(tag); 75 | } 76 | adapter = new CarousAdapter(); 77 | vp.setAdapter(adapter); 78 | vp.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { 79 | @Override 80 | public void onPageSelected(int position) { 81 | super.onPageSelected(position); 82 | for (int i = 0; i < ll_tag.getChildCount(); i++) { 83 | if (i == position) { 84 | ll_tag.getChildAt(i).setEnabled(true); 85 | } else { 86 | ll_tag.getChildAt(i).setEnabled(false); 87 | } 88 | 89 | } 90 | } 91 | }); 92 | 93 | vp.setOnTouchListener(new View.OnTouchListener() { 94 | @Override 95 | public boolean onTouch(View v, MotionEvent event) { 96 | switch (event.getAction()) { 97 | case MotionEvent.ACTION_DOWN: 98 | case MotionEvent.ACTION_MOVE: 99 | stopCarousel(); 100 | break; 101 | default: 102 | startCarousel(); 103 | break; 104 | 105 | } 106 | 107 | return false; 108 | } 109 | }); 110 | for (int i = 0; i < ll_tag.getChildCount(); i++) { 111 | if (i == vp.getCurrentItem()) { 112 | ll_tag.getChildAt(i).setEnabled(true); 113 | } else { 114 | ll_tag.getChildAt(i).setEnabled(false); 115 | } 116 | 117 | } 118 | 119 | startCarousel(); 120 | 121 | } 122 | 123 | public void stopCarousel() { 124 | if (handler != null && handler.hasMessages(0)) { 125 | handler.removeMessages(0); 126 | } 127 | } 128 | 129 | public void startCarousel() { 130 | if (handler != null) { 131 | if (handler.hasMessages(0)) { 132 | handler.removeMessages(0); 133 | } 134 | handler.sendEmptyMessageDelayed(0, 1000); 135 | } 136 | } 137 | 138 | 139 | public class CarousAdapter extends PagerAdapter { 140 | 141 | 142 | @Override 143 | public int getCount() { 144 | return datas.size(); 145 | } 146 | 147 | @Override 148 | public boolean isViewFromObject(View view, Object object) { 149 | return view == object; 150 | } 151 | 152 | @Override 153 | public void destroyItem(ViewGroup container, int position, Object object) { 154 | container.removeView((View) object); 155 | } 156 | 157 | @Override 158 | public Object instantiateItem(ViewGroup container, int position) { 159 | ImageView imageView = new ImageView(context); 160 | 161 | imageView.setImageResource(((List)datas).get(position).imgId); 162 | imageView.setScaleType(ImageView.ScaleType.FIT_XY); 163 | ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 164 | 165 | 166 | imageView.setLayoutParams(layoutParams); 167 | // final Set_Item item= (Set_Item) datas.get(position); 168 | // 169 | // if (!TextUtils.isEmpty(item.img_url)) { 170 | // GlideUtils.loadImage(context,imageView,item.img_url); 171 | // }else { 172 | // GlideUtils.loadImage(context,imageView,item.icon_id); 173 | // 174 | // } 175 | imageView.setEnabled(true); 176 | // imageView.setOnClickListener(new View.OnClickListener() { 177 | // @Override 178 | // public void onClick(View v) { 179 | // if (!TextUtils.isEmpty(item.describe)){ 180 | // Intent intent = new Intent(context, ShowDetailActivity.class); 181 | // TranInfor infor = new TranInfor(); 182 | // infor.title = item.title; 183 | // infor.type = 1; 184 | // infor.content = item.describe; 185 | // infor.describe = item.describe; 186 | // intent.putExtra(Config.infors, infor); 187 | // context. startActivity(intent); 188 | // } 189 | // } 190 | // }); 191 | 192 | container.addView(imageView); 193 | return imageView; 194 | } 195 | } 196 | 197 | } 198 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaonian/sang/alibehaver/holder/ItemHolder.java: -------------------------------------------------------------------------------- 1 | package com.xiaonian.sang.alibehaver.holder; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | import com.sang.viewfractory.utils.ToastUtil; 9 | import com.xiaonian.sang.alibehaver.R; 10 | 11 | import java.util.List; 12 | 13 | import em.sang.com.allrecycleview.holder.CustomHolder; 14 | 15 | /** 16 | * 是时候撸点真正的代码了!!! 17 | *

18 | * 创建人:桑小年 19 | * 日期: 2017/7/10. 20 | *

21 | * 功能描述: 22 | */ 23 | 24 | public class ItemHolder extends CustomHolder { 25 | public ItemHolder(View itemView) { 26 | super(itemView); 27 | } 28 | 29 | public ItemHolder(List datas, View itemView) { 30 | super(datas, itemView); 31 | } 32 | 33 | public ItemHolder(Context context, List lists, int itemID) { 34 | super(context, lists, itemID); 35 | } 36 | 37 | @Override 38 | public void initView(int position, List datas, Context context) { 39 | TextView textView = (TextView) itemView.findViewById(R.id.tv); 40 | final String msg = (String) datas.get(position); 41 | textView.setText(msg); 42 | textView.setHeight(300); 43 | textView.setPadding(20, 10, 20, 10); 44 | if (position % 2 == 0) { 45 | textView.setBackgroundColor(Color.parseColor("#abcdef")); 46 | } else { 47 | textView.setBackgroundColor(Color.parseColor("#fedcba")); 48 | } 49 | itemView.setOnClickListener(new View.OnClickListener() { 50 | @Override 51 | public void onClick(View v) { 52 | ToastUtil.showTextToast(msg); 53 | } 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/xiaonian/sang/alibehaver/utils/ToastUtil.java: -------------------------------------------------------------------------------- 1 | package com.xiaonian.sang.alibehaver.utils; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | 7 | public class ToastUtil { 8 | private static Toast toast = null; 9 | private static Context context; 10 | 11 | public static void init(Context cnt){ 12 | context=cnt; 13 | } 14 | public static void showTextToast( String msg) { 15 | if (toast == null) { 16 | toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT); 17 | } else { 18 | toast.setText(msg); 19 | } 20 | toast.show(); 21 | } 22 | public static void showTextToastById( int msg) { 23 | if (toast == null) { 24 | toast = Toast.makeText(context, context.getResources().getString(msg), Toast.LENGTH_SHORT); 25 | } else { 26 | toast.setText(msg); 27 | } 28 | toast.show(); 29 | } 30 | 31 | public static void showTextToast(Context context, String msg) { 32 | if (toast == null) { 33 | toast = Toast.makeText(context, msg, Toast.LENGTH_SHORT); 34 | } else { 35 | toast.setText(msg); 36 | } 37 | toast.show(); 38 | } 39 | public static void showTextToastById(Context context, int msg) { 40 | if (toast == null) { 41 | toast = Toast.makeText(context, context.getResources().getString(msg), Toast.LENGTH_SHORT); 42 | } else { 43 | toast.setText(msg); 44 | } 45 | toast.show(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_color_gay.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tag_carousel.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tag_gray.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/tag_red.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | 14 | 21 | 22 | 31 | 32 | 33 | 45 | 46 | 47 | 53 | 54 | 55 | 56 | 60 | 61 | 69 | 73 |