├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── inspectionProfiles │ ├── Project_Default.xml │ └── profiles_settings.xml ├── misc.xml ├── modules.xml └── runConfigurations.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── leo │ │ └── myactivityoptions │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── leo │ │ │ └── myactivityoptions │ │ │ ├── Comment.java │ │ │ ├── ImgBrowsePagerAdapter.java │ │ │ ├── LargePicFragment.java │ │ │ ├── MainActivity.java │ │ │ ├── RecycleAdapter.java │ │ │ ├── SecondActivity.java │ │ │ ├── SelectActivity.java │ │ │ ├── customview │ │ │ ├── FireflyView.java │ │ │ └── FloatParticle.java │ │ │ ├── likewx │ │ │ ├── LikeWxActivity.java │ │ │ ├── ReAdapter.java │ │ │ └── SimpleControlPanel.java │ │ │ ├── localdemo │ │ │ ├── DividerGridItemDecoration.java │ │ │ ├── GridAdapter.java │ │ │ ├── LocalLargePicFragment.java │ │ │ ├── LocalMainActivity.java │ │ │ ├── LocalSecondActivity.java │ │ │ └── bean │ │ │ │ ├── CanScrollBean.java │ │ │ │ └── LocalBean.java │ │ │ └── utils │ │ │ ├── CircleProgressView.java │ │ │ ├── MyGlideModule.java │ │ │ ├── OkHttpFetcher.java │ │ │ ├── OkHttpGlideUrlLoader.java │ │ │ ├── ProgressInterceptor.java │ │ │ ├── ProgressListener.java │ │ │ ├── ProgressResponseBody.java │ │ │ ├── UIUtil.java │ │ │ └── Utils.java │ └── res │ │ ├── layout │ │ ├── activity_likewx.xml │ │ ├── activity_localmain.xml │ │ ├── activity_main.xml │ │ ├── activity_second.xml │ │ ├── activity_second_local.xml │ │ ├── activity_select.xml │ │ ├── fragment_viewer.xml │ │ ├── item_grid.xml │ │ ├── item_gridview.xml │ │ ├── item_viewpager.xml │ │ └── simple_control_panel.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── home_icon.png │ │ ├── ic_firefly_bg.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── other1.jpg │ │ ├── other2.jpeg │ │ ├── other3.png │ │ ├── other4.jpg │ │ ├── other5.jpg │ │ ├── wangze1.png │ │ ├── wangze10.png │ │ ├── wangze2.png │ │ ├── wangze3.png │ │ ├── wangze4.png │ │ ├── wangze5.png │ │ ├── wangze6.png │ │ ├── wangze7.png │ │ ├── wangze8.png │ │ ├── wangze9.png │ │ └── wutu.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── leo │ └── myactivityoptions │ └── ExampleUnitTest.java ├── atman.txt ├── build.gradle ├── diooto ├── build.gradle ├── diooto.iml ├── proguard-rules.pro └── src │ ├── androidTest │ └── androidTest1.iml │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── net │ │ │ └── moyokoo │ │ │ └── diooto │ │ │ ├── Diooto.java │ │ │ ├── DragDiootoView.java │ │ │ ├── ImageActivity.java │ │ │ ├── ImageFragment.java │ │ │ ├── config │ │ │ ├── ContentViewOriginModel.java │ │ │ └── DiootoConfig.java │ │ │ ├── interfaces │ │ │ ├── CircleIndexIndicator.java │ │ │ ├── CircleIndicator.java │ │ │ ├── DefaultCircleProgress.java │ │ │ ├── DefaultPercentProgress.java │ │ │ ├── IIndicator.java │ │ │ └── IProgress.java │ │ │ └── tools │ │ │ ├── Fucking.java │ │ │ ├── LoadingView.java │ │ │ ├── NoScrollViewPager.java │ │ │ └── Utils.java │ └── res │ │ ├── layout │ │ ├── activity_image.xml │ │ ├── content_item.xml │ │ └── fragment_image.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ ├── ic_gif.png │ │ ├── ic_launcher.png │ │ ├── ic_launcher_leo.png │ │ └── image_error.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── styles.xml │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── ids.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── test1.iml ├── gif动图.gif ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── smallupdateGif1.gif ├── smallupdateGif2.gif ├── 未加载图.gif ├── 正常录制.gif ├── 视频.gif └── 长图.gif /.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 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 共享元素小图到大图浏览,即recycleView到viewPager,pager左右滑动,共享动画item改变: 2 | 3 | - viewPager滑动到当前gridView还没有滑到的item.主动让gridView下滑 4 | - 共享元素滑动改变共享item 5 | - 注意:在网络图片加载中。增加了图片加载进度。解决动画的弊端 6 | 7 | 8 | (为了效果展示压缩了 展示的gif,有点模糊,请下载观看最佳效果) 9 | 10 | 11 | #### 项目演示 12 | |滑动改变item|滑动到列表不可见,列表下滑| 13 | |:---:|:---:| 14 | |![](https://github.com/lihangleo2/mPro/blob/master/smallupdateGif1.gif)|![](https://github.com/lihangleo2/mPro/blob/master/smallupdateGif2.gif)| 15 | 16 | 17 | 18 | [我的博客](https://blog.csdn.net/leol_2/article/details/80198306) 19 | # 20 | # 21 | # 22 | # 23 | ## 第三方实现高仿微信图片拖拽退出 24 | (如果用共享元素也能实现。大致实现原理是,调转一个透明的activity,getLocation记住点击控件的坐标,然后设置给透明activity里控件位置) 25 | - 支持图片缩放,支持gif动图,支持长图,对未加载图片有妥善的处理 26 | - 手指拖拽退出,单击退出 27 | - 支持自定义布局(本文暂且未提供,如需要,作者持续更新) 28 | 29 | ### 在此感谢以下: 30 | [sketch](https://github.com/panpf/sketch) 31 | 32 | [ArtPlayer](https://github.com/maiwenchang/ArtPlayer) 33 | 34 | [特别感谢Diooto,支持原创。笔者只是在其基础上优化了一些,加上自己的理解](https://github.com/moyokoo/Diooto) 35 | 36 | 37 | #### 第三方功能展示 38 | |正常功能展示|视频|长图| 39 | |:---:|:---:|:---:| 40 | |![](https://github.com/lihangleo2/mPro/blob/master/%E6%AD%A3%E5%B8%B8%E5%BD%95%E5%88%B6.gif)|![](https://github.com/lihangleo2/mPro/blob/master/%E8%A7%86%E9%A2%91.gif)|![](https://github.com/lihangleo2/mPro/blob/master/%E9%95%BF%E5%9B%BE.gif) 41 | |gif动图|未加载图| 42 | |![](https://github.com/lihangleo2/mPro/blob/master/gif%E5%8A%A8%E5%9B%BE.gif)|![](https://github.com/lihangleo2/mPro/blob/master/%E6%9C%AA%E5%8A%A0%E8%BD%BD%E5%9B%BE.gif)| 43 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.leo.diootostudy" 7 | minSdkVersion 16 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(include: ['*.jar'], dir: 'libs') 23 | implementation 'com.android.support:appcompat-v7:28.0.0' 24 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 25 | testImplementation 'junit:junit:4.12' 26 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 28 | implementation 'com.android.support:recyclerview-v7:28.0.0' 29 | implementation 'com.github.bumptech.glide:glide:3.7.0' 30 | implementation 'jp.wasabeef:glide-transformations:2.0.0' 31 | implementation 'com.squareup.okhttp3:okhttp:3.8.0' 32 | //eventbus 33 | implementation 'org.greenrobot:eventbus:3.0.0' 34 | 35 | //使用高仿微信加上 36 | implementation project(':diooto') 37 | implementation 'org.salient.artvideoplayer:artplayer-java:0.6.0' 38 | implementation 'org.salient.artvideoplayer:artplayer-ui:0.6.0' 39 | // implementation 'org.salient.artvideoplayer:artplayer-ijk:0.6.0' 40 | // implementation "org.salient.artvideoplayer:artplayer-armv7a:0.6.0" 41 | implementation 'me.panpf:sketch-gif:2.6.2-b1' 42 | implementation 'me.panpf:sketch:2.6.2-b1' 43 | implementation 'com.gyf.barlibrary:barlibrary:2.3.0' 44 | } 45 | -------------------------------------------------------------------------------- /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 C:\Users\Administrator\AppData\Local\Android\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/leo/myactivityoptions/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions; 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.leo.myactivityoptions", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 32 | 33 | 36 | 37 | 40 | 41 | 45 | 46 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/Comment.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions; 2 | 3 | import android.graphics.Bitmap; 4 | 5 | import com.leo.myactivityoptions.localdemo.bean.LocalBean; 6 | 7 | import java.util.ArrayList; 8 | 9 | /** 10 | * Created by Administrator on 2018/4/17. 11 | */ 12 | 13 | public class Comment { 14 | public static Bitmap bitmap; 15 | public static ArrayList urls; 16 | public static ArrayList mipmaps; 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/ImgBrowsePagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions; 2 | 3 | import android.content.Context; 4 | import android.support.v4.view.PagerAdapter; 5 | import android.support.v4.view.ViewCompat; 6 | import android.support.v4.view.ViewPager; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | import android.widget.RelativeLayout; 12 | 13 | import com.bumptech.glide.Glide; 14 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 15 | 16 | import java.util.ArrayList; 17 | 18 | import static com.leo.myactivityoptions.R.id.image_pager; 19 | 20 | public class ImgBrowsePagerAdapter extends PagerAdapter { 21 | 22 | private ArrayList urls; 23 | private LayoutInflater inflater; 24 | private Context context; 25 | private ImageView view; 26 | private int index; 27 | 28 | public ImgBrowsePagerAdapter(Context context, ArrayList urls, int index) { 29 | this.urls = urls; 30 | inflater = LayoutInflater.from(context); 31 | this.context = context; 32 | this.index = index; 33 | } 34 | 35 | 36 | @Override 37 | public int getCount() { // 获得size 38 | return urls.size(); 39 | } 40 | 41 | @Override 42 | public boolean isViewFromObject(View arg0, Object arg1) { 43 | return arg0 == arg1; 44 | } 45 | 46 | 47 | @Override 48 | public void destroyItem(ViewGroup container, int position, Object object) { 49 | ((ViewPager) container).removeView((View) object); 50 | 51 | } 52 | 53 | 54 | @Override 55 | public Object instantiateItem(ViewGroup container, int position) { 56 | view = (ImageView) inflater.inflate(R.layout.item_viewpager, null); 57 | Glide.with(context) 58 | .load(urls.get(position)) 59 | .asBitmap() 60 | .dontAnimate() 61 | .into(view); 62 | ((ViewPager) container).addView(view); 63 | if (index == position) { 64 | ViewCompat.setTransitionName(view, "shareView"); 65 | } 66 | return view; 67 | } 68 | 69 | public ImageView getShareView() { 70 | return view; 71 | } 72 | } -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/LargePicFragment.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.graphics.drawable.Drawable; 6 | import android.os.Build; 7 | import android.os.Bundle; 8 | import android.support.annotation.Nullable; 9 | import android.support.v4.app.Fragment; 10 | import android.util.Log; 11 | import android.view.LayoutInflater; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.view.ViewTreeObserver; 15 | import android.widget.ImageView; 16 | 17 | import com.bumptech.glide.Glide; 18 | import com.bumptech.glide.load.engine.DiskCacheStrategy; 19 | import com.bumptech.glide.load.resource.drawable.GlideDrawable; 20 | import com.bumptech.glide.request.animation.GlideAnimation; 21 | import com.bumptech.glide.request.target.GlideDrawableImageViewTarget; 22 | import com.leo.myactivityoptions.utils.CircleProgressView; 23 | import com.leo.myactivityoptions.utils.ProgressInterceptor; 24 | import com.leo.myactivityoptions.utils.ProgressListener; 25 | 26 | import static com.leo.myactivityoptions.Comment.urls; 27 | 28 | /** 29 | * Created by Mr_Wrong on 15/10/6. 30 | */ 31 | public class LargePicFragment extends Fragment { 32 | private SecondActivity activity; 33 | private int index; 34 | private ImageView image; 35 | CircleProgressView progressView;//进度条 36 | 37 | public static Fragment newFragment(int index) { 38 | Bundle bundle = new Bundle(); 39 | bundle.putInt("index", index); 40 | LargePicFragment fragment = new LargePicFragment(); 41 | fragment.setArguments(bundle); 42 | return fragment; 43 | } 44 | 45 | @Override 46 | public void onAttach(Context context) { 47 | super.onAttach(context); 48 | this.activity = (SecondActivity) context; 49 | 50 | } 51 | 52 | @Override 53 | public void onCreate(@Nullable Bundle savedInstanceState) { 54 | super.onCreate(savedInstanceState); 55 | index = getArguments().getInt("index"); 56 | } 57 | 58 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 59 | @Nullable 60 | @Override 61 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 62 | View view = inflater.inflate(R.layout.fragment_viewer, container, false); 63 | image = view.findViewById(R.id.image); 64 | progressView = view.findViewById(R.id.progressView); 65 | 66 | image.setOnClickListener(new View.OnClickListener() { 67 | @Override 68 | public void onClick(View v) { 69 | activity.supportFinishAfterTransition(); 70 | } 71 | }); 72 | 73 | 74 | view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 75 | @Override 76 | public boolean onPreDraw() { 77 | image.getViewTreeObserver().removeOnPreDrawListener(this); 78 | getActivity().supportStartPostponedEnterTransition(); 79 | return true; 80 | } 81 | }); 82 | return view; 83 | } 84 | 85 | @Override 86 | public void onResume() { 87 | super.onResume(); 88 | 89 | 90 | ProgressInterceptor.addListener(urls.get(index), new ProgressListener() { 91 | @Override 92 | public void onProgress(int progress) { 93 | progressView.setProgress(progress); 94 | } 95 | }); 96 | 97 | Glide.with(activity) 98 | .load(urls.get(index)) 99 | .dontAnimate() 100 | .into(new GlideDrawableImageViewTarget(image) { 101 | @Override 102 | public void onLoadStarted(Drawable placeholder) { 103 | super.onLoadStarted(placeholder); 104 | progressView.setVisibility(View.VISIBLE); 105 | } 106 | 107 | @Override 108 | public void onResourceReady(GlideDrawable resource, GlideAnimation animation) { 109 | super.onResourceReady(resource, animation); 110 | 111 | progressView.setVisibility(View.GONE); 112 | ProgressInterceptor.removeListener(urls.get(index)); 113 | 114 | } 115 | }); 116 | 117 | 118 | } 119 | 120 | public View getSharedElement() { 121 | return image; 122 | } 123 | 124 | 125 | } 126 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions; 2 | 3 | import android.app.SharedElementCallback; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.graphics.Bitmap; 7 | import android.graphics.Rect; 8 | import android.graphics.drawable.BitmapDrawable; 9 | import android.os.Build; 10 | import android.os.Bundle; 11 | import android.support.v4.app.ActivityCompat; 12 | import android.support.v4.app.ActivityOptionsCompat; 13 | import android.support.v4.util.Pair; 14 | import android.support.v7.app.AppCompatActivity; 15 | import android.support.v7.widget.GridLayoutManager; 16 | import android.support.v7.widget.RecyclerView; 17 | import android.view.View; 18 | import android.widget.GridView; 19 | import android.widget.ImageView; 20 | 21 | import com.leo.myactivityoptions.localdemo.LocalMainActivity; 22 | import com.leo.myactivityoptions.localdemo.bean.CanScrollBean; 23 | 24 | import org.greenrobot.eventbus.EventBus; 25 | import org.greenrobot.eventbus.Subscribe; 26 | import org.greenrobot.eventbus.ThreadMode; 27 | 28 | import java.io.BufferedOutputStream; 29 | import java.io.File; 30 | import java.io.FileOutputStream; 31 | import java.io.IOException; 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | import java.util.Map; 35 | 36 | import static android.R.attr.fragment; 37 | 38 | 39 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 40 | 41 | private RecyclerView recyclerView; 42 | private ArrayList urls = new ArrayList<>(); 43 | private RecycleAdapter adapter; 44 | 45 | private Bundle bundle; 46 | 47 | public static void actionStart(Context context) { 48 | Intent intent = new Intent(context, MainActivity.class); 49 | context.startActivity(intent); 50 | } 51 | 52 | @Override 53 | protected void onCreate(Bundle savedInstanceState) { 54 | super.onCreate(savedInstanceState); 55 | setContentView(R.layout.activity_main); 56 | EventBus.getDefault().register(this); 57 | recyclerView = (RecyclerView) findViewById(R.id.recyclerView); 58 | adapter = new RecycleAdapter(this, this); 59 | 60 | urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1542359234325&di=d76577449c1abdf96605a1c720df396c&imgtype=0&src=http%3A%2F%2Fimg.oyksoft.com%2Fpic%2F201811%2F01174018_42743b5b9e.jpg"); 61 | urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1542359234319&di=bf8ddc39d485d99e6b30e7f1b99d6288&imgtype=0&src=http%3A%2F%2Fdingyue.nosdn.127.net%2F0rp1dOH4jTONuOOS1cV9oPt5txrI4cKH1HQXdlPH3Vhdh1541156207273compressflag.jpg"); 62 | urls.add("http://imgsrc.baidu.com/imgad/pic/item/d000baa1cd11728bdf999dd4c2fcc3cec2fd2c8b.jpg"); 63 | urls.add("http://img5.duitang.com/uploads/item/201312/05/20131205171922_dVBte.jpeg"); 64 | urls.add("http://img.pconline.com.cn/images/upload/upc/tx/gamephotolib/1410/27/c0/40170771_1414341013392.jpg"); 65 | urls.add("http://images.17173.com/2014/9yin/2014/03/11/20140311092844886.png"); 66 | urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1542359234318&di=853828b15ad006a7236bbd45f83a0cc9&imgtype=0&src=http%3A%2F%2Fwww.17qq.com%2Fimg_qqtouxiang%2F69016928.jpeg"); 67 | urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1542359234316&di=929439b9620eced0ec426bd0ea9d7867&imgtype=0&src=http%3A%2F%2Fn.sinaimg.cn%2Fsinacn14%2F200%2Fw640h360%2F20181115%2F8510-hnvukff3227000.jpg"); 68 | urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1542359234312&di=e505f530aa6ecbca148af578b6386f34&imgtype=0&src=http%3A%2F%2Fd.ifengimg.com%2Fw600%2Fp0.ifengimg.com%2Fpmop%2F2018%2F0929%2FFE644071FB1F06EBCE8F88EE1D23A753180D375B_size154_w800_h494.jpeg"); 69 | urls.add("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1542359440368&di=ea5554b20ead50972c3e8ed5cf80923d&imgtype=0&src=http%3A%2F%2Fimg.oyksoft.com%2Fpic%2F201810%2F26143721_a1ae9c2e3f.jpg"); 70 | Comment.urls = urls; 71 | 72 | adapter.setDataList(urls); 73 | adapter.setHasStableIds(true); 74 | //初始化布局管理器 75 | final GridLayoutManager lm = new GridLayoutManager(this, 2); 76 | //设置布局管理器 77 | recyclerView.setLayoutManager(lm); 78 | // recyclerView.addItemDecoration(new DividerGridItemDecoration(this)); 79 | recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { 80 | @Override 81 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 82 | outRect.set((int) getResources().getDimension(R.dimen.space_5), (int) getResources().getDimension(R.dimen.space_5), (int) getResources().getDimension(R.dimen.space_5), (int) getResources().getDimension(R.dimen.space_5)); 83 | } 84 | }); 85 | recyclerView.setAdapter(adapter); 86 | 87 | 88 | if (Build.VERSION.SDK_INT >= 22) { 89 | setExitSharedElementCallback(new SharedElementCallback() { 90 | @Override 91 | public void onMapSharedElements(List names, Map sharedElements) { 92 | if (bundle != null) { 93 | int i = bundle.getInt("index", 0); 94 | sharedElements.clear(); 95 | names.clear(); 96 | View itemView = lm.findViewByPosition(i); 97 | ImageView imageView = itemView.findViewById(R.id.imageView); 98 | //注意这里第二个参数,如果防止是的条目的item则动画不自然。放置对应的imageView则完美 99 | sharedElements.put(urls.get(i), imageView); 100 | bundle = null; 101 | } 102 | } 103 | }); 104 | } 105 | 106 | 107 | } 108 | 109 | @Override 110 | public void onClick(View view) { 111 | switch (view.getId()) { 112 | case R.id.imageView: 113 | int index = (int) view.getTag(R.id.imageView); 114 | ImageView imvv = (ImageView) view; 115 | Bitmap bm = ((BitmapDrawable) imvv.getDrawable()).getBitmap(); 116 | Comment.bitmap = bm; 117 | Intent intent = new Intent(MainActivity.this, SecondActivity.class); 118 | intent.putExtra("index", index); 119 | 120 | if (Build.VERSION.SDK_INT >= 22) { 121 | ActivityOptionsCompat options = ActivityOptionsCompat 122 | .makeSceneTransitionAnimation(MainActivity.this, view, urls.get(index));// mAdapter.get(position).getUrl() 123 | startActivity(intent, options.toBundle()); 124 | } else { 125 | startActivity(intent); 126 | } 127 | break; 128 | } 129 | } 130 | 131 | 132 | @Override 133 | public void onActivityReenter(int resultCode, Intent data) { 134 | super.onActivityReenter(resultCode, data); 135 | bundle = new Bundle(data.getExtras()); 136 | } 137 | 138 | @Subscribe(threadMode = ThreadMode.MAIN) 139 | public void onbackEvent(CanScrollBean canScrollBean) {//这里用于列表元素共享的时候,列表下滑 140 | recyclerView.scrollToPosition(canScrollBean.getPosition()); 141 | } 142 | 143 | @Override 144 | protected void onDestroy() { 145 | super.onDestroy(); 146 | EventBus.getDefault().unregister(this); 147 | } 148 | 149 | } 150 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/RecycleAdapter.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | import android.widget.RelativeLayout; 10 | 11 | import com.bumptech.glide.Glide; 12 | import com.leo.myactivityoptions.localdemo.bean.LocalBean; 13 | import com.leo.myactivityoptions.utils.UIUtil; 14 | 15 | import java.util.ArrayList; 16 | 17 | 18 | /** 19 | * Created by liujinhua on 15/9/10. 20 | */ 21 | public class RecycleAdapter extends RecyclerView.Adapter { 22 | 23 | private ArrayList dataList; 24 | Context context; 25 | View.OnClickListener listener; 26 | 27 | public RecycleAdapter(Context context, View.OnClickListener listener) { 28 | this.context = context; 29 | this.listener = listener; 30 | } 31 | 32 | public ArrayList getDataList() { 33 | return dataList; 34 | } 35 | 36 | public void setDataList(ArrayList dataList) { 37 | this.dataList = dataList; 38 | } 39 | 40 | 41 | @Override 42 | public long getItemId(int position) { 43 | return position; 44 | } 45 | 46 | //创建ViewHolder的时候要 47 | @Override 48 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 49 | RecyclerView.ViewHolder holder = null; 50 | 51 | 52 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_gridview, parent, false); 53 | holder = new VH(view); 54 | 55 | return holder; 56 | } 57 | 58 | //绑定数据 59 | @Override 60 | public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { 61 | String item = dataList.get(position); 62 | VH vhHolder = (VH) holder; 63 | RelativeLayout.LayoutParams reParams = (RelativeLayout.LayoutParams) vhHolder.imageView.getLayoutParams(); 64 | reParams.height = (UIUtil.getWidth(context) - UIUtil.dip2px(context, 30)) / 3; 65 | Glide.with(context) 66 | .load(item) 67 | .asBitmap() 68 | .dontAnimate() 69 | .placeholder(R.mipmap.wutu) 70 | .error(R.mipmap.wutu) 71 | .into(vhHolder.imageView); 72 | vhHolder.imageView.setOnClickListener(listener); 73 | vhHolder.imageView.setTag(R.id.imageView, position); 74 | } 75 | 76 | 77 | //获取Item的数量,因为添加了Header和Footer,View的数量应该加2 78 | @Override 79 | public int getItemCount() { 80 | return dataList.size(); 81 | } 82 | 83 | 84 | public class VH extends RecyclerView.ViewHolder { 85 | ImageView imageView; 86 | 87 | public VH(View itemView) { 88 | super(itemView); 89 | imageView = itemView.findViewById(R.id.imageView); 90 | } 91 | 92 | } 93 | 94 | 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/SecondActivity.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.Activity; 5 | import android.app.SharedElementCallback; 6 | import android.content.Intent; 7 | import android.os.Build; 8 | import android.os.Bundle; 9 | import android.support.annotation.Nullable; 10 | import android.support.v4.app.ActivityCompat; 11 | import android.support.v4.app.Fragment; 12 | import android.support.v4.app.FragmentStatePagerAdapter; 13 | import android.support.v4.view.ViewCompat; 14 | import android.support.v4.view.ViewPager; 15 | import android.support.v7.app.AppCompatActivity; 16 | import android.util.Log; 17 | import android.view.View; 18 | import android.widget.ImageView; 19 | import android.widget.RelativeLayout; 20 | 21 | import com.leo.myactivityoptions.localdemo.bean.CanScrollBean; 22 | 23 | import org.greenrobot.eventbus.EventBus; 24 | 25 | import java.util.List; 26 | import java.util.Map; 27 | 28 | import static com.leo.myactivityoptions.Comment.urls; 29 | 30 | /** 31 | * Created by Administrator on 2018/4/17. 32 | */ 33 | 34 | public class SecondActivity extends AppCompatActivity { 35 | 36 | private ViewPager mPager; 37 | private int index; 38 | private PagerAdapter adapter; 39 | 40 | @Override 41 | protected void onCreate(@Nullable Bundle savedInstanceState) { 42 | super.onCreate(savedInstanceState); 43 | setContentView(R.layout.activity_second); 44 | mPager = (ViewPager) findViewById(R.id.pager); 45 | index = (int) getIntent().getExtras().get("index"); 46 | supportPostponeEnterTransition();//延缓执行 然后在fragment里面的控件加载完成后start 47 | 48 | 49 | adapter = new PagerAdapter(); 50 | mPager.setAdapter(adapter); 51 | mPager.setCurrentItem(index); 52 | if (Build.VERSION.SDK_INT >= 22) { 53 | //这个可以看做个管道 每次进入和退出的时候都会进行调用 进入的时候获取到前面传来的共享元素的信息 54 | //退出的时候 把这些信息传递给前面的activity 55 | //同时向sharedElements里面put view,跟对view添加transitionname作用一样 56 | setEnterSharedElementCallback(new SharedElementCallback() { 57 | @Override 58 | public void onMapSharedElements(List names, Map sharedElements) { 59 | String url = urls.get(mPager.getCurrentItem()); 60 | LargePicFragment fragment = (LargePicFragment) adapter.instantiateItem(mPager, mPager.getCurrentItem()); 61 | sharedElements.clear(); 62 | sharedElements.put(url, fragment.getSharedElement()); 63 | } 64 | }); 65 | } 66 | 67 | 68 | mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 69 | @Override 70 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 71 | 72 | } 73 | 74 | @Override 75 | public void onPageSelected(int position) { 76 | CanScrollBean can = new CanScrollBean(); 77 | can.setPosition(position); 78 | EventBus.getDefault().post(can); 79 | } 80 | 81 | @Override 82 | public void onPageScrollStateChanged(int state) { 83 | 84 | } 85 | }); 86 | 87 | } 88 | 89 | 90 | @TargetApi(22) 91 | @Override 92 | public void supportFinishAfterTransition() { 93 | Intent data = new Intent(); 94 | data.putExtra("index", mPager.getCurrentItem()); 95 | setResult(RESULT_OK, data); 96 | super.supportFinishAfterTransition(); 97 | } 98 | 99 | 100 | @Override 101 | public void onBackPressed() { 102 | Intent data = new Intent(); 103 | data.putExtra("index", mPager.getCurrentItem()); 104 | setResult(RESULT_OK, data); 105 | super.supportFinishAfterTransition(); 106 | } 107 | 108 | private class PagerAdapter extends FragmentStatePagerAdapter { 109 | 110 | public PagerAdapter() { 111 | super(getSupportFragmentManager()); 112 | } 113 | 114 | @Override 115 | public int getCount() { 116 | return Comment.urls.size(); 117 | } 118 | 119 | @Override 120 | public Fragment getItem(int position) { 121 | return LargePicFragment.newFragment( 122 | position); 123 | } 124 | 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/SelectActivity.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | 8 | import com.gyf.barlibrary.ImmersionBar; 9 | import com.leo.myactivityoptions.likewx.LikeWxActivity; 10 | import com.leo.myactivityoptions.localdemo.LocalMainActivity; 11 | 12 | public class SelectActivity extends AppCompatActivity implements View.OnClickListener { 13 | //沉浸式状态栏 14 | protected ImmersionBar mImmersionBar; 15 | 16 | @Override 17 | protected void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | setContentView(R.layout.activity_select); 20 | mImmersionBar = ImmersionBar.with(this) 21 | .fitsSystemWindows(false); 22 | mImmersionBar.init(); 23 | findViewById(R.id.buttonPanel).setOnClickListener(this); 24 | findViewById(R.id.button).setOnClickListener(this); 25 | findViewById(R.id.buttonLuck).setOnClickListener(this); 26 | } 27 | 28 | @Override 29 | protected void onDestroy() { 30 | super.onDestroy(); 31 | mImmersionBar.destroy(); 32 | } 33 | 34 | @Override 35 | public void onClick(View v) { 36 | switch (v.getId()) { 37 | case R.id.buttonPanel: 38 | LocalMainActivity.actionStart(this); 39 | break; 40 | case R.id.button: 41 | MainActivity.actionStart(this); 42 | break; 43 | case R.id.buttonLuck: 44 | startActivity(new Intent(SelectActivity.this, LikeWxActivity.class)); 45 | break; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/customview/FireflyView.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.customview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.PixelFormat; 8 | import android.graphics.PorterDuff; 9 | import android.os.Handler; 10 | import android.os.HandlerThread; 11 | import android.os.Message; 12 | import android.util.AttributeSet; 13 | import android.view.SurfaceHolder; 14 | import android.view.SurfaceView; 15 | 16 | 17 | import com.leo.myactivityoptions.R; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.Random; 22 | 23 | /** 24 | * Created by wenshi on 2018/7/5. 25 | * Description 浮点粒子控件 26 | */ 27 | public class FireflyView extends SurfaceView implements SurfaceHolder.Callback { 28 | 29 | // 粒子的最大数量 30 | private static final int MAX_NUM = 400; 31 | // 粒子集合 32 | private List mListParticles; 33 | // 随机数 34 | private Random mRandom; 35 | 36 | private SurfaceHolder mHolder; 37 | 38 | // 动画线程 39 | private Handler mHandler; 40 | 41 | // 粒子半径 42 | private int mParticleMaxRadius; 43 | 44 | // 粒子数量 45 | private int mParticleNum; 46 | 47 | // 粒子移动速率 48 | private int mParticleMoveRate; 49 | 50 | private static final int EMPTY_FLAG = 1; 51 | 52 | public FireflyView(Context context) { 53 | this(context, null); 54 | } 55 | 56 | public FireflyView(Context context, AttributeSet attrs) { 57 | this(context, attrs, 0); 58 | } 59 | 60 | public FireflyView(Context context, AttributeSet attrs, int defStyleAttr) { 61 | super(context, attrs, defStyleAttr); 62 | // 关闭硬件加速 63 | setLayerType(LAYER_TYPE_SOFTWARE, null); 64 | init(); 65 | 66 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.FireflyView); 67 | mParticleMaxRadius = ta.getInt(R.styleable.FireflyView_firefly_max_radius, 5); 68 | mParticleNum = ta.getInt(R.styleable.FireflyView_firefly_num, MAX_NUM); 69 | mParticleMoveRate = ta.getInt(R.styleable.FireflyView_firefly_move_rate, 5); 70 | ta.recycle(); 71 | } 72 | 73 | private void init() { 74 | // 设置透明 75 | setZOrderOnTop(true); 76 | // 配合清屏 canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); 77 | mHolder = getHolder(); 78 | mHolder.setFormat(PixelFormat.TRANSLUCENT); 79 | mHolder.addCallback(this); 80 | // 初始化随机数 81 | mRandom = new Random(); 82 | } 83 | 84 | @Override 85 | public void surfaceCreated(SurfaceHolder holder) { 86 | } 87 | 88 | // 初始化浮点粒子数据 89 | private void initParticlesData(int width, int height) { 90 | mListParticles = new ArrayList<>(); 91 | for (int i = 0; i < mParticleNum; i++) { 92 | FloatParticle fp = new FloatParticle(width, height); 93 | mParticleMaxRadius = mParticleMaxRadius < 2 ? 2 : mParticleMaxRadius; 94 | fp.setRadius(mRandom.nextInt(mParticleMaxRadius - 1) + 1); 95 | mListParticles.add(fp); 96 | } 97 | } 98 | 99 | @Override 100 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 101 | initParticlesData(width, height); 102 | startAnimation(); 103 | } 104 | 105 | @Override 106 | public void surfaceDestroyed(SurfaceHolder holder) { 107 | stopAnimation(); 108 | } 109 | 110 | public void stopAnimation() { 111 | mHandler.removeCallbacksAndMessages(null); 112 | } 113 | 114 | public void startAnimation() { 115 | //if (mHandler != null) return; 116 | HandlerThread fireThread = new HandlerThread(this.getClass().getName()); 117 | fireThread.start(); 118 | mHandler = new Handler(fireThread.getLooper()) { 119 | @Override 120 | public void handleMessage(Message msg) { 121 | super.handleMessage(msg); 122 | Canvas mCanvas = mHolder.lockCanvas(null); 123 | if (mCanvas != null) { 124 | synchronized (mHolder) { 125 | // 清屏 126 | mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); 127 | for (FloatParticle fp : mListParticles) { 128 | fp.drawParticle(mCanvas); 129 | } 130 | } 131 | } 132 | try { 133 | Thread.sleep(10); 134 | } catch (InterruptedException e) { 135 | e.printStackTrace(); 136 | } 137 | if (mCanvas != null) { 138 | mHolder.unlockCanvasAndPost(mCanvas); 139 | } 140 | mHandler.sendEmptyMessageDelayed(EMPTY_FLAG, mParticleMoveRate); 141 | } 142 | }; 143 | mHandler.sendEmptyMessage(EMPTY_FLAG); 144 | } 145 | 146 | public int getParticleMoveRate() { 147 | return mParticleMoveRate; 148 | } 149 | 150 | public void setParticleMoveRate(int particleMoveRate) { 151 | mParticleMoveRate = particleMoveRate; 152 | } 153 | 154 | public int getParticleMaxRadius() { 155 | return mParticleMaxRadius; 156 | } 157 | 158 | public int getParticleNum() { 159 | return mParticleNum; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/customview/FloatParticle.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.customview; 2 | 3 | import android.graphics.BlurMaskFilter; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.graphics.PathMeasure; 9 | import android.graphics.Point; 10 | 11 | import java.util.Random; 12 | 13 | /** 14 | * Created by wenshi on 2018/7/4. 15 | * Description 浮点粒子 16 | */ 17 | public class FloatParticle { 18 | 19 | // 三阶贝塞尔曲线 20 | private Point startPoint; 21 | private Point endPoint; 22 | private Point controlPoint1; 23 | private Point controlPoint2; 24 | 25 | private Paint mPaint; 26 | private Path mPath; 27 | private Random mRandom; 28 | 29 | // 圆半径 30 | private float mRadius = 5; 31 | 32 | // 控件宽度 33 | private int mWidth; 34 | // 控件高度 35 | private int mHeight; 36 | 37 | private float mCurDistance = 0; 38 | 39 | private static final int DISTANCE = 255; 40 | 41 | private static final float MOVE_PER_FRAME = 1f; 42 | 43 | // 火花外侧阴影大小 44 | private static final float BLUR_SIZE = 5.0F; 45 | 46 | // 路径测量 47 | private PathMeasure mPathMeasure; 48 | 49 | private float mMeasureLength; 50 | 51 | public FloatParticle(int width, int height) { 52 | mWidth = width; 53 | mHeight = height; 54 | mRandom = new Random(); 55 | 56 | startPoint = new Point((int) (mRandom.nextFloat() * mWidth), (int) (mRandom.nextFloat() * mHeight)); 57 | 58 | // 抗锯齿 59 | mPaint = new Paint(); 60 | mPaint.setAntiAlias(true); 61 | //这里是修改粒子颜色值的 62 | mPaint.setColor(Color.WHITE); 63 | // 防抖动 64 | mPaint.setDither(true); 65 | mPaint.setStyle(Paint.Style.FILL); 66 | // 设置模糊效果 边缘模糊 67 | mPaint.setMaskFilter(new BlurMaskFilter(BLUR_SIZE, BlurMaskFilter.Blur.SOLID)); 68 | 69 | mPath = new Path(); 70 | mPathMeasure = new PathMeasure(); 71 | 72 | startPoint.x = (int) (mRandom.nextFloat() * mWidth); 73 | startPoint.y = (int) (mRandom.nextFloat() * mHeight); 74 | } 75 | 76 | public void drawParticle(Canvas canvas) { 77 | 78 | // 初始化三阶贝塞尔曲线数据 79 | if (mCurDistance == 0) { 80 | endPoint = getRandomPointRange(startPoint.x, startPoint.y, DISTANCE); 81 | controlPoint1 = getRandomPointRange(startPoint.x, startPoint.y, mRandom.nextInt(Math.min(mWidth, mHeight) / 2)); 82 | controlPoint2 = getRandomPointRange(endPoint.x, endPoint.y, mRandom.nextInt(Math.min(mWidth, mHeight) / 2)); 83 | // 添加贝塞尔曲线路径 84 | mPath.reset(); 85 | mPath.moveTo(startPoint.x, startPoint.y); 86 | mPath.cubicTo(controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y); 87 | mPathMeasure.setPath(mPath, false); 88 | mMeasureLength = mPathMeasure.getLength(); 89 | } 90 | //计算当前坐标点 91 | float[] loc = new float[2]; 92 | mPathMeasure.getPosTan(mCurDistance / DISTANCE * mMeasureLength, loc, null); 93 | startPoint.x = (int) loc[0]; 94 | startPoint.y = (int) loc[1]; 95 | 96 | // 递增1 97 | mCurDistance += MOVE_PER_FRAME; 98 | 99 | if (mCurDistance >= DISTANCE) { 100 | mCurDistance = 0; 101 | } 102 | 103 | canvas.drawCircle(startPoint.x, startPoint.y, mRadius, mPaint); 104 | } 105 | 106 | /** 107 | * @param baseX 基准坐标x 108 | * @param baseY 基准坐标y 109 | * @param range 指定范围长度 110 | * @return 根据基准点获取指定范围的随机点 111 | */ 112 | private Point getRandomPointRange(int baseX, int baseY, int range) { 113 | int randomX = 0; 114 | int randomY = 0; 115 | //range指定长度为255,可以根据实际效果调整 116 | if (range <= 0) { 117 | range = 1; 118 | } 119 | //我们知道一点(baseX,baseY)求与它距离长度为range的另一点 120 | 121 | //两点x方向的距离(随机产生) 122 | int distanceX = mRandom.nextInt(range); 123 | 124 | //知道x方向的距离与斜边的距离求y方向的距离 125 | int distanceY = (int) Math.sqrt(range * range - distanceX * distanceX); 126 | 127 | randomX = baseX + getRandomPNValue(distanceX); 128 | randomY = baseY + getRandomPNValue(distanceY); 129 | 130 | if (randomX > mWidth) { 131 | randomX = mWidth - range; 132 | } else if (randomX < 0) { 133 | randomX = range; 134 | } else if (randomY > mHeight) { 135 | randomY = mHeight - range; 136 | } else if (randomY < 0) { 137 | randomY = range; 138 | } 139 | 140 | return new Point(randomX, randomY); 141 | } 142 | 143 | /** 144 | * 获取随机的正负值 145 | * 146 | * @return 147 | */ 148 | private int getRandomPNValue(int value) { 149 | return mRandom.nextBoolean() ? value : 0 - value; 150 | } 151 | 152 | /** 153 | * 设置圆半径 154 | * 155 | * @param radius 156 | */ 157 | public void setRadius(float radius) { 158 | mRadius = radius; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/likewx/LikeWxActivity.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.likewx; 2 | 3 | import android.graphics.Rect; 4 | import android.os.Bundle; 5 | import android.support.annotation.Nullable; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.support.v7.widget.GridLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.view.View; 10 | import android.widget.Toast; 11 | 12 | import com.gyf.barlibrary.ImmersionBar; 13 | import com.leo.myactivityoptions.R; 14 | 15 | import net.moyokoo.diooto.Diooto; 16 | import net.moyokoo.diooto.DragDiootoView; 17 | import net.moyokoo.diooto.config.DiootoConfig; 18 | import net.moyokoo.diooto.interfaces.DefaultCircleProgress; 19 | 20 | import org.salient.artplayer.MediaPlayerManager; 21 | import org.salient.artplayer.ScaleType; 22 | import org.salient.artplayer.VideoView; 23 | 24 | import java.util.ArrayList; 25 | 26 | import me.panpf.sketch.SketchImageView; 27 | 28 | /** 29 | * Created by leo 30 | * on 2019/5/14. 31 | */ 32 | public class LikeWxActivity extends AppCompatActivity implements View.OnClickListener { 33 | private RecyclerView recyclerView; 34 | private ArrayList arrayList = new ArrayList<>(); 35 | private ReAdapter adapter; 36 | //沉浸式状态栏 37 | protected ImmersionBar mImmersionBar; 38 | @Override 39 | protected void onCreate(@Nullable Bundle savedInstanceState) { 40 | super.onCreate(savedInstanceState); 41 | setContentView(R.layout.activity_likewx); 42 | mImmersionBar = ImmersionBar.with(this) 43 | .statusBarColor(R.color.status_color) 44 | // .keyboardEnable(true) 45 | // .keyboardMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN) 46 | .fitsSystemWindows(true); 47 | mImmersionBar.init(); 48 | recyclerView = findViewById(R.id.recyclerView); 49 | adapter = new ReAdapter(this, this); 50 | arrayList.add("https://ww1.sinaimg.cn"); 51 | arrayList.add("https://ww1.sinaimg.cn/large/0073sXn7ly1g1p973zyz4g30de0mskjp?imageView2/2/w/460"); 52 | // arrayList.add("https://github.com/moyokoo/Media/blob/master/diooto3.jpg?raw=true"); 53 | arrayList.add("https://ww4.sinaimg.cn/bmiddle/61e7945bly1fwnpjo7er0j215o6u77o1.jpg"); 54 | // arrayList.add("https://github.com/moyokoo/Media/blob/master/diooto4.jpg?raw=true"); 55 | arrayList.add("http://img5.mtime.cn/mg/2018/07/06/093947.51483272.jpg"); 56 | 57 | arrayList.add("https://github.com/moyokoo/Media/blob/master/diooto5.jpg?raw=true"); 58 | arrayList.add("https://github.com/moyokoo/Media/blob/master/diooto6.jpg?raw=true"); 59 | arrayList.add("https://github.com/moyokoo/Media/blob/master/diooto7.png?raw=true"); 60 | arrayList.add("https://github.com/moyokoo/Media/blob/master/diooto8.png?raw=true"); 61 | arrayList.add("https://github.com/moyokoo/Media/blob/master/diooto9.jpg?raw=true"); 62 | 63 | final GridLayoutManager lm = new GridLayoutManager(this, 3); 64 | //设置布局管理器 65 | recyclerView.setLayoutManager(lm); 66 | recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { 67 | @Override 68 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 69 | outRect.set((int) getResources().getDimension(R.dimen.divide), (int) getResources().getDimension(R.dimen.divide), (int) getResources().getDimension(R.dimen.divide), (int) getResources().getDimension(R.dimen.divide)); 70 | } 71 | }); 72 | adapter.setRemindList(arrayList); 73 | recyclerView.setAdapter(adapter); 74 | } 75 | 76 | @Override 77 | protected void onDestroy() { 78 | super.onDestroy(); 79 | mImmersionBar.destroy(); 80 | } 81 | 82 | @Override 83 | public void onClick(View v) { 84 | switch (v.getId()){ 85 | case R.id.srcImageView: 86 | final int position = (int) v.getTag(); 87 | if (position != 3) { 88 | //加载列表 89 | String[] array = (String[]) arrayList.toArray(new String[arrayList.size()]); 90 | Diooto diooto = new Diooto(LikeWxActivity.this) 91 | .indicatorVisibility(View.VISIBLE) 92 | .urls(array) 93 | .type(DiootoConfig.PHOTO) 94 | .immersive(true) 95 | .position(position, 0) 96 | .views(recyclerView, R.id.srcImageView) 97 | .loadPhotoBeforeShowBigImage(new Diooto.OnLoadPhotoBeforeShowBigImageListener() { 98 | @Override 99 | public void loadView(SketchImageView sketchImageView, int position) { 100 | sketchImageView.displayImage(arrayList.get(position)); 101 | sketchImageView.setOnLongClickListener(new View.OnLongClickListener() { 102 | @Override 103 | public boolean onLongClick(View v) { 104 | Toast.makeText(LikeWxActivity.this, "Long click", Toast.LENGTH_SHORT).show(); 105 | return false; 106 | } 107 | }); 108 | } 109 | }).start(); 110 | } else { 111 | final String[] array = (String[]) arrayList.toArray(new String[arrayList.size()]); 112 | //加载视频 113 | Diooto diooto = new Diooto(LikeWxActivity.this) 114 | .urls(array[position]) 115 | .position(position) 116 | .views((SketchImageView) v) 117 | .type(DiootoConfig.VIDEO) 118 | .immersive(true) 119 | .setProgress(new DefaultCircleProgress()) 120 | //提供视频View 121 | .onProvideVideoView(new Diooto.OnProvideViewListener() { 122 | @Override 123 | public View provideView() { 124 | return new VideoView(LikeWxActivity.this); 125 | } 126 | }) 127 | //显示视频加载之前的缩略图 128 | .loadPhotoBeforeShowBigImage(new Diooto.OnLoadPhotoBeforeShowBigImageListener() { 129 | @Override 130 | public void loadView(SketchImageView sketchImageView, int positionL) { 131 | sketchImageView.displayImage(array[position]); 132 | } 133 | }) 134 | //动画到最大化时的接口 135 | .onVideoLoadEnd(new Diooto.OnShowToMaxFinishListener() { 136 | @Override 137 | public void onShowToMax(final DragDiootoView dragDiootoView, final SketchImageView sketchImageView, final View progressView) { 138 | VideoView videoView = (VideoView) dragDiootoView.getContentView(); 139 | SimpleControlPanel simpleControlPanel = new SimpleControlPanel(LikeWxActivity.this); 140 | simpleControlPanel.setOnClickListener(new View.OnClickListener() { 141 | @Override 142 | public void onClick(View v) { 143 | dragDiootoView.backToMin(); 144 | } 145 | }); 146 | simpleControlPanel.setOnVideoPreparedListener(new SimpleControlPanel.OnVideoPreparedListener() { 147 | @Override 148 | public void prepared() { 149 | sketchImageView.setVisibility(View.GONE); 150 | progressView.setVisibility(View.GONE); 151 | } 152 | }); 153 | videoView.setControlPanel(simpleControlPanel); 154 | 155 | videoView.setUp("http://vfx.mtime.cn/Video/2018/07/06/mp4/180706094003288023.mp4"); 156 | videoView.start(); 157 | dragDiootoView.notifySize(1920, 1080); 158 | MediaPlayerManager.instance().setScreenScale(ScaleType.SCALE_CENTER_CROP); 159 | } 160 | }) 161 | //到最小状态的接口 162 | .onFinish(new Diooto.OnFinishListener() { 163 | @Override 164 | public void finish(DragDiootoView dragDiootoView) { 165 | MediaPlayerManager.instance().releasePlayerAndView(LikeWxActivity.this); 166 | } 167 | }).start(); 168 | 169 | } 170 | 171 | 172 | break; 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/likewx/ReAdapter.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.likewx; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.FrameLayout; 9 | 10 | import com.leo.myactivityoptions.R; 11 | import com.leo.myactivityoptions.utils.UIUtil; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | 16 | import me.panpf.sketch.Sketch; 17 | import me.panpf.sketch.SketchImageView; 18 | import me.panpf.sketch.request.DisplayOptions; 19 | 20 | /** 21 | * Created by leo 22 | * on 2019/5/13. 23 | */ 24 | 25 | public class ReAdapter extends RecyclerView.Adapter { 26 | 27 | private Context context; 28 | private List remindList; 29 | private LayoutInflater inflater; 30 | private View.OnClickListener listener; 31 | 32 | 33 | public ReAdapter(Context context, View.OnClickListener listener) { 34 | this.context = context; 35 | inflater = LayoutInflater.from(context); 36 | this.listener = listener; 37 | } 38 | 39 | public void setRemindList(ArrayList remindList) { 40 | this.remindList = remindList; 41 | } 42 | 43 | 44 | @Override 45 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 46 | 47 | RecyclerView.ViewHolder holder = null; 48 | View v; 49 | 50 | v = inflater.inflate(R.layout.item_grid, parent, false); 51 | holder = new ViewHolder(v); 52 | 53 | return holder; 54 | 55 | } 56 | 57 | 58 | @Override 59 | public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) { 60 | 61 | 62 | ViewHolder holder1 = (ViewHolder) holder; 63 | String itemUrl = remindList.get(position); 64 | FrameLayout.LayoutParams cardreParams = (FrameLayout.LayoutParams) holder1.srcImageView.getLayoutParams(); 65 | cardreParams.height = (UIUtil.getWidth(context) - UIUtil.dip2px(context,16)) / 3; 66 | DisplayOptions displayOptions = new DisplayOptions(); 67 | displayOptions.setLoadingImage(R.mipmap.ic_launcher_leo); 68 | displayOptions.setErrorImage(R.mipmap.image_error); 69 | holder1.srcImageView.setShowGifFlagEnabled(R.mipmap.ic_gif); 70 | Sketch.with(context).display(itemUrl, holder1.srcImageView) 71 | .options(displayOptions) 72 | .commit(); 73 | holder1.srcImageView.setOnClickListener(listener); 74 | holder1.srcImageView.setTag(position); 75 | } 76 | 77 | 78 | @Override 79 | public int getItemCount() { 80 | return remindList == null ? 0 : remindList.size(); 81 | } 82 | 83 | 84 | class ViewHolder extends RecyclerView.ViewHolder { 85 | SketchImageView srcImageView; 86 | 87 | 88 | public ViewHolder(View itemView) { 89 | super(itemView); 90 | srcImageView = itemView.findViewById(R.id.srcImageView); 91 | } 92 | } 93 | 94 | 95 | } -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/likewx/SimpleControlPanel.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.likewx; 2 | 3 | import android.annotation.SuppressLint; 4 | import android.content.Context; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | import android.view.View; 8 | import android.view.ViewParent; 9 | import android.widget.ImageView; 10 | import android.widget.ProgressBar; 11 | import android.widget.SeekBar; 12 | 13 | import com.leo.myactivityoptions.R; 14 | 15 | import org.salient.artplayer.AbsControlPanel; 16 | import org.salient.artplayer.MediaPlayerManager; 17 | 18 | public class SimpleControlPanel extends AbsControlPanel implements SeekBar.OnSeekBarChangeListener { 19 | 20 | private ProgressBar loading; 21 | private ImageView video_cover; 22 | public interface OnVideoPreparedListener{ 23 | void prepared(); 24 | } 25 | OnVideoPreparedListener onVideoPreparedListener; 26 | 27 | public void setOnVideoPreparedListener(OnVideoPreparedListener onVideoPreparedListener) { 28 | this.onVideoPreparedListener = onVideoPreparedListener; 29 | } 30 | 31 | public SimpleControlPanel(Context context) { 32 | super(context); 33 | } 34 | 35 | public SimpleControlPanel(Context context, AttributeSet attrs) { 36 | super(context, attrs); 37 | } 38 | 39 | public SimpleControlPanel(Context context, AttributeSet attrs, int defStyleAttr) { 40 | super(context, attrs, defStyleAttr); 41 | } 42 | 43 | 44 | @Override 45 | protected int getResourceId() { 46 | return R.layout.simple_control_panel; 47 | } 48 | 49 | @SuppressLint("ClickableViewAccessibility") 50 | @Override 51 | protected void init(Context context) { 52 | super.init(context); 53 | loading = findViewById(R.id.loading); 54 | video_cover = findViewById(R.id.video_cover); 55 | } 56 | 57 | 58 | 59 | @Override 60 | public void onStateError() { 61 | 62 | } 63 | 64 | @Override 65 | public void onStateIdle() { 66 | hideUI( loading); 67 | showUI(video_cover); 68 | } 69 | 70 | @Override 71 | public void onStatePreparing() { 72 | showUI(loading); 73 | } 74 | 75 | @Override 76 | public void onStatePrepared() { 77 | hideUI(loading); 78 | if (onVideoPreparedListener!=null){ 79 | onVideoPreparedListener.prepared(); 80 | } 81 | } 82 | 83 | @Override 84 | public void onStatePlaying() { 85 | } 86 | 87 | @Override 88 | public void onStatePaused() { 89 | } 90 | 91 | @Override 92 | public void onStatePlaybackCompleted() { 93 | } 94 | 95 | @Override 96 | public void onSeekComplete() { 97 | 98 | } 99 | 100 | @Override 101 | public void onBufferingUpdate(int progress) { 102 | } 103 | 104 | @Override 105 | public void onInfo(int what, int extra) { 106 | } 107 | 108 | @Override 109 | public void onProgressUpdate(final int progress, final long position, final long duration) { 110 | 111 | } 112 | 113 | @Override 114 | public void onEnterSecondScreen() { 115 | } 116 | 117 | @Override 118 | public void onExitSecondScreen() { 119 | } 120 | 121 | @Override 122 | public void onStartTrackingTouch(SeekBar seekBar) { 123 | MediaPlayerManager.instance().cancelProgressTimer(); 124 | ViewParent vpdown = getParent(); 125 | while (vpdown != null) { 126 | vpdown.requestDisallowInterceptTouchEvent(true); 127 | vpdown = vpdown.getParent(); 128 | } 129 | } 130 | 131 | @Override 132 | public void onStopTrackingTouch(SeekBar seekBar) { 133 | MediaPlayerManager.instance().startProgressTimer(); 134 | ViewParent vpup = getParent(); 135 | while (vpup != null) { 136 | vpup.requestDisallowInterceptTouchEvent(false); 137 | vpup = vpup.getParent(); 138 | } 139 | if (MediaPlayerManager.instance().getPlayerState() != MediaPlayerManager.PlayerState.PLAYING && 140 | MediaPlayerManager.instance().getPlayerState() != MediaPlayerManager.PlayerState.PAUSED) 141 | return; 142 | long time = (long) (seekBar.getProgress() * 1.00 / 100 * MediaPlayerManager.instance().getDuration()); 143 | MediaPlayerManager.instance().seekTo(time); 144 | } 145 | 146 | @Override 147 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 148 | if (fromUser) { 149 | long duration = MediaPlayerManager.instance().getDuration(); 150 | } 151 | } 152 | 153 | //显示WiFi状态提醒 154 | public void showWifiAlert() { 155 | hideUI(loading); 156 | } 157 | 158 | @Override 159 | public void onClick(View v) { 160 | int id = v.getId(); 161 | } 162 | 163 | @Override 164 | public boolean onTouch(View v, MotionEvent event) { 165 | switch (event.getAction()) { 166 | case MotionEvent.ACTION_DOWN: 167 | break; 168 | case MotionEvent.ACTION_MOVE: 169 | break; 170 | case MotionEvent.ACTION_UP: 171 | break; 172 | } 173 | return false; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/localdemo/DividerGridItemDecoration.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.localdemo; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Rect; 7 | import android.graphics.drawable.Drawable; 8 | import android.support.v7.widget.GridLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.support.v7.widget.RecyclerView.LayoutManager; 11 | import android.support.v7.widget.RecyclerView.State; 12 | import android.support.v7.widget.StaggeredGridLayoutManager; 13 | import android.view.View; 14 | 15 | /** 16 | * 17 | * @author zhy 18 | * 19 | */ 20 | public class DividerGridItemDecoration extends RecyclerView.ItemDecoration 21 | { 22 | 23 | private static final int[] ATTRS = new int[] { android.R.attr.listDivider }; 24 | private Drawable mDivider; 25 | 26 | public DividerGridItemDecoration(Context context) 27 | { 28 | final TypedArray a = context.obtainStyledAttributes(ATTRS); 29 | mDivider = a.getDrawable(0); 30 | a.recycle(); 31 | } 32 | 33 | @Override 34 | public void onDraw(Canvas c, RecyclerView parent, State state) 35 | { 36 | 37 | drawHorizontal(c, parent); 38 | drawVertical(c, parent); 39 | 40 | } 41 | 42 | private int getSpanCount(RecyclerView parent) 43 | { 44 | // 列数 45 | int spanCount = -1; 46 | LayoutManager layoutManager = parent.getLayoutManager(); 47 | if (layoutManager instanceof GridLayoutManager) 48 | { 49 | 50 | spanCount = ((GridLayoutManager) layoutManager).getSpanCount(); 51 | } else if (layoutManager instanceof StaggeredGridLayoutManager) 52 | { 53 | spanCount = ((StaggeredGridLayoutManager) layoutManager) 54 | .getSpanCount(); 55 | } 56 | return spanCount; 57 | } 58 | 59 | public void drawHorizontal(Canvas c, RecyclerView parent) 60 | { 61 | int childCount = parent.getChildCount(); 62 | for (int i = 0; i < childCount; i++) 63 | { 64 | final View child = parent.getChildAt(i); 65 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 66 | .getLayoutParams(); 67 | final int left = child.getLeft() - params.leftMargin; 68 | final int right = child.getRight() + params.rightMargin 69 | + mDivider.getIntrinsicWidth(); 70 | final int top = child.getBottom() + params.bottomMargin; 71 | final int bottom = top + mDivider.getIntrinsicHeight(); 72 | mDivider.setBounds(left, top, right, bottom); 73 | mDivider.draw(c); 74 | } 75 | } 76 | 77 | public void drawVertical(Canvas c, RecyclerView parent) 78 | { 79 | final int childCount = parent.getChildCount(); 80 | for (int i = 0; i < childCount; i++) 81 | { 82 | final View child = parent.getChildAt(i); 83 | 84 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 85 | .getLayoutParams(); 86 | final int top = child.getTop() - params.topMargin; 87 | final int bottom = child.getBottom() + params.bottomMargin; 88 | final int left = child.getRight() + params.rightMargin; 89 | final int right = left + mDivider.getIntrinsicWidth(); 90 | 91 | mDivider.setBounds(left, top, right, bottom); 92 | mDivider.draw(c); 93 | } 94 | } 95 | 96 | private boolean isLastColum(RecyclerView parent, int pos, int spanCount, 97 | int childCount) 98 | { 99 | LayoutManager layoutManager = parent.getLayoutManager(); 100 | if (layoutManager instanceof GridLayoutManager) 101 | { 102 | if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边 103 | { 104 | return true; 105 | } 106 | } else if (layoutManager instanceof StaggeredGridLayoutManager) 107 | { 108 | int orientation = ((StaggeredGridLayoutManager) layoutManager) 109 | .getOrientation(); 110 | if (orientation == StaggeredGridLayoutManager.VERTICAL) 111 | { 112 | if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边 113 | { 114 | return true; 115 | } 116 | } else 117 | { 118 | childCount = childCount - childCount % spanCount; 119 | if (pos >= childCount)// 如果是最后一列,则不需要绘制右边 120 | return true; 121 | } 122 | } 123 | return false; 124 | } 125 | 126 | private boolean isLastRaw(RecyclerView parent, int pos, int spanCount, 127 | int childCount) 128 | { 129 | LayoutManager layoutManager = parent.getLayoutManager(); 130 | if (layoutManager instanceof GridLayoutManager) 131 | { 132 | childCount = childCount - childCount % spanCount; 133 | if (pos >= childCount)// 如果是最后一行,则不需要绘制底部 134 | return true; 135 | } else if (layoutManager instanceof StaggeredGridLayoutManager) 136 | { 137 | int orientation = ((StaggeredGridLayoutManager) layoutManager) 138 | .getOrientation(); 139 | // StaggeredGridLayoutManager 且纵向滚动 140 | if (orientation == StaggeredGridLayoutManager.VERTICAL) 141 | { 142 | childCount = childCount - childCount % spanCount; 143 | // 如果是最后一行,则不需要绘制底部 144 | if (pos >= childCount) 145 | return true; 146 | } else 147 | // StaggeredGridLayoutManager 且横向滚动 148 | { 149 | // 如果是最后一行,则不需要绘制底部 150 | if ((pos + 1) % spanCount == 0) 151 | { 152 | return true; 153 | } 154 | } 155 | } 156 | return false; 157 | } 158 | 159 | @Override 160 | public void getItemOffsets(Rect outRect, int itemPosition, 161 | RecyclerView parent) 162 | { 163 | int spanCount = getSpanCount(parent); 164 | int childCount = parent.getAdapter().getItemCount(); 165 | if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部 166 | { 167 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); 168 | } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边 169 | { 170 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); 171 | } else 172 | { 173 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 174 | mDivider.getIntrinsicHeight()); 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/localdemo/GridAdapter.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.localdemo; 2 | 3 | import android.content.Context; 4 | import android.support.v7.view.menu.MenuView; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.ImageView; 10 | import android.widget.RelativeLayout; 11 | import android.widget.TextView; 12 | 13 | import com.bumptech.glide.Glide; 14 | import com.leo.myactivityoptions.R; 15 | import com.leo.myactivityoptions.localdemo.bean.LocalBean; 16 | import com.leo.myactivityoptions.utils.UIUtil; 17 | 18 | import java.util.ArrayList; 19 | 20 | 21 | /** 22 | * Created by liujinhua on 15/9/10. 23 | */ 24 | public class GridAdapter extends RecyclerView.Adapter { 25 | 26 | private ArrayList dataList; 27 | Context context; 28 | View.OnClickListener listener; 29 | 30 | public GridAdapter(Context context, View.OnClickListener listener) { 31 | this.context = context; 32 | this.listener = listener; 33 | } 34 | 35 | public ArrayList getDataList() { 36 | return dataList; 37 | } 38 | 39 | public void setDataList(ArrayList dataList) { 40 | this.dataList = dataList; 41 | } 42 | 43 | 44 | @Override 45 | public long getItemId(int position) { 46 | return position; 47 | } 48 | 49 | //创建ViewHolder的时候要 50 | @Override 51 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 52 | RecyclerView.ViewHolder holder = null; 53 | 54 | 55 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_gridview, parent, false); 56 | holder = new VH(view); 57 | 58 | return holder; 59 | } 60 | 61 | //绑定数据 62 | @Override 63 | public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { 64 | LocalBean item = dataList.get(position); 65 | VH vhHolder = (VH) holder; 66 | RelativeLayout.LayoutParams reParams = (RelativeLayout.LayoutParams) vhHolder.imageView.getLayoutParams(); 67 | reParams.height = (UIUtil.getWidth(context) - UIUtil.dip2px(context, 30)) / 3; 68 | Glide.with(context) 69 | .load(item.getMipmap()) 70 | .asBitmap() 71 | .dontAnimate() 72 | .placeholder(R.mipmap.wutu) 73 | .error(R.mipmap.wutu) 74 | .into(vhHolder.imageView); 75 | vhHolder.imageView.setOnClickListener(listener); 76 | vhHolder.imageView.setTag(R.id.imageView, position); 77 | } 78 | 79 | 80 | //获取Item的数量,因为添加了Header和Footer,View的数量应该加2 81 | @Override 82 | public int getItemCount() { 83 | return dataList.size(); 84 | } 85 | 86 | 87 | public class VH extends RecyclerView.ViewHolder { 88 | ImageView imageView; 89 | 90 | public VH(View itemView) { 91 | super(itemView); 92 | imageView = itemView.findViewById(R.id.imageView); 93 | } 94 | 95 | } 96 | 97 | 98 | } 99 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/localdemo/LocalLargePicFragment.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.localdemo; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.view.ViewTreeObserver; 13 | import android.widget.ImageView; 14 | 15 | import com.bumptech.glide.Glide; 16 | import com.leo.myactivityoptions.R; 17 | import com.leo.myactivityoptions.SecondActivity; 18 | 19 | import static com.leo.myactivityoptions.Comment.mipmaps; 20 | 21 | /** 22 | * Created by Mr_Wrong on 15/10/6. 23 | */ 24 | public class LocalLargePicFragment extends Fragment { 25 | private LocalSecondActivity activity; 26 | private int index; 27 | private ImageView image; 28 | 29 | public static Fragment newFragment(int index) { 30 | Bundle bundle = new Bundle(); 31 | bundle.putInt("index", index); 32 | LocalLargePicFragment fragment = new LocalLargePicFragment(); 33 | fragment.setArguments(bundle); 34 | return fragment; 35 | } 36 | 37 | @Override 38 | public void onAttach(Context context) { 39 | super.onAttach(context); 40 | this.activity = (LocalSecondActivity) context; 41 | 42 | } 43 | 44 | @Override 45 | public void onCreate(@Nullable Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | index = getArguments().getInt("index"); 48 | } 49 | 50 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 51 | @Nullable 52 | @Override 53 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 54 | View view = inflater.inflate(R.layout.fragment_viewer, container, false); 55 | image = view.findViewById(R.id.image); 56 | 57 | image.setOnClickListener(new View.OnClickListener() { 58 | @Override 59 | public void onClick(View v) { 60 | activity.supportFinishAfterTransition(); 61 | } 62 | }); 63 | 64 | 65 | image.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { 66 | @Override 67 | public boolean onPreDraw() { 68 | image.getViewTreeObserver().removeOnPreDrawListener(this); 69 | getActivity().supportStartPostponedEnterTransition(); 70 | return true; 71 | } 72 | }); 73 | return view; 74 | } 75 | 76 | @Override 77 | public void onResume() { 78 | super.onResume(); 79 | Glide.with(activity) 80 | .load(mipmaps.get(index).getMipmap()) 81 | .asBitmap() 82 | .dontAnimate() 83 | .into(image); 84 | } 85 | 86 | public View getSharedElement() { 87 | return image; 88 | } 89 | 90 | 91 | } 92 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/localdemo/LocalMainActivity.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.localdemo; 2 | 3 | import android.app.SharedElementCallback; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | import android.graphics.Rect; 7 | import android.os.Build; 8 | import android.os.Bundle; 9 | import android.support.v4.app.ActivityOptionsCompat; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.support.v7.widget.GridLayoutManager; 12 | import android.support.v7.widget.RecyclerView; 13 | import android.util.Log; 14 | import android.view.View; 15 | import android.widget.GridView; 16 | import android.widget.ImageView; 17 | 18 | import com.leo.myactivityoptions.Comment; 19 | import com.leo.myactivityoptions.R; 20 | import com.leo.myactivityoptions.localdemo.bean.CanScrollBean; 21 | import com.leo.myactivityoptions.localdemo.bean.LocalBean; 22 | 23 | import org.greenrobot.eventbus.EventBus; 24 | import org.greenrobot.eventbus.Subscribe; 25 | import org.greenrobot.eventbus.ThreadMode; 26 | 27 | import java.util.ArrayList; 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | 32 | public class LocalMainActivity extends AppCompatActivity implements View.OnClickListener { 33 | 34 | private RecyclerView recyclerView; 35 | private ArrayList mipmaps = new ArrayList<>(); 36 | private GridAdapter adapter; 37 | private Bundle bundle; 38 | 39 | public static void actionStart(Context context) { 40 | Intent intent = new Intent(context, LocalMainActivity.class); 41 | context.startActivity(intent); 42 | } 43 | 44 | @Override 45 | protected void onCreate(Bundle savedInstanceState) { 46 | super.onCreate(savedInstanceState); 47 | setContentView(R.layout.activity_localmain); 48 | EventBus.getDefault().register(this); 49 | 50 | recyclerView = (RecyclerView) findViewById(R.id.recyclerView); 51 | adapter = new GridAdapter(this, this); 52 | mipmaps.add(new LocalBean(R.mipmap.wangze1, "0")); 53 | mipmaps.add(new LocalBean(R.mipmap.other1, "1")); 54 | mipmaps.add(new LocalBean(R.mipmap.other2, "2")); 55 | mipmaps.add(new LocalBean(R.mipmap.wangze2, "3")); 56 | mipmaps.add(new LocalBean(R.mipmap.other3, "4")); 57 | mipmaps.add(new LocalBean(R.mipmap.other4, "5")); 58 | mipmaps.add(new LocalBean(R.mipmap.other5, "6")); 59 | mipmaps.add(new LocalBean(R.mipmap.wangze3, "7")); 60 | mipmaps.add(new LocalBean(R.mipmap.wangze4, "8")); 61 | mipmaps.add(new LocalBean(R.mipmap.wangze5, "9")); 62 | mipmaps.add(new LocalBean(R.mipmap.wangze6, "10")); 63 | mipmaps.add(new LocalBean(R.mipmap.wangze7, "11")); 64 | mipmaps.add(new LocalBean(R.mipmap.wangze8, "12")); 65 | mipmaps.add(new LocalBean(R.mipmap.wangze9, "13")); 66 | mipmaps.add(new LocalBean(R.mipmap.wangze10, "14")); 67 | 68 | Comment.mipmaps = mipmaps; 69 | adapter.setDataList(mipmaps); 70 | adapter.setHasStableIds(true); 71 | //初始化布局管理器 72 | final GridLayoutManager lm = new GridLayoutManager(this, 2); 73 | //设置布局管理器 74 | recyclerView.setLayoutManager(lm); 75 | // recyclerView.addItemDecoration(new DividerGridItemDecoration(this)); 76 | recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { 77 | @Override 78 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 79 | outRect.set((int) getResources().getDimension(R.dimen.space_5), (int) getResources().getDimension(R.dimen.space_5), (int) getResources().getDimension(R.dimen.space_5), (int) getResources().getDimension(R.dimen.space_5)); 80 | } 81 | }); 82 | recyclerView.setAdapter(adapter); 83 | 84 | 85 | if (Build.VERSION.SDK_INT >= 22) { 86 | setExitSharedElementCallback(new SharedElementCallback() { 87 | @Override 88 | public void onMapSharedElements(List names, Map sharedElements) { 89 | if (bundle != null) { 90 | int i = bundle.getInt("index", 0); 91 | sharedElements.clear(); 92 | names.clear(); 93 | View itemView = lm.findViewByPosition(i); 94 | ImageView imageView = itemView.findViewById(R.id.imageView); 95 | //注意这里第二个参数,如果放置的是条目的item则动画不自然。放置对应的imageView则完美 96 | sharedElements.put(mipmaps.get(i).getTag(), imageView); 97 | bundle = null; 98 | } 99 | } 100 | }); 101 | } 102 | 103 | 104 | } 105 | 106 | @Override 107 | public void onClick(View view) { 108 | switch (view.getId()) { 109 | case R.id.imageView: 110 | int index = (int) view.getTag(R.id.imageView); 111 | Intent intent = new Intent(LocalMainActivity.this, LocalSecondActivity.class); 112 | intent.putExtra("index", index); 113 | 114 | if (Build.VERSION.SDK_INT >= 22) { 115 | ActivityOptionsCompat options = ActivityOptionsCompat 116 | .makeSceneTransitionAnimation(LocalMainActivity.this, view, mipmaps.get(index).getTag());// mAdapter.get(position).getUrl() 117 | startActivity(intent, options.toBundle()); 118 | } else { 119 | startActivity(intent); 120 | } 121 | break; 122 | } 123 | } 124 | 125 | 126 | @Override 127 | public void onActivityReenter(int resultCode, Intent data) { 128 | super.onActivityReenter(resultCode, data); 129 | bundle = new Bundle(data.getExtras()); 130 | } 131 | 132 | 133 | @Subscribe(threadMode = ThreadMode.MAIN) 134 | public void onbackEvent(CanScrollBean canScrollBean) {//这里用于列表元素共享的时候,列表下滑 135 | recyclerView.scrollToPosition(canScrollBean.getPosition()); 136 | } 137 | 138 | @Override 139 | protected void onDestroy() { 140 | super.onDestroy(); 141 | EventBus.getDefault().unregister(this); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/localdemo/LocalSecondActivity.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.localdemo; 2 | 3 | import android.annotation.TargetApi; 4 | import android.app.SharedElementCallback; 5 | import android.content.Intent; 6 | import android.os.Build; 7 | import android.os.Bundle; 8 | import android.support.annotation.Nullable; 9 | import android.support.v4.app.Fragment; 10 | import android.support.v4.app.FragmentStatePagerAdapter; 11 | import android.support.v4.view.ViewPager; 12 | import android.support.v7.app.AppCompatActivity; 13 | import android.view.View; 14 | 15 | import com.leo.myactivityoptions.Comment; 16 | import com.leo.myactivityoptions.R; 17 | import com.leo.myactivityoptions.localdemo.bean.CanScrollBean; 18 | 19 | import org.greenrobot.eventbus.EventBus; 20 | 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | import static com.leo.myactivityoptions.Comment.mipmaps; 25 | 26 | /** 27 | * Created by Administrator on 2018/4/17. 28 | */ 29 | 30 | public class LocalSecondActivity extends AppCompatActivity { 31 | 32 | private ViewPager mPager; 33 | private int index; 34 | private PagerAdapter adapter; 35 | 36 | @Override 37 | protected void onCreate(@Nullable Bundle savedInstanceState) { 38 | super.onCreate(savedInstanceState); 39 | setContentView(R.layout.activity_second_local); 40 | mPager = (ViewPager) findViewById(R.id.pager); 41 | index = (int) getIntent().getExtras().get("index"); 42 | supportPostponeEnterTransition();//延缓执行 然后在fragment里面的控件加载完成后start 43 | 44 | 45 | adapter = new PagerAdapter(); 46 | mPager.setAdapter(adapter); 47 | mPager.setCurrentItem(index); 48 | if (Build.VERSION.SDK_INT >= 22) { 49 | //这个可以看做个管道 每次进入和退出的时候都会进行调用 进入的时候获取到前面传来的共享元素的信息 50 | //退出的时候 把这些信息传递给前面的activity 51 | //同时向sharedElements里面put view,跟对view添加transitionname作用一样 52 | setEnterSharedElementCallback(new SharedElementCallback() { 53 | @Override 54 | public void onMapSharedElements(List names, Map sharedElements) { 55 | String url = mipmaps.get(mPager.getCurrentItem()).getTag(); 56 | LocalLargePicFragment fragment = (LocalLargePicFragment) adapter.instantiateItem(mPager, mPager.getCurrentItem()); 57 | sharedElements.clear(); 58 | sharedElements.put(url, fragment.getSharedElement()); 59 | } 60 | }); 61 | } 62 | 63 | mPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { 64 | @Override 65 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 66 | 67 | } 68 | 69 | @Override 70 | public void onPageSelected(int position) { 71 | CanScrollBean can = new CanScrollBean(); 72 | can.setPosition(position); 73 | EventBus.getDefault().post(can); 74 | } 75 | 76 | @Override 77 | public void onPageScrollStateChanged(int state) { 78 | 79 | } 80 | }); 81 | 82 | } 83 | 84 | 85 | @TargetApi(22) 86 | @Override 87 | public void supportFinishAfterTransition() { 88 | Intent data = new Intent(); 89 | data.putExtra("index", mPager.getCurrentItem()); 90 | setResult(RESULT_OK, data); 91 | super.supportFinishAfterTransition(); 92 | } 93 | 94 | 95 | @Override 96 | public void onBackPressed() { 97 | Intent data = new Intent(); 98 | data.putExtra("index", mPager.getCurrentItem()); 99 | setResult(RESULT_OK, data); 100 | super.supportFinishAfterTransition(); 101 | } 102 | 103 | private class PagerAdapter extends FragmentStatePagerAdapter { 104 | 105 | public PagerAdapter() { 106 | super(getSupportFragmentManager()); 107 | } 108 | 109 | @Override 110 | public int getCount() { 111 | return Comment.mipmaps.size(); 112 | } 113 | 114 | @Override 115 | public Fragment getItem(int position) { 116 | return LocalLargePicFragment.newFragment( 117 | position); 118 | } 119 | 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/localdemo/bean/CanScrollBean.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.localdemo.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | public class CanScrollBean implements Serializable { 6 | private int position; 7 | 8 | public int getPosition() { 9 | return position; 10 | } 11 | 12 | public void setPosition(int position) { 13 | this.position = position; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/localdemo/bean/LocalBean.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.localdemo.bean; 2 | 3 | import java.io.Serializable; 4 | 5 | public class LocalBean implements Serializable { 6 | private Integer mipmap; 7 | private String tag; 8 | 9 | public LocalBean(Integer mipmap, String tag) { 10 | this.mipmap = mipmap; 11 | this.tag = tag; 12 | } 13 | 14 | public Integer getMipmap() { 15 | return mipmap; 16 | } 17 | 18 | public void setMipmap(Integer mipmap) { 19 | this.mipmap = mipmap; 20 | } 21 | 22 | public String getTag() { 23 | return tag; 24 | } 25 | 26 | public void setTag(String tag) { 27 | this.tag = tag; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/utils/MyGlideModule.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.utils; 2 | 3 | import android.content.Context; 4 | 5 | import com.bumptech.glide.Glide; 6 | import com.bumptech.glide.GlideBuilder; 7 | import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool; 8 | import com.bumptech.glide.load.engine.cache.ExternalCacheDiskCacheFactory; 9 | import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory; 10 | import com.bumptech.glide.load.engine.cache.LruResourceCache; 11 | import com.bumptech.glide.load.model.GlideUrl; 12 | import com.bumptech.glide.module.GlideModule; 13 | 14 | import java.io.InputStream; 15 | 16 | import okhttp3.OkHttpClient; 17 | 18 | /** 19 | * Created by lihang on 2017/9/15. 20 | */ 21 | 22 | public class MyGlideModule implements GlideModule { 23 | 24 | int diskSize = 1024 * 1024 * 100; 25 | int memorySize = (int) (Runtime.getRuntime().maxMemory()) / 8; // 取1/8最大内存作为最大缓存 26 | 27 | 28 | @Override 29 | public void applyOptions(Context context, GlideBuilder builder) { 30 | 31 | //自定义图片质量 32 | // builder.setDecodeFormat(DecodeFormat.PREFER_ARGB_8888); 33 | 34 | 35 | // 下面这样配置的话,缓存会在 SDCard/Android/data/应用包名/cache/image_manager_disk_cache目录下 36 | //设置磁盘缓存 37 | // builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, SystemConst.merorySize)); 38 | 39 | // builder.setDiskCache( 40 | // new DiskLruCacheFactory("glide", 150 * 1024 * 1024)); 41 | // 42 | // builder.setMemoryCache(new LruResourceCache(150 * 1024 * 1024)); 43 | // builder.setBitmapPool(new LruBitmapPool(50 * 1024 * 1024)); 44 | 45 | 46 | // 如果需求修改缓存路径的话,需要增加一下参数即可(变为SDCard/Android/data/应用包名/cache/xiayu) 47 | //设置磁盘缓存大小 48 | // int size = 100 * 1024 * 1024; 49 | // String dir = "xiayu"; 50 | // //设置磁盘缓存 51 | // builder.setDiskCache(new ExternalCacheDiskCacheFactory(context,dir, size)); 52 | 53 | 54 | /** 55 | * 测试!! 56 | */ 57 | // 定义缓存大小和位置 58 | builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskSize)); //内存中 59 | builder.setDiskCache(new ExternalCacheDiskCacheFactory(context, "cache", diskSize)); //sd卡中 60 | 61 | 62 | // 自定义内存和图片池大小 63 | builder.setMemoryCache(new LruResourceCache(memorySize)); 64 | builder.setBitmapPool(new LruBitmapPool(memorySize)); 65 | 66 | 67 | } 68 | 69 | @Override 70 | public void registerComponents(Context context, Glide glide) { 71 | OkHttpClient.Builder builder = new OkHttpClient.Builder(); 72 | builder.addInterceptor(new ProgressInterceptor()); 73 | OkHttpClient okHttpClient = builder.build(); 74 | glide.register(GlideUrl.class, InputStream.class, new OkHttpGlideUrlLoader.Factory(okHttpClient)); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/utils/OkHttpFetcher.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.utils; 2 | 3 | import com.bumptech.glide.Priority; 4 | import com.bumptech.glide.load.data.DataFetcher; 5 | import com.bumptech.glide.load.model.GlideUrl; 6 | import com.bumptech.glide.util.ContentLengthInputStream; 7 | 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.util.Map; 11 | 12 | import okhttp3.OkHttpClient; 13 | import okhttp3.Request; 14 | import okhttp3.Response; 15 | import okhttp3.ResponseBody; 16 | 17 | /** 18 | * @author guolin 19 | * @since 2017/11/2 20 | */ 21 | public class OkHttpFetcher implements DataFetcher { 22 | 23 | private final OkHttpClient client; 24 | private final GlideUrl url; 25 | private InputStream stream; 26 | private ResponseBody responseBody; 27 | private volatile boolean isCancelled; 28 | 29 | public OkHttpFetcher(OkHttpClient client, GlideUrl url) { 30 | this.client = client; 31 | this.url = url; 32 | } 33 | 34 | @Override 35 | public InputStream loadData(Priority priority) throws Exception { 36 | Request.Builder requestBuilder = new Request.Builder() 37 | .url(url.toStringUrl()); 38 | for (Map.Entry headerEntry : url.getHeaders().entrySet()) { 39 | String key = headerEntry.getKey(); 40 | requestBuilder.addHeader(key, headerEntry.getValue()); 41 | } 42 | Request request = requestBuilder.build(); 43 | if (isCancelled) { 44 | return null; 45 | } 46 | Response response = client.newCall(request).execute(); 47 | responseBody = response.body(); 48 | if (!response.isSuccessful() || responseBody == null) { 49 | throw new IOException("Request failed with code: " + response.code()); 50 | } 51 | stream = ContentLengthInputStream.obtain(responseBody.byteStream(), 52 | responseBody.contentLength()); 53 | return stream; 54 | } 55 | 56 | @Override 57 | public void cleanup() { 58 | try { 59 | if (stream != null) { 60 | stream.close(); 61 | } 62 | if (responseBody != null) { 63 | responseBody.close(); 64 | } 65 | } catch (IOException e) { 66 | e.printStackTrace(); 67 | } 68 | } 69 | 70 | @Override 71 | public String getId() { 72 | return url.getCacheKey(); 73 | } 74 | 75 | @Override 76 | public void cancel() { 77 | isCancelled = true; 78 | } 79 | } -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/utils/OkHttpGlideUrlLoader.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.utils; 2 | 3 | import android.content.Context; 4 | 5 | import com.bumptech.glide.load.data.DataFetcher; 6 | import com.bumptech.glide.load.model.GenericLoaderFactory; 7 | import com.bumptech.glide.load.model.GlideUrl; 8 | import com.bumptech.glide.load.model.ModelLoader; 9 | import com.bumptech.glide.load.model.ModelLoaderFactory; 10 | 11 | import java.io.InputStream; 12 | 13 | import okhttp3.OkHttpClient; 14 | 15 | /** 16 | * @author guolin 17 | * @since 2017/11/2 18 | */ 19 | public class OkHttpGlideUrlLoader implements ModelLoader { 20 | 21 | private OkHttpClient okHttpClient; 22 | 23 | public static class Factory implements ModelLoaderFactory { 24 | 25 | private OkHttpClient client; 26 | 27 | public Factory() { 28 | } 29 | 30 | public Factory(OkHttpClient client) { 31 | this.client = client; 32 | } 33 | 34 | private synchronized OkHttpClient getOkHttpClient() { 35 | if (client == null) { 36 | client = new OkHttpClient(); 37 | } 38 | return client; 39 | } 40 | 41 | @Override 42 | public ModelLoader build(Context context, GenericLoaderFactory factories) { 43 | return new OkHttpGlideUrlLoader(getOkHttpClient()); 44 | } 45 | 46 | @Override 47 | public void teardown() { 48 | } 49 | } 50 | 51 | public OkHttpGlideUrlLoader(OkHttpClient client) { 52 | this.okHttpClient = client; 53 | } 54 | 55 | @Override 56 | public DataFetcher getResourceFetcher(GlideUrl model, int width, int height) { 57 | return new OkHttpFetcher(okHttpClient, model); 58 | } 59 | } -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/utils/ProgressInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.utils; 2 | 3 | import java.io.IOException; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import okhttp3.Interceptor; 8 | import okhttp3.Request; 9 | import okhttp3.Response; 10 | import okhttp3.ResponseBody; 11 | 12 | /** 13 | * @author guolin 14 | * @since 2017/11/5 15 | */ 16 | public class ProgressInterceptor implements Interceptor { 17 | 18 | static final Map LISTENER_MAP = new HashMap<>(); 19 | 20 | public static void addListener(String url, ProgressListener listener) { 21 | LISTENER_MAP.put(url, listener); 22 | } 23 | 24 | public static void removeListener(String url) { 25 | LISTENER_MAP.remove(url); 26 | } 27 | 28 | @Override 29 | public Response intercept(Chain chain) throws IOException { 30 | Request request = chain.request(); 31 | Response response = chain.proceed(request); 32 | String url = request.url().toString(); 33 | ResponseBody body = response.body(); 34 | Response newResponse = response.newBuilder().body(new ProgressResponseBody(url, body)).build(); 35 | return newResponse; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/utils/ProgressListener.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.utils; 2 | 3 | /** 4 | * @author guolin 5 | * @since 2017/11/5 6 | */ 7 | public interface ProgressListener { 8 | 9 | /** 10 | * 当下载进度发生变化时,会回调此方法。 11 | * @param progress 12 | * 当前的下载进度,参数值的范围是0-100。 13 | */ 14 | void onProgress(int progress); 15 | 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/utils/ProgressResponseBody.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.utils; 2 | 3 | import android.util.Log; 4 | 5 | import java.io.IOException; 6 | 7 | import okhttp3.MediaType; 8 | import okhttp3.ResponseBody; 9 | import okio.Buffer; 10 | import okio.BufferedSource; 11 | import okio.ForwardingSource; 12 | import okio.Okio; 13 | import okio.Source; 14 | 15 | /** 16 | * @author guolin 17 | * @since 2017/11/5 18 | */ 19 | public class ProgressResponseBody extends ResponseBody { 20 | 21 | private static final String TAG = "ProgressResponseBody"; 22 | 23 | private BufferedSource bufferedSource; 24 | 25 | private ResponseBody responseBody; 26 | 27 | private ProgressListener listener; 28 | 29 | public ProgressResponseBody(String url, ResponseBody responseBody) { 30 | this.responseBody = responseBody; 31 | listener = ProgressInterceptor.LISTENER_MAP.get(url); 32 | } 33 | 34 | @Override 35 | public MediaType contentType() { 36 | return responseBody.contentType(); 37 | } 38 | 39 | @Override 40 | public long contentLength() { 41 | return responseBody.contentLength(); 42 | } 43 | 44 | @Override 45 | public BufferedSource source() { 46 | if (bufferedSource == null) { 47 | bufferedSource = Okio.buffer(new ProgressSource(responseBody.source())); 48 | } 49 | return bufferedSource; 50 | } 51 | 52 | private class ProgressSource extends ForwardingSource { 53 | 54 | long totalBytesRead = 0; 55 | 56 | int currentProgress; 57 | 58 | ProgressSource(Source source) { 59 | super(source); 60 | } 61 | 62 | @Override 63 | public long read(Buffer sink, long byteCount) throws IOException { 64 | long bytesRead = super.read(sink, byteCount); 65 | long fullLength = responseBody.contentLength(); 66 | if (bytesRead == -1) { 67 | totalBytesRead = fullLength; 68 | } else { 69 | totalBytesRead += bytesRead; 70 | } 71 | int progress = (int) (100f * totalBytesRead / fullLength); 72 | Log.d(TAG, "download progress is " + progress); 73 | if (listener != null && progress != currentProgress) { 74 | listener.onProgress(progress); 75 | } 76 | if (listener != null && totalBytesRead == fullLength) { 77 | listener = null; 78 | } 79 | currentProgress = progress; 80 | return bytesRead; 81 | } 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/utils/UIUtil.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.utils; 2 | 3 | import android.content.Context; 4 | import android.view.WindowManager; 5 | 6 | /** 7 | * Created by lihang Leo on 2016/12/10. 8 | */ 9 | public class UIUtil { 10 | 11 | public static int getWidth(Context context) { 12 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 13 | int width = wm.getDefaultDisplay().getWidth(); 14 | return width; 15 | } 16 | 17 | /** 18 | * Dip to Px 19 | * 20 | * @param context 21 | * @param dipValue 22 | * @return 23 | */ 24 | public static int dip2px(Context context, float dipValue) { 25 | float scale = context.getResources().getDisplayMetrics().density; 26 | return (int) (dipValue * scale + 0.5f); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/leo/myactivityoptions/utils/Utils.java: -------------------------------------------------------------------------------- 1 | package com.leo.myactivityoptions.utils; 2 | 3 | import android.content.Context; 4 | import android.graphics.Bitmap; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.RectF; 9 | import android.graphics.drawable.BitmapDrawable; 10 | import android.graphics.drawable.Drawable; 11 | import android.support.annotation.ColorRes; 12 | import android.text.TextUtils; 13 | import android.util.DisplayMetrics; 14 | import android.view.WindowManager; 15 | 16 | import java.util.Collection; 17 | 18 | public class Utils { 19 | 20 | private static WindowManager windowManager; 21 | 22 | private static WindowManager getWindowManager(Context context) { 23 | if (windowManager == null) { 24 | windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 25 | } 26 | return windowManager; 27 | } 28 | 29 | public static float getDensity(Context context) { 30 | return context.getResources().getDisplayMetrics().density; 31 | } 32 | 33 | public static float getFontDensity(Context context) { 34 | return context.getResources().getDisplayMetrics().scaledDensity; 35 | } 36 | 37 | public static DisplayMetrics getDisplayMetrics(Context context) { 38 | DisplayMetrics displayMetrics = new DisplayMetrics(); 39 | getWindowManager(context).getDefaultDisplay().getMetrics(displayMetrics); 40 | return displayMetrics; 41 | } 42 | 43 | public static int dp2px(Context context, float dp) { 44 | return (int) (getDensity(context) * dp + 0.5f); 45 | } 46 | 47 | public static int px2dp(Context context, float px) { 48 | return (int) (px / getDensity(context) + 0.5f); 49 | } 50 | 51 | public static int sp2px(Context context, float sp) { 52 | return (int) (getFontDensity(context) * sp + 0.5f); 53 | } 54 | 55 | public static int px2sp(Context context, float px) { 56 | return (int) (px / getFontDensity(context) + 0.5f); 57 | } 58 | 59 | public static int getWindowWidth(Context context) { 60 | return getDisplayMetrics(context).widthPixels; 61 | } 62 | 63 | public static int getWindowHeight(Context context) { 64 | return getDisplayMetrics(context).heightPixels; 65 | } 66 | 67 | public static String getPathFormat(String path) { 68 | if (!TextUtils.isEmpty(path)) { 69 | int lastPeriodIndex = path.lastIndexOf('.'); 70 | if (lastPeriodIndex > 0 && lastPeriodIndex + 1 < path.length()) { 71 | String format = path.substring(lastPeriodIndex + 1); 72 | if (!TextUtils.isEmpty(format)) { 73 | return format.toLowerCase(); 74 | } 75 | } 76 | } 77 | return ""; 78 | } 79 | 80 | public static boolean isGif(String url) { 81 | return "gif".equals(getPathFormat(url)); 82 | } 83 | 84 | public static Bitmap getTextBitmap(Context context, int width, int height, int radius, String text, int textSize, @ColorRes int bgColor) { 85 | radius = dp2px(context, radius); 86 | Bitmap bitmap = Bitmap.createBitmap(dp2px(context, width), dp2px(context, height), Bitmap.Config.ARGB_8888); 87 | Canvas canvas = new Canvas(bitmap); 88 | RectF rect = new RectF(0, 0, canvas.getWidth(), canvas.getHeight()); 89 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 90 | paint.setColor(context.getResources().getColor(bgColor)); 91 | canvas.drawRoundRect(new RectF(0, 0, rect.width(), rect.height()), radius, radius, paint); 92 | paint.setColor(Color.WHITE); 93 | paint.setTextSize(dp2px(context, textSize)); 94 | paint.setTextAlign(Paint.Align.CENTER); 95 | Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt(); 96 | float baseline = (rect.bottom + rect.top - fontMetrics.bottom - fontMetrics.top) / 2; 97 | canvas.drawText(text, rect.centerX(), baseline, paint); 98 | return bitmap; 99 | } 100 | 101 | public static Drawable getTextDrawable(Context context, int width, int height, int radius, String text, int textSize, @ColorRes int bgColor) { 102 | return new BitmapDrawable(getTextBitmap(context, width, height, radius, text, textSize, bgColor)); 103 | } 104 | 105 | public static boolean isEmpty(Collection collection) { 106 | return collection == null || collection.isEmpty(); 107 | } 108 | 109 | public static int getSize(Collection collection) { 110 | return collection == null ? 0 : collection.size(); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_likewx.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_localmain.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_second.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_second_local.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_select.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | 19 | 20 |