├── .idea
├── .name
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── vcs.xml
├── modules.xml
├── libraries
│ ├── support_annotations_23_1_1.xml
│ ├── appcompat_v7_23_1_1.xml
│ └── support_v4_23_1_1.xml
├── runConfigurations.xml
├── gradle.xml
├── compiler.xml
└── misc.xml
├── app
├── .gitignore
├── screenshot
│ ├── pic1.png
│ ├── pic2.png
│ ├── pic3.png
│ ├── pic4.png
│ ├── pic5.png
│ ├── pic6.png
│ └── pic7.png
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ ├── dimens.xml
│ │ │ │ └── styles.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ └── layout
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── item_selectimg_show.xml
│ │ │ │ ├── pre_top_bar.xml
│ │ │ │ ├── activity_select_img.xml
│ │ │ │ ├── pre_bottom_bar.xml
│ │ │ │ └── layout_top_bar.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── lisdemo
│ │ │ │ ├── Test.java
│ │ │ │ ├── ShowSelectedImgs.java
│ │ │ │ ├── ShowSelectAdapter.java
│ │ │ │ ├── MyPreActivity2.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── MyPreActivity.java
│ │ └── AndroidManifest.xml
│ ├── test
│ │ └── java
│ │ │ └── com
│ │ │ └── lisdemo
│ │ │ └── ExampleUnitTest.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── lisdemo
│ │ └── ApplicationTest.java
├── proguard-rules.pro
├── build.gradle
└── app.iml
├── library-lis
├── .gitignore
├── src
│ └── main
│ │ ├── res
│ │ ├── drawable-hdpi
│ │ │ ├── default_img.png
│ │ │ ├── ic_pic_dir.png
│ │ │ ├── ic_select_no.png
│ │ │ ├── ic_selected.png
│ │ │ ├── ic_select_yes.png
│ │ │ ├── ic_show_more_flag_1.png
│ │ │ ├── ic_bottom_mark_press.9.png
│ │ │ └── ic_bottom_mark_normal.9.png
│ │ ├── drawable
│ │ │ ├── conver_bg_color.xml
│ │ │ └── select_bucket.xml
│ │ ├── values
│ │ │ └── lis_color.xml
│ │ ├── anim
│ │ │ ├── slide_bottom_in.xml
│ │ │ ├── slide_bottom_out.xml
│ │ │ ├── slide_top_in.xml
│ │ │ ├── slide_top_out.xml
│ │ │ ├── bucket_pop_in.xml
│ │ │ └── bucket_pop_out.xml
│ │ └── layout
│ │ │ ├── layout_preview_img.xml
│ │ │ ├── layout_bucket_pop.xml
│ │ │ ├── gridview_select_pic_item.xml
│ │ │ ├── activity_previewpager.xml
│ │ │ ├── lis_imglist_bottom_layout.xml
│ │ │ ├── lis_activity_img_list.xml
│ │ │ └── img_bucket_item.xml
│ │ ├── java
│ │ ├── com
│ │ │ └── cocolover2
│ │ │ │ └── lis
│ │ │ │ ├── interf
│ │ │ │ ├── OnImageClickListener.java
│ │ │ │ ├── OnPagerUpdateListener.java
│ │ │ │ └── OnSelectResultListener.java
│ │ │ │ ├── entity
│ │ │ │ ├── ImageBucket.java
│ │ │ │ └── ImageItem.java
│ │ │ │ ├── LISConstant.java
│ │ │ │ ├── utils
│ │ │ │ ├── ImageCache.java
│ │ │ │ └── ImageUtils.java
│ │ │ │ ├── view
│ │ │ │ ├── HackyViewPager.java
│ │ │ │ └── BounceBackViewPager.java
│ │ │ │ ├── activity
│ │ │ │ ├── LisSimplePreviewPagerActivity.java
│ │ │ │ ├── LisSimpleListImgsActivity.java
│ │ │ │ ├── LisBasePreviewPagerActivity.java
│ │ │ │ └── LisBaseListImgsActivity.java
│ │ │ │ ├── ShowImageView.java
│ │ │ │ ├── adapter
│ │ │ │ ├── ImageBucketAdapter.java
│ │ │ │ └── ImageGridAdapter.java
│ │ │ │ ├── AlbumHelper.java
│ │ │ │ └── LocalImageLoader.java
│ │ └── uk
│ │ │ └── co
│ │ │ └── senab
│ │ │ └── photoview
│ │ │ ├── gestures
│ │ │ ├── GestureDetector.java
│ │ │ ├── OnGestureListener.java
│ │ │ ├── VersionedGestureDetector.java
│ │ │ ├── FroyoGestureDetector.java
│ │ │ ├── EclairGestureDetector.java
│ │ │ └── CupcakeGestureDetector.java
│ │ │ ├── scrollerproxy
│ │ │ ├── IcsScroller.java
│ │ │ ├── ScrollerProxy.java
│ │ │ ├── PreGingerScroller.java
│ │ │ └── GingerScroller.java
│ │ │ ├── Compat.java
│ │ │ ├── DefaultOnDoubleTapListener.java
│ │ │ ├── PhotoView.java
│ │ │ └── IPhotoView.java
│ │ └── AndroidManifest.xml
├── build.gradle
├── proguard-rules.pro
└── library-lis.iml
├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── LisDemo.iml
├── README.md
├── gradlew.bat
├── gradlew
└── LICENSE
/.idea/.name:
--------------------------------------------------------------------------------
1 | LisDemo
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library-lis/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app',':library-lis'
2 |
--------------------------------------------------------------------------------
/app/screenshot/pic1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/screenshot/pic1.png
--------------------------------------------------------------------------------
/app/screenshot/pic2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/screenshot/pic2.png
--------------------------------------------------------------------------------
/app/screenshot/pic3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/screenshot/pic3.png
--------------------------------------------------------------------------------
/app/screenshot/pic4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/screenshot/pic4.png
--------------------------------------------------------------------------------
/app/screenshot/pic5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/screenshot/pic5.png
--------------------------------------------------------------------------------
/app/screenshot/pic6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/screenshot/pic6.png
--------------------------------------------------------------------------------
/app/screenshot/pic7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/screenshot/pic7.png
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LisDemo
3 |
4 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/library-lis/src/main/res/drawable-hdpi/default_img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/library-lis/src/main/res/drawable-hdpi/default_img.png
--------------------------------------------------------------------------------
/library-lis/src/main/res/drawable-hdpi/ic_pic_dir.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/library-lis/src/main/res/drawable-hdpi/ic_pic_dir.png
--------------------------------------------------------------------------------
/library-lis/src/main/res/drawable-hdpi/ic_select_no.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/library-lis/src/main/res/drawable-hdpi/ic_select_no.png
--------------------------------------------------------------------------------
/library-lis/src/main/res/drawable-hdpi/ic_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/library-lis/src/main/res/drawable-hdpi/ic_selected.png
--------------------------------------------------------------------------------
/library-lis/src/main/res/drawable-hdpi/ic_select_yes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/library-lis/src/main/res/drawable-hdpi/ic_select_yes.png
--------------------------------------------------------------------------------
/library-lis/src/main/res/drawable-hdpi/ic_show_more_flag_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/library-lis/src/main/res/drawable-hdpi/ic_show_more_flag_1.png
--------------------------------------------------------------------------------
/library-lis/src/main/res/drawable-hdpi/ic_bottom_mark_press.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/library-lis/src/main/res/drawable-hdpi/ic_bottom_mark_press.9.png
--------------------------------------------------------------------------------
/library-lis/src/main/res/drawable-hdpi/ic_bottom_mark_normal.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cocolove2/LISDemo/HEAD/library-lis/src/main/res/drawable-hdpi/ic_bottom_mark_normal.9.png
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/interf/OnImageClickListener.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.interf;
2 |
3 |
4 | public interface OnImageClickListener {
5 | void onImgClick();
6 | }
7 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/drawable/conver_bg_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/library-lis/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/interf/OnPagerUpdateListener.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.interf;
2 |
3 | public interface OnPagerUpdateListener {
4 | void onSelect(int position);
5 |
6 | void onDeleted(int position);
7 | }
8 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/interf/OnSelectResultListener.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.interf;
2 |
3 | /**
4 | * 已选择的图片路径
5 | */
6 | public interface OnSelectResultListener {
7 | void onSelectImgs(int selectedCount);
8 | }
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/values/lis_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #bc000000
4 | #ffcccccc
5 | #ff666666
6 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 21 11:34:03 PDT 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
7 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/drawable/select_bucket.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/anim/slide_bottom_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/anim/slide_bottom_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/anim/slide_top_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/anim/slide_top_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/anim/bucket_pop_in.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/entity/ImageBucket.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.entity;
2 |
3 | import java.util.ArrayList;
4 |
5 | /**
6 | * 图片文件夹实体类
7 | */
8 | public class ImageBucket{
9 | public int count = 0;
10 | public String bucketName;//文件夹名
11 | public ArrayList imageList;//文件夹下所有文件的绝对路径
12 | public boolean isSelected = false;//文件夹是否被选中
13 | }
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/anim/bucket_pop_out.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
10 |
--------------------------------------------------------------------------------
/app/src/test/java/com/lisdemo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.lisdemo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 |
15 | # Gradle files
16 | .gradle/
17 | build/
18 | /*/build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/lisdemo/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.lisdemo;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lisdemo/Test.java:
--------------------------------------------------------------------------------
1 | package com.lisdemo;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.os.Parcelable;
6 | import android.support.v7.app.AppCompatActivity;
7 |
8 | /**
9 | * Created by Administrator on 2015/12/22.
10 | */
11 | public class Test extends AppCompatActivity {
12 | @Override
13 | protected void onCreate(Bundle savedInstanceState) {
14 | super.onCreate(savedInstanceState);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_selectimg_show.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/libraries/support_annotations_23_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/pre_top_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/LISConstant.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis;
2 |
3 |
4 | public class LISConstant {
5 |
6 | public static final String ALL_IMG_BUCKET = "所有图片";
7 | public static final String ACTION_PRE = "com.cocolover2.lis.ACTION_preview";
8 | public static final String CATEGORY_SUFFIX = ".category.PREVIEW";
9 | // public static final String FLAG_PRE_SELECTED_IMGS = "pre_selected_imgs";
10 | //所要预览的图片的集合
11 | public static final String PRE_IMG_DATAS = "preview_imgs";
12 | //预览图片的起始位置
13 | public static final String PRE_IMG_START_POSITION = "preview_start_img_position";
14 | }
15 |
--------------------------------------------------------------------------------
/library-lis/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 |
9 | minSdkVersion 16
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | compile 'com.android.support:appcompat-v7:23.1.1'
25 | }
26 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\MySoftWare\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 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/library-lis/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\MySoftWare\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 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.lisdemo"
9 | minSdkVersion 16
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:23.1.1'
26 | compile project(':library-lis')
27 | }
28 |
--------------------------------------------------------------------------------
/.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/libraries/appcompat_v7_23_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_select_img.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
23 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/library-lis/src/main/res/layout/layout_preview_img.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
21 |
--------------------------------------------------------------------------------
/.idea/libraries/support_v4_23_1_1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/pre_bottom_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
24 |
--------------------------------------------------------------------------------
/LisDemo.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/layout/layout_bucket_pop.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
14 |
15 |
24 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/layout/gridview_select_pic_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
24 |
25 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/utils/ImageCache.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.utils;
2 |
3 | import android.graphics.Bitmap;
4 | import android.os.Build;
5 | import android.support.v4.util.LruCache;
6 |
7 | public class ImageCache {
8 | private static LruCache mCache;
9 |
10 | private ImageCache() {
11 | }
12 |
13 | public static LruCache getInstance() {
14 | if (mCache == null)
15 | synchronized (ImageCache.class) {
16 | if (mCache == null)
17 | mCache = new LruCache((int) Runtime.getRuntime().maxMemory() / 8) {
18 | @Override
19 | protected int sizeOf(String key, Bitmap value) {
20 | if (Build.VERSION.SDK_INT > 12)
21 | return value.getByteCount();
22 | else
23 | return value.getRowBytes() * value.getHeight();
24 | }
25 | };
26 | }
27 | return mCache;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_top_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
28 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/layout/activity_previewpager.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
12 |
13 |
17 |
18 |
19 |
23 |
24 |
29 |
30 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/gestures/GestureDetector.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview.gestures;
17 |
18 | import android.view.MotionEvent;
19 |
20 | public interface GestureDetector {
21 |
22 | public boolean onTouchEvent(MotionEvent ev);
23 |
24 | public boolean isScaling();
25 |
26 | public void setOnGestureListener(OnGestureListener listener);
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/gestures/OnGestureListener.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview.gestures;
17 |
18 | public interface OnGestureListener {
19 |
20 | public void onDrag(float dx, float dy);
21 |
22 | public void onFling(float startX, float startY, float velocityX,
23 | float velocityY);
24 |
25 | public void onScale(float scaleFactor, float focusX, float focusY);
26 |
27 | }
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/scrollerproxy/IcsScroller.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview.scrollerproxy;
17 |
18 | import android.annotation.TargetApi;
19 | import android.content.Context;
20 |
21 | @TargetApi(14)
22 | public class IcsScroller extends GingerScroller {
23 |
24 | public IcsScroller(Context context) {
25 | super(context);
26 | }
27 |
28 | @Override
29 | public boolean computeScrollOffset() {
30 | return mScroller.computeScrollOffset();
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ### 简介
2 | * library-lis是仿照微信本地图片选择的效果实现的一个库,包括图片选择和图片浏览效果可参考微信。
3 | * 开发者可以根据自己的需求灵活的定制自己的topLayout,bottomLayout。
4 |
5 | ###library-lisde简易UML类图
6 | 
7 | 
8 |
9 | ###demo运行效果图
10 | 
11 | 
12 | 
13 | 
14 | 
15 |
16 | ###[图片选择demo参考](https://github.com/cocolove2/LISDemo/blob/master/app/src/main/java/com/lisdemo/MainActivity.java)
17 |
18 | ###[图片预览demo参考](https://github.com/cocolove2/LISDemo/blob/master/app/src/main/java/com/lisdemo/MyPreActivity.java)
19 | * 图片预览的支持是使用隐式跳转。
20 | ```
21 |
22 |
23 | //your packagename+".category.PREVIEW"
24 |
25 |
26 |
27 | ```
28 | ##### 最近修改
29 | * 2015-12-27 加入图片浏览时,viewpager左右回弹效果
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/view/HackyViewPager.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.view;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.ViewPager;
5 | import android.util.AttributeSet;
6 | import android.util.Log;
7 | import android.view.MotionEvent;
8 |
9 | /**
10 | * Hacky fix for Issue #4 and
11 | * http://code.google.com/p/android/issues/detail?id=18990
12 | *
13 | * ScaleGestureDetector seems to mess up the touch events, which means that
14 | * ViewGroups which make use of onInterceptTouchEvent throw a lot of
15 | * IllegalArgumentException: pointerIndex out of range.
16 | *
17 | * There's not much I can do in my code for now, but we can mask the result by
18 | * just catching the problem and ignoring it.
19 | *
20 | * @author Chris Banes
21 | */
22 | public class HackyViewPager extends BounceBackViewPager {
23 |
24 |
25 | private static final String TAG = "HackyViewPager";
26 |
27 | public HackyViewPager(Context context) {
28 | super(context);
29 | }
30 |
31 | public HackyViewPager(Context context, AttributeSet attrs) {
32 | super(context, attrs);
33 | }
34 |
35 | @Override
36 | public boolean onInterceptTouchEvent(MotionEvent ev) {
37 | try {
38 | return super.onInterceptTouchEvent(ev);
39 | } catch (IllegalArgumentException e) {
40 | //不理会
41 | Log.e(TAG,"hacky viewpager error1");
42 | return false;
43 | }catch(ArrayIndexOutOfBoundsException e ){
44 | //不理会
45 | Log.e(TAG,"hacky viewpager error2");
46 | return false;
47 | }
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/entity/ImageItem.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.entity;
2 |
3 | import android.os.Parcel;
4 | import android.os.Parcelable;
5 |
6 | /**
7 | * 图片实体类
8 | */
9 | public class ImageItem implements Parcelable {
10 | public int imageId;
11 | public String imagePath;//原图的路径
12 | public long imageSize;
13 | public long createTime;
14 | public boolean isSelected;
15 |
16 | @Override
17 | public int describeContents() {
18 | return 0;
19 | }
20 |
21 | @Override
22 | public void writeToParcel(Parcel dest, int flags) {
23 | dest.writeInt(imageId);
24 | dest.writeString(imagePath);
25 | dest.writeLong(imageSize);
26 | dest.writeLong(createTime);
27 | dest.writeByte((byte) (isSelected ? 1 : 0));
28 | }
29 |
30 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
31 | @Override
32 | public ImageItem createFromParcel(Parcel source) {
33 | //读取要和写入的顺序一致
34 | ImageItem item = new ImageItem();
35 | item.imageId = source.readInt();
36 | item.imagePath = source.readString();
37 | item.imageSize = source.readLong();
38 | item.createTime = source.readLong();
39 | item.isSelected = (source.readByte() != 0);
40 | return item;
41 | }
42 |
43 | @Override
44 | public ImageItem[] newArray(int size) {
45 | return new ImageItem[size];
46 | }
47 | };
48 | }
49 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lisdemo/ShowSelectedImgs.java:
--------------------------------------------------------------------------------
1 | package com.lisdemo;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v7.app.AppCompatActivity;
7 | import android.view.View;
8 | import android.widget.Button;
9 | import android.widget.GridView;
10 |
11 | import com.cocolover2.lis.entity.ImageItem;
12 |
13 | import java.util.ArrayList;
14 |
15 |
16 | public class ShowSelectedImgs extends AppCompatActivity {
17 | private ArrayList mDatas = new ArrayList<>();
18 | private Button modifyBtn;
19 | private GridView mGridView;
20 | ShowSelectAdapter adapter;
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_select_img);
26 | modifyBtn = (Button) findViewById(R.id.select_img_modify_btn);
27 | mGridView = (GridView) findViewById(R.id.select_img_gv);
28 | adapter = new ShowSelectAdapter(this, mDatas);
29 | mGridView.setAdapter(adapter);
30 | modifyBtn.setOnClickListener(new View.OnClickListener() {
31 | @Override
32 | public void onClick(View v) {
33 | MainActivity.actionIntent(ShowSelectedImgs.this, 9 - mDatas.size(), 1);
34 | }
35 | });
36 | }
37 |
38 | @Override
39 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
40 | if (requestCode == 1 && data != null) {
41 | final ArrayList tmp = data.getStringArrayListExtra("datas");
42 | mDatas.addAll(tmp);
43 | adapter.notifyDataSetChanged();
44 | }
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/gestures/VersionedGestureDetector.java:
--------------------------------------------------------------------------------
1 | package uk.co.senab.photoview.gestures;
2 |
3 | /*******************************************************************************
4 | * Copyright 2011, 2012 Chris Banes.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | *******************************************************************************/
18 |
19 | import android.content.Context;
20 | import android.os.Build;
21 |
22 | public final class VersionedGestureDetector {
23 |
24 | public static GestureDetector newInstance(Context context,
25 | OnGestureListener listener) {
26 | final int sdkVersion = Build.VERSION.SDK_INT;
27 | GestureDetector detector;
28 |
29 | if (sdkVersion < Build.VERSION_CODES.ECLAIR) {
30 | detector = new CupcakeGestureDetector(context);
31 | } else if (sdkVersion < Build.VERSION_CODES.FROYO) {
32 | detector = new EclairGestureDetector(context);
33 | } else {
34 | detector = new FroyoGestureDetector(context);
35 | }
36 |
37 | detector.setOnGestureListener(listener);
38 |
39 | return detector;
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/library-lis/src/main/res/layout/lis_imglist_bottom_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
14 |
15 |
23 |
24 |
33 |
34 |
35 |
44 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/utils/ImageUtils.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.utils;
2 |
3 | import android.graphics.Bitmap;
4 | import android.graphics.BitmapFactory;
5 | import android.text.TextUtils;
6 |
7 | import java.io.File;
8 |
9 | public class ImageUtils {
10 | private ImageUtils() {
11 | throw new UnsupportedOperationException("cannot be instantiated");
12 | }
13 |
14 | /**
15 | * 压缩图片的像素
16 | *
17 | * @param path
18 | * @param requestWidth
19 | * @param requestHeight
20 | * @return
21 | */
22 | public static Bitmap compressImgBySize(String path, int requestWidth, int requestHeight) {
23 | if (null == path || TextUtils.isEmpty(path) || !new File(path).exists())
24 | return null;
25 | //第一次解析图片的时候将inJustDecodeBounds设置为true,来获取图片的大小
26 | BitmapFactory.Options options = new BitmapFactory.Options();
27 | options.inJustDecodeBounds = true;
28 | BitmapFactory.decodeFile(path, options);
29 | options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight);
30 | options.inJustDecodeBounds = false;
31 | return BitmapFactory.decodeFile(path, options);
32 | }
33 |
34 | private static int calculateInSampleSize(BitmapFactory.Options options, int requestWidth, int requestHeight) {
35 | int width = options.outWidth;
36 | int height = options.outHeight;
37 | int inSampleSize = 1;
38 | if (width > requestWidth || height > requestHeight) {
39 | final int heightRatio = Math.round((float) height / (float) requestHeight);
40 | final int widthRatio = Math.round((float) width / (float) requestWidth);
41 | inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
42 | }
43 | return inSampleSize;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/scrollerproxy/ScrollerProxy.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview.scrollerproxy;
17 |
18 | import android.content.Context;
19 | import android.os.Build.VERSION;
20 | import android.os.Build.VERSION_CODES;
21 |
22 | public abstract class ScrollerProxy {
23 |
24 | public static ScrollerProxy getScroller(Context context) {
25 | if (VERSION.SDK_INT < VERSION_CODES.GINGERBREAD) {
26 | return new PreGingerScroller(context);
27 | } else if (VERSION.SDK_INT < VERSION_CODES.ICE_CREAM_SANDWICH) {
28 | return new GingerScroller(context);
29 | } else {
30 | return new IcsScroller(context);
31 | }
32 | }
33 |
34 | public abstract boolean computeScrollOffset();
35 |
36 | public abstract void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY,
37 | int maxY, int overX, int overY);
38 |
39 | public abstract void forceFinished(boolean finished);
40 |
41 | public abstract boolean isFinished();
42 |
43 | public abstract int getCurrX();
44 |
45 | public abstract int getCurrY();
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/layout/lis_activity_img_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
16 |
17 |
28 |
29 |
34 |
35 |
39 |
40 |
41 |
42 |
43 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lisdemo/ShowSelectAdapter.java:
--------------------------------------------------------------------------------
1 | package com.lisdemo;
2 |
3 | import android.content.Context;
4 | import android.graphics.BitmapFactory;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.BaseAdapter;
9 | import android.widget.ImageView;
10 |
11 | import com.cocolover2.lis.LocalImageLoader;
12 | import com.cocolover2.lis.entity.ImageItem;
13 |
14 | import java.util.ArrayList;
15 |
16 | public class ShowSelectAdapter extends BaseAdapter {
17 | private ArrayList data;
18 | private Context context;
19 |
20 | public ShowSelectAdapter(Context context, ArrayList data) {
21 | this.context = context;
22 | this.data = data;
23 | }
24 |
25 | @Override
26 | public int getCount() {
27 | return data == null ? 0 : data.size();
28 | }
29 |
30 | @Override
31 | public Object getItem(int position) {
32 | return data.get(position);
33 | }
34 |
35 | @Override
36 | public long getItemId(int position) {
37 | return position;
38 | }
39 |
40 | @Override
41 | public View getView(int position, View convertView, ViewGroup parent) {
42 | ViewHolder vh;
43 | if (convertView == null) {
44 | vh = new ViewHolder();
45 | convertView = LayoutInflater.from(context).inflate(R.layout.item_selectimg_show, null);
46 | vh.iv = (ImageView) convertView.findViewById(R.id.item_selectimg);
47 | convertView.setTag(vh);
48 | } else {
49 | vh = (ViewHolder) convertView.getTag();
50 | }
51 | vh.iv.setOnClickListener(new View.OnClickListener() {
52 | @Override
53 | public void onClick(View v) {
54 | MyPreActivity2.actionIntent(context,data);
55 | }
56 | });
57 | LocalImageLoader.getInstance().loadImage(data.get(position), vh.iv, R.drawable.default_img);
58 | return convertView;
59 | }
60 |
61 | static class ViewHolder {
62 | ImageView iv;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/scrollerproxy/PreGingerScroller.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview.scrollerproxy;
17 |
18 | import android.content.Context;
19 | import android.widget.Scroller;
20 |
21 | public class PreGingerScroller extends ScrollerProxy {
22 |
23 | private final Scroller mScroller;
24 |
25 | public PreGingerScroller(Context context) {
26 | mScroller = new Scroller(context);
27 | }
28 |
29 | @Override
30 | public boolean computeScrollOffset() {
31 | return mScroller.computeScrollOffset();
32 | }
33 |
34 | @Override
35 | public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,
36 | int overX, int overY) {
37 | mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);
38 | }
39 |
40 | @Override
41 | public void forceFinished(boolean finished) {
42 | mScroller.forceFinished(finished);
43 | }
44 |
45 | public boolean isFinished() {
46 | return mScroller.isFinished();
47 | }
48 |
49 | @Override
50 | public int getCurrX() {
51 | return mScroller.getCurrX();
52 | }
53 |
54 | @Override
55 | public int getCurrY() {
56 | return mScroller.getCurrY();
57 | }
58 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lisdemo/MyPreActivity2.java:
--------------------------------------------------------------------------------
1 | package com.lisdemo;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v4.app.Fragment;
7 | import android.view.View;
8 | import android.widget.ImageView;
9 | import android.widget.TextView;
10 |
11 | import com.cocolover2.lis.LISConstant;
12 | import com.cocolover2.lis.ShowImageView;
13 | import com.cocolover2.lis.activity.LisSimplePreviewPagerActivity;
14 | import com.cocolover2.lis.entity.ImageItem;
15 | import com.cocolover2.lis.interf.OnPagerUpdateListener;
16 |
17 | import java.util.ArrayList;
18 |
19 | public class MyPreActivity2 extends LisSimplePreviewPagerActivity {
20 | private TextView topTitle;
21 |
22 | @Override
23 | public int getTopBarLayoutId() {
24 | return R.layout.pre_top_bar;
25 | }
26 |
27 | @Override
28 | public int getBottomLayoutId() {
29 | return 0;
30 | }
31 |
32 | @Override
33 | public void onMyCreate(Bundle savedInstanceState) {
34 | topTitle = (TextView) findViewById(R.id.pre_top_bar_title);
35 | topTitle.setText("(" + (getStartPos() + 1) + "/" + getAllDatasSize() + ")");
36 | setOnPagerUpdateListener(pagerSelectListener);
37 | }
38 |
39 | @Override
40 | public Fragment showContentFragment(String content) {
41 | ShowImageView fragment = ShowImageView.newInstance(content);
42 | fragment.setOnImgClickListener(this);
43 | return fragment;
44 | }
45 |
46 | private OnPagerUpdateListener pagerSelectListener = new OnPagerUpdateListener() {
47 | @Override
48 | public void onSelect(int position) {
49 | topTitle.setText("(" + (position + 1) + "/" + getAllDatasSize() + ")");
50 | }
51 |
52 | @Override
53 | public void onDeleted(int position) {
54 |
55 | }
56 | };
57 |
58 | public static void actionIntent(Context context, ArrayList data) {
59 | context.startActivity(new Intent(context, MyPreActivity2.class).putStringArrayListExtra(LISConstant.PRE_IMG_DATAS, data));
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/library-lis/src/main/res/layout/img_bucket_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
15 |
16 |
23 |
24 |
25 |
32 |
33 |
38 |
39 |
44 |
45 |
46 |
55 |
56 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/activity/LisSimplePreviewPagerActivity.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.activity;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.widget.Toast;
5 |
6 | import com.cocolover2.lis.AlbumHelper;
7 | import com.cocolover2.lis.ShowImageView;
8 | import com.cocolover2.lis.entity.ImageItem;
9 | import com.cocolover2.lis.interf.OnImageClickListener;
10 |
11 |
12 | public abstract class LisSimplePreviewPagerActivity extends LisBasePreviewPagerActivity
13 | implements OnImageClickListener {
14 | final long PER_MB = 1024 * 1024;
15 | final long PER_KB = 1024;
16 |
17 | //针对本地图片
18 | protected void removeSelectItem(ImageItem item) {
19 | AlbumHelper.removeItem(item);
20 | item.isSelected = false;
21 | }
22 |
23 | protected boolean addToSelectList(ImageItem item) {
24 | if (AlbumHelper.getHasSelectCount() >= AlbumHelper.getMaxSize()) {
25 | item.isSelected = false;
26 | Toast.makeText(this, "最多选择" + AlbumHelper.getMaxSize() + "张图片", Toast.LENGTH_SHORT).show();
27 | return false;
28 | }
29 | item.isSelected = true;
30 | return AlbumHelper.addtoSelectImgs(item);
31 | }
32 |
33 | protected String getSelectImgsSize() {
34 | int size = 0;
35 | for (ImageItem i : AlbumHelper.getHasSelectImgs()) {
36 | size += i.imageSize;
37 | }
38 | if (size < PER_KB) {//小于1KB
39 | return size + "B";
40 | }
41 | if (size < PER_MB) {
42 | return size / PER_KB + "KB";
43 | }
44 | return size / PER_MB + "MB";
45 | }
46 |
47 | //针对本地图片(其他的展示界面重写该方法)
48 | @Override
49 | public Fragment showContentFragment(T content) {
50 | if (content instanceof ImageItem) {
51 | ShowImageView fragment = ShowImageView.newInstance(((ImageItem) content).imagePath);
52 | fragment.setOnImgClickListener(this);
53 | return fragment;
54 | }
55 | return null;
56 | }
57 |
58 |
59 |
60 | @Override
61 | public void onImgClick() {
62 | if (isShowTopBottom) {
63 | hideTopAndBottomLayout();
64 | } else {
65 | showTopAndBottomLayout();
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/app/src/main/java/com/lisdemo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.lisdemo;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.view.View;
8 | import android.widget.Button;
9 | import android.widget.TextView;
10 |
11 | import com.cocolover2.lis.LISConstant;
12 | import com.cocolover2.lis.activity.LisSimpleListImgsActivity;
13 | import com.cocolover2.lis.entity.ImageItem;
14 |
15 | import java.util.ArrayList;
16 |
17 | public class MainActivity extends LisSimpleListImgsActivity {
18 | TextView mTextView;
19 | Button sureBtn;
20 | int maxSize;
21 |
22 | @Override
23 | public int getTopLayoutId() {
24 | return R.layout.layout_top_bar;
25 | }
26 |
27 | @Override
28 | public void onMyCreate(Bundle savedInstanceState) {
29 | super.onMyCreate(savedInstanceState);
30 | mTextView = (TextView) findViewById(R.id.top_bar_tv);
31 | sureBtn = (Button) findViewById(R.id.layout_top_bar_sure);
32 | mTextView.setText("我是topbar");
33 | setIsPreView(true);
34 | maxSize = getIntent().getIntExtra("maxSize", 0);
35 | setMaxSize(maxSize);
36 |
37 | sureBtn.setOnClickListener(new View.OnClickListener() {
38 | @Override
39 | public void onClick(View v) {
40 | Intent i = getIntent().putStringArrayListExtra("datas", getSelectImgPaths());
41 | setResult(RESULT_OK, i);
42 | finish();
43 | }
44 | });
45 | }
46 |
47 | @Override
48 | protected void onStart() {
49 | super.onStart();
50 | if (getSelectImgs() != null) {
51 | if (getSelectImgs().size() == 0)
52 | sureBtn.setText("确定");
53 | else {
54 | sureBtn.setText("确定(" + getSelectImgs().size() + "/" + maxSize + ")");
55 | }
56 | }
57 | }
58 |
59 | @Override
60 | public void onSelectImgs(int selectedCount) {
61 | super.onSelectImgs(selectedCount);
62 | sureBtn.setText("确定(" + getSelectImgs().size() + "/" + maxSize + ")");
63 | }
64 |
65 | public static void actionIntent(Activity context, int maxSize, int requestCode) {
66 | context.startActivityForResult(new Intent(context, MainActivity.class)
67 | .putExtra("maxSize", maxSize), requestCode);
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/Compat.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview;
17 |
18 | import android.annotation.TargetApi;
19 | import android.os.Build;
20 | import android.os.Build.VERSION;
21 | import android.os.Build.VERSION_CODES;
22 | import android.view.MotionEvent;
23 | import android.view.View;
24 |
25 | public class Compat {
26 |
27 | private static final int SIXTY_FPS_INTERVAL = 1000 / 60;
28 |
29 | public static void postOnAnimation(View view, Runnable runnable) {
30 | if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
31 | postOnAnimationJellyBean(view, runnable);
32 | } else {
33 | view.postDelayed(runnable, SIXTY_FPS_INTERVAL);
34 | }
35 | }
36 |
37 | @TargetApi(16)
38 | private static void postOnAnimationJellyBean(View view, Runnable runnable) {
39 | view.postOnAnimation(runnable);
40 | }
41 |
42 | public static int getPointerIndex(int action) {
43 | if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB)
44 | return getPointerIndexHoneyComb(action);
45 | else
46 | return getPointerIndexEclair(action);
47 | }
48 |
49 | @SuppressWarnings("deprecation")
50 | @TargetApi(VERSION_CODES.ECLAIR)
51 | private static int getPointerIndexEclair(int action) {
52 | return (action & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
53 | }
54 |
55 | @TargetApi(VERSION_CODES.HONEYCOMB)
56 | private static int getPointerIndexHoneyComb(int action) {
57 | return (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/scrollerproxy/GingerScroller.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview.scrollerproxy;
17 |
18 | import android.annotation.TargetApi;
19 | import android.content.Context;
20 | import android.widget.OverScroller;
21 |
22 | @TargetApi(9)
23 | public class GingerScroller extends ScrollerProxy {
24 |
25 | protected final OverScroller mScroller;
26 | private boolean mFirstScroll = false;
27 |
28 | public GingerScroller(Context context) {
29 | mScroller = new OverScroller(context);
30 | }
31 |
32 | @Override
33 | public boolean computeScrollOffset() {
34 | // Workaround for first scroll returning 0 for the direction of the edge it hits.
35 | // Simply recompute values.
36 | if (mFirstScroll) {
37 | mScroller.computeScrollOffset();
38 | mFirstScroll = false;
39 | }
40 | return mScroller.computeScrollOffset();
41 | }
42 |
43 | @Override
44 | public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY,
45 | int overX, int overY) {
46 | mScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, overX, overY);
47 | }
48 |
49 | @Override
50 | public void forceFinished(boolean finished) {
51 | mScroller.forceFinished(finished);
52 | }
53 |
54 | @Override
55 | public boolean isFinished() {
56 | return mScroller.isFinished();
57 | }
58 |
59 | @Override
60 | public int getCurrX() {
61 | return mScroller.getCurrX();
62 | }
63 |
64 | @Override
65 | public int getCurrY() {
66 | return mScroller.getCurrY();
67 | }
68 | }
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/ShowImageView.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis;
2 |
3 | import android.graphics.Bitmap;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import com.cocolover2.lis.interf.OnImageClickListener;
12 | import com.cocolover2.lis.utils.ImageCache;
13 | import com.cocolover2.lis.utils.ImageUtils;
14 |
15 | import uk.co.senab.photoview.PhotoView;
16 | import uk.co.senab.photoview.PhotoViewAttacher;
17 |
18 |
19 | public class ShowImageView extends Fragment {
20 | private String key_prefix = "big_img_";
21 | private PhotoView imageView;
22 |
23 | @Nullable
24 | @Override
25 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
26 | return inflater.inflate(R.layout.layout_preview_img, container, false);
27 | }
28 |
29 | Bitmap bp;
30 |
31 | @Override
32 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
33 | super.onActivityCreated(savedInstanceState);
34 | if (getView() != null) {
35 | imageView = (PhotoView) getView().findViewById(R.id.layout_preview_img_img);
36 | }
37 | final String url = getArguments().getString("imagePath");
38 | if (ImageCache.getInstance().get(key_prefix + url) == null) {
39 | bp = ImageUtils.compressImgBySize(url, 480, 800);
40 | ImageCache.getInstance().put(key_prefix + url, bp);
41 | } else {
42 | bp = ImageCache.getInstance().get(key_prefix + url);
43 | }
44 |
45 |
46 | imageView.setImageBitmap(bp);
47 | imageView.setOnPhotoTapListener(new PhotoViewAttacher.OnPhotoTapListener() {
48 | @Override
49 | public void onPhotoTap(View view, float x, float y) {
50 | if (listener != null)
51 | listener.onImgClick();
52 | }
53 | });
54 | }
55 |
56 |
57 | public static ShowImageView newInstance(String imgPath) {
58 | ShowImageView fragment = new ShowImageView();
59 | Bundle bundle = new Bundle();
60 | bundle.putString("imagePath", imgPath);
61 | fragment.setArguments(bundle);
62 | return fragment;
63 | }
64 |
65 | private OnImageClickListener listener;
66 |
67 | public void setOnImgClickListener(OnImageClickListener listener) {
68 | this.listener = listener;
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/gestures/FroyoGestureDetector.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview.gestures;
17 |
18 | import android.annotation.TargetApi;
19 | import android.content.Context;
20 | import android.view.MotionEvent;
21 | import android.view.ScaleGestureDetector;
22 |
23 | @TargetApi(8)
24 | public class FroyoGestureDetector extends EclairGestureDetector {
25 |
26 | protected final ScaleGestureDetector mDetector;
27 |
28 | public FroyoGestureDetector(Context context) {
29 | super(context);
30 | ScaleGestureDetector.OnScaleGestureListener mScaleListener = new ScaleGestureDetector.OnScaleGestureListener() {
31 |
32 | @Override
33 | public boolean onScale(ScaleGestureDetector detector) {
34 | float scaleFactor = detector.getScaleFactor();
35 |
36 | if (Float.isNaN(scaleFactor) || Float.isInfinite(scaleFactor))
37 | return false;
38 |
39 | mListener.onScale(scaleFactor,
40 | detector.getFocusX(), detector.getFocusY());
41 | return true;
42 | }
43 |
44 | @Override
45 | public boolean onScaleBegin(ScaleGestureDetector detector) {
46 | return true;
47 | }
48 |
49 | @Override
50 | public void onScaleEnd(ScaleGestureDetector detector) {
51 | // NO-OP
52 | }
53 | };
54 | mDetector = new ScaleGestureDetector(context, mScaleListener);
55 | }
56 |
57 | @Override
58 | public boolean isScaling() {
59 | return mDetector.isInProgress();
60 | }
61 |
62 | @Override
63 | public boolean onTouchEvent(MotionEvent ev) {
64 | mDetector.onTouchEvent(ev);
65 | return super.onTouchEvent(ev);
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 1.8
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/adapter/ImageBucketAdapter.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.adapter;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.BaseAdapter;
9 | import android.widget.ImageView;
10 | import android.widget.TextView;
11 |
12 |
13 | import com.cocolover2.lis.LocalImageLoader;
14 | import com.cocolover2.lis.R;
15 | import com.cocolover2.lis.entity.ImageBucket;
16 |
17 | import java.util.ArrayList;
18 |
19 |
20 | public class ImageBucketAdapter extends BaseAdapter {
21 |
22 | private ArrayList bucketList;
23 | private Context context;
24 |
25 | public ImageBucketAdapter(Context context, ArrayList bucketList) {
26 | this.context = context;
27 | this.bucketList = bucketList;
28 | }
29 |
30 | @Override
31 | public int getCount() {
32 | return bucketList == null ? 0 : bucketList.size();
33 | }
34 |
35 | @Override
36 | public Object getItem(int position) {
37 | return bucketList.get(position);
38 | }
39 |
40 | @Override
41 | public long getItemId(int position) {
42 | return position;
43 | }
44 |
45 | @SuppressLint("InflateParams")
46 | @Override
47 | public View getView(int position, View convertView, ViewGroup parent) {
48 | ImageBucket bucket = bucketList.get(position);
49 | ViewHolder vh ;
50 | if (convertView == null) {
51 | vh = new ViewHolder();
52 | convertView = LayoutInflater.from(context).inflate(
53 | R.layout.img_bucket_item, null);
54 | vh.frontConver = (ImageView) convertView
55 | .findViewById(R.id.img_bucket_item_img);
56 | vh.chooseFlag = (ImageView) convertView
57 | .findViewById(R.id.img_bucket_item_choose_flag);
58 | vh.bucketName = (TextView) convertView
59 | .findViewById(R.id.img_bucket_item_name);
60 | vh.countNum = (TextView) convertView
61 | .findViewById(R.id.img_bucket_item_num);
62 | convertView.setTag(vh);
63 | } else {
64 | vh = (ViewHolder) convertView.getTag();
65 | }
66 | if (bucket.isSelected)
67 | vh.chooseFlag.setImageResource(R.drawable.ic_selected);
68 | else
69 | vh.chooseFlag.setImageBitmap(null);
70 |
71 |
72 | vh.bucketName.setText(bucket.bucketName);
73 | vh.countNum.setText(bucket.count + "张");
74 | LocalImageLoader.getInstance().loadImage(bucket.imageList.get(0).imagePath, vh.frontConver,0);
75 | return convertView;
76 | }
77 |
78 | static class ViewHolder {
79 | ImageView frontConver;
80 | ImageView chooseFlag;
81 | TextView bucketName;
82 | TextView countNum;
83 | }
84 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/lisdemo/MyPreActivity.java:
--------------------------------------------------------------------------------
1 | package com.lisdemo;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 | import android.widget.ImageView;
6 | import android.widget.TextView;
7 |
8 | import com.cocolover2.lis.interf.OnPagerUpdateListener;
9 | import com.cocolover2.lis.activity.LisSimplePreviewPagerActivity;
10 | import com.cocolover2.lis.entity.ImageItem;
11 |
12 | public class MyPreActivity extends LisSimplePreviewPagerActivity {
13 | private TextView topTitle;
14 | private ImageView select;
15 | private TextView sizeTv;
16 | ImageItem mItem;
17 | private int currentPos;
18 |
19 | @Override
20 | public int getTopBarLayoutId() {
21 | return R.layout.pre_top_bar;
22 | }
23 |
24 | @Override
25 | public int getBottomLayoutId() {
26 | return R.layout.pre_bottom_bar;
27 | }
28 |
29 | @Override
30 | public void onMyCreate(Bundle savedInstanceState) {
31 | topTitle = (TextView) findViewById(R.id.pre_top_bar_title);
32 | sizeTv = (TextView) findViewById(R.id.pre_bottom_bar_size);
33 | select = (ImageView) findViewById(R.id.pre_bottom_bar_select);
34 | topTitle.setText("(" + (getStartPos() + 1) + "/" + getAllDatasSize() + ")");
35 | currentPos = getStartPos();
36 | mItem = getItem(currentPos);
37 | updateBottom();
38 | select.setOnClickListener(new View.OnClickListener() {
39 | @Override
40 | public void onClick(View v) {
41 | if (mItem.isSelected) {
42 | removeSelectItem(mItem);
43 | sizeTv.setVisibility(View.INVISIBLE);
44 | select.setImageResource(R.drawable.ic_select_no);
45 | } else {
46 | if (addToSelectList(mItem)) {
47 | select.setImageResource(R.drawable.ic_select_yes);
48 | sizeTv.setVisibility(View.VISIBLE);
49 | sizeTv.setText(getSelectImgsSize());
50 | }
51 | }
52 | }
53 | });
54 | setOnPagerUpdateListener(pagerSelectListener);
55 | }
56 |
57 | private void updateBottom() {
58 | if (mItem.isSelected) {
59 | sizeTv.setVisibility(View.VISIBLE);
60 | sizeTv.setText(getSelectImgsSize());
61 | select.setImageResource(R.drawable.ic_select_yes);
62 | } else {
63 | sizeTv.setVisibility(View.INVISIBLE);
64 | select.setImageResource(R.drawable.ic_select_no);
65 | }
66 | }
67 |
68 | private OnPagerUpdateListener pagerSelectListener = new OnPagerUpdateListener() {
69 | @Override
70 | public void onSelect(int position) {
71 | currentPos = position;
72 | mItem = getItem(position);
73 | updateBottom();
74 | topTitle.setText("(" + (position + 1) + "/" + getAllDatasSize() + ")");
75 | }
76 |
77 | @Override
78 | public void onDeleted(int position) {
79 |
80 | }
81 | };
82 |
83 | }
84 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/view/BounceBackViewPager.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.view;
2 |
3 | import android.content.Context;
4 | import android.graphics.Rect;
5 | import android.support.v4.view.ViewPager;
6 | import android.util.AttributeSet;
7 | import android.util.Log;
8 | import android.view.MotionEvent;
9 | import android.view.animation.DecelerateInterpolator;
10 | import android.view.animation.TranslateAnimation;
11 |
12 | public class BounceBackViewPager extends ViewPager {
13 |
14 | private Rect mRect = new Rect();//用来记录初始位置
15 | private boolean handleDefault = true;//处理Viewpager默认情况标志
16 | private float preX = 0f;
17 | private static final float RATIO = 0.8f;//摩擦系数
18 |
19 |
20 | public BounceBackViewPager(Context context) {
21 | super(context);
22 | }
23 |
24 | public BounceBackViewPager(Context context, AttributeSet attrs) {
25 | super(context, attrs);
26 | }
27 |
28 | @Override
29 | public boolean onInterceptTouchEvent(MotionEvent ev) {
30 | switch (ev.getAction()) {
31 | case MotionEvent.ACTION_DOWN:
32 | preX = ev.getX();//记录起点
33 | break;
34 | }
35 | return super.onInterceptTouchEvent(ev);
36 | }
37 |
38 | @Override
39 | public boolean onTouchEvent(MotionEvent ev) {
40 | switch (ev.getAction()) {
41 | case MotionEvent.ACTION_MOVE:
42 | if (actionMove(ev)) return true;
43 | break;
44 | case MotionEvent.ACTION_UP:
45 | onTouchActionUp();
46 | break;
47 | }
48 | return super.onTouchEvent(ev);
49 | }
50 |
51 | private boolean actionMove(MotionEvent ev) {
52 | final float nowX = ev.getX();
53 | //偏移量
54 | final float offset = preX - nowX;
55 | preX = nowX;
56 | if (getAdapter().getCount() > 0) {
57 | if (handleDefault) {//手指滑动的距离大于设定值
58 | whetherIsCollided(offset);
59 | } else {//这种情况是已经出现缓冲区域了,手指慢慢恢复的情况
60 | scrollBy((int) (offset * RATIO), 0);
61 | }
62 | } else {
63 | handleDefault = true;
64 | }
65 | return !handleDefault;
66 | }
67 |
68 | private void whetherIsCollided(float offset) {
69 | if (mRect.isEmpty()) {
70 | mRect.set(getLeft(), getTop(), getRight(), getBottom());
71 | }
72 | handleDefault = false;
73 | scrollBy((int) (offset * RATIO), 0);
74 | }
75 |
76 | private void onTouchActionUp() {
77 | if (!mRect.isEmpty()) {
78 | recoveryPosition();
79 | }
80 | }
81 |
82 | private void recoveryPosition() {
83 | TranslateAnimation ta = new TranslateAnimation(getLeft(), mRect.left, 0, 0);
84 | ta.setDuration(150);
85 | ta.setInterpolator(new DecelerateInterpolator());
86 | startAnimation(ta);
87 | layout(mRect.left, mRect.top, mRect.right, mRect.bottom);
88 | mRect.setEmpty();
89 | handleDefault = true;
90 | }
91 |
92 | }
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/gestures/EclairGestureDetector.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview.gestures;
17 |
18 | import uk.co.senab.photoview.Compat;
19 | import android.annotation.TargetApi;
20 | import android.content.Context;
21 | import android.view.MotionEvent;
22 |
23 | @TargetApi(5)
24 | public class EclairGestureDetector extends CupcakeGestureDetector {
25 |
26 | private static final int INVALID_POINTER_ID = -1;
27 | private int mActivePointerId = INVALID_POINTER_ID;
28 | private int mActivePointerIndex = 0;
29 |
30 | public EclairGestureDetector(Context context) {
31 | super(context);
32 | }
33 |
34 | @Override
35 | float getActiveX(MotionEvent ev) {
36 | try {
37 | return ev.getX(mActivePointerIndex);
38 | } catch (Exception e) {
39 | return ev.getX();
40 | }
41 | }
42 |
43 | @Override
44 | float getActiveY(MotionEvent ev) {
45 | try {
46 | return ev.getY(mActivePointerIndex);
47 | } catch (Exception e) {
48 | return ev.getY();
49 | }
50 | }
51 |
52 | @Override
53 | public boolean onTouchEvent(MotionEvent ev) {
54 | final int action = ev.getAction();
55 | switch (action & MotionEvent.ACTION_MASK) {
56 | case MotionEvent.ACTION_DOWN:
57 | mActivePointerId = ev.getPointerId(0);
58 | break;
59 | case MotionEvent.ACTION_CANCEL:
60 | case MotionEvent.ACTION_UP:
61 | mActivePointerId = INVALID_POINTER_ID;
62 | break;
63 | case MotionEvent.ACTION_POINTER_UP:
64 | // Ignore deprecation, ACTION_POINTER_ID_MASK and
65 | // ACTION_POINTER_ID_SHIFT has same value and are deprecated
66 | // You can have either deprecation or lint target api warning
67 | final int pointerIndex = Compat.getPointerIndex(ev.getAction());
68 | final int pointerId = ev.getPointerId(pointerIndex);
69 | if (pointerId == mActivePointerId) {
70 | // This was our active pointer going up. Choose a new
71 | // active pointer and adjust accordingly.
72 | final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
73 | mActivePointerId = ev.getPointerId(newPointerIndex);
74 | mLastTouchX = ev.getX(newPointerIndex);
75 | mLastTouchY = ev.getY(newPointerIndex);
76 | }
77 | break;
78 | }
79 |
80 | mActivePointerIndex = ev
81 | .findPointerIndex(mActivePointerId != INVALID_POINTER_ID ? mActivePointerId
82 | : 0);
83 | return super.onTouchEvent(ev);
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/DefaultOnDoubleTapListener.java:
--------------------------------------------------------------------------------
1 | package uk.co.senab.photoview;
2 |
3 | import android.graphics.RectF;
4 | import android.view.GestureDetector;
5 | import android.view.MotionEvent;
6 | import android.widget.ImageView;
7 |
8 | /**
9 | * Provided default implementation of GestureDetector.OnDoubleTapListener, to be overriden with custom behavior, if needed
10 | *
11 | * To be used via {@link PhotoViewAttacher#setOnDoubleTapListener(GestureDetector.OnDoubleTapListener)}
12 | */
13 | public class DefaultOnDoubleTapListener implements GestureDetector.OnDoubleTapListener {
14 |
15 | private PhotoViewAttacher photoViewAttacher;
16 |
17 | /**
18 | * Default constructor
19 | *
20 | * @param photoViewAttacher PhotoViewAttacher to bind to
21 | */
22 | public DefaultOnDoubleTapListener(PhotoViewAttacher photoViewAttacher) {
23 | setPhotoViewAttacher(photoViewAttacher);
24 | }
25 |
26 | /**
27 | * Allows to change PhotoViewAttacher within range of single instance
28 | *
29 | * @param newPhotoViewAttacher PhotoViewAttacher to bind to
30 | */
31 | public void setPhotoViewAttacher(PhotoViewAttacher newPhotoViewAttacher) {
32 | this.photoViewAttacher = newPhotoViewAttacher;
33 | }
34 |
35 | @Override
36 | public boolean onSingleTapConfirmed(MotionEvent e) {
37 | if (this.photoViewAttacher == null)
38 | return false;
39 |
40 | ImageView imageView = photoViewAttacher.getImageView();
41 |
42 | if (null != photoViewAttacher.getOnPhotoTapListener()) {
43 | final RectF displayRect = photoViewAttacher.getDisplayRect();
44 |
45 | if (null != displayRect) {
46 | final float x = e.getX(), y = e.getY();
47 |
48 | // Check to see if the user tapped on the photo
49 | if (displayRect.contains(x, y)) {
50 |
51 | float xResult = (x - displayRect.left)
52 | / displayRect.width();
53 | float yResult = (y - displayRect.top)
54 | / displayRect.height();
55 |
56 | photoViewAttacher.getOnPhotoTapListener().onPhotoTap(imageView, xResult, yResult);
57 | return true;
58 | }
59 | }
60 | }
61 | if (null != photoViewAttacher.getOnViewTapListener()) {
62 | photoViewAttacher.getOnViewTapListener().onViewTap(imageView, e.getX(), e.getY());
63 | }
64 |
65 | return false;
66 | }
67 |
68 | @Override
69 | public boolean onDoubleTap(MotionEvent ev) {
70 | if (photoViewAttacher == null)
71 | return false;
72 |
73 | try {
74 | float scale = photoViewAttacher.getScale();
75 | float x = ev.getX();
76 | float y = ev.getY();
77 |
78 | if (scale < photoViewAttacher.getMediumScale()) {
79 | photoViewAttacher.setScale(photoViewAttacher.getMediumScale(), x, y, true);
80 | } else if (scale >= photoViewAttacher.getMediumScale() && scale < photoViewAttacher.getMaximumScale()) {
81 | photoViewAttacher.setScale(photoViewAttacher.getMaximumScale(), x, y, true);
82 | } else {
83 | photoViewAttacher.setScale(photoViewAttacher.getMinimumScale(), x, y, true);
84 | }
85 | } catch (ArrayIndexOutOfBoundsException e) {
86 | // Can sometimes happen when getX() and getY() is called
87 | }
88 |
89 | return true;
90 | }
91 |
92 | @Override
93 | public boolean onDoubleTapEvent(MotionEvent e) {
94 | // Wait for the confirmed onDoubleTap() instead
95 | return false;
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/activity/LisSimpleListImgsActivity.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.activity;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.MotionEvent;
6 | import android.view.View;
7 | import android.widget.Button;
8 | import android.widget.ImageView;
9 |
10 | import com.cocolover2.lis.LISConstant;
11 | import com.cocolover2.lis.interf.OnSelectResultListener;
12 | import com.cocolover2.lis.R;
13 |
14 |
15 | public abstract class LisSimpleListImgsActivity extends LisBaseListImgsActivity
16 | implements OnSelectResultListener, View.OnClickListener {
17 | private Button chooseBucketBtn;
18 | private ImageView bottomIcon;
19 | private Button preBtn;
20 |
21 |
22 | @Override
23 | public int getBottomLayoutId() {
24 | return R.layout.lis_imglist_bottom_layout;
25 | }
26 |
27 | @Override
28 | public void onMyCreate(Bundle savedInstanceState) {
29 | chooseBucketBtn = (Button) findViewById(R.id.lis_imglist_bottom_bucket_btn);
30 | bottomIcon = (ImageView) findViewById(R.id.lis_imglist_bottom_bucket_icon);
31 | preBtn = (Button) findViewById(R.id.lis_imglist_bottom_pre_btn);
32 | chooseBucketBtn.setText("所有图片");
33 | chooseBucketBtn.setOnTouchListener(bucketTouchListener);
34 | chooseBucketBtn.setOnClickListener(this);
35 | setOnSelectResultListener(this);
36 | }
37 |
38 | @Override
39 | protected void onStart() {
40 | super.onStart();
41 | if (getMaxSize() > 1) {
42 | preBtn.setOnClickListener(this);
43 | preBtn.setEnabled(false);
44 | preBtn.setTextColor(getResources().getColor(R.color.dark_gray));
45 | initPreBtn(getSelectImgCount());
46 | } else {
47 | preBtn.setVisibility(View.INVISIBLE);
48 | }
49 | }
50 |
51 | @Override
52 | public void onBucketSelect(String bucketName) {
53 | chooseBucketBtn.setText(bucketName);
54 | }
55 |
56 | private View.OnTouchListener bucketTouchListener = new View.OnTouchListener() {
57 | @Override
58 | public boolean onTouch(View v, MotionEvent event) {
59 | final int id = v.getId();
60 | if (event.getAction() == MotionEvent.ACTION_DOWN) {
61 | if (id == R.id.lis_imglist_bottom_bucket_btn) {
62 | chooseBucketBtn.setTextColor(getResources().getColor(com.cocolover2.lis.R.color.dark_gray));
63 | bottomIcon.setImageResource(com.cocolover2.lis.R.drawable.ic_bottom_mark_press);
64 | }
65 | } else if (event.getAction() == MotionEvent.ACTION_UP) {
66 | if (id == R.id.lis_imglist_bottom_bucket_btn) {
67 | bottomIcon.setImageResource(com.cocolover2.lis.R.drawable.ic_bottom_mark_normal);
68 | chooseBucketBtn.setTextColor(getResources().getColor(com.cocolover2.lis.R.color.gray));
69 | }
70 | }
71 | return false;
72 | }
73 | };
74 |
75 |
76 | @Override
77 | public void onSelectImgs(int selectedCount) {
78 | initPreBtn(selectedCount);
79 | }
80 |
81 | private void initPreBtn(int selectedCount) {
82 | if (selectedCount > 0) {
83 | preBtn.setText("预览(" + selectedCount + ")");
84 | preBtn.setEnabled(true);
85 | preBtn.setTextColor(getResources().getColor(android.R.color.white));
86 | } else {
87 | preBtn.setText("预览");
88 | preBtn.setEnabled(false);
89 | preBtn.setTextColor(getResources().getColor(R.color.dark_gray));
90 | }
91 | }
92 |
93 | @Override
94 | public void onBackPressed() {
95 | clearSelectedImgs();
96 | super.onBackPressed();
97 | }
98 |
99 | @Override
100 | public void onClick(View v) {
101 | final int id = v.getId();
102 | if (id == R.id.lis_imglist_bottom_bucket_btn) {
103 | if (isPopShow())
104 | hidePop();
105 | else
106 | showPop();
107 | } else if (id == R.id.lis_imglist_bottom_pre_btn) {
108 | Intent intent = new Intent(LISConstant.ACTION_PRE);
109 | intent.addCategory(getPackageName() + LISConstant.CATEGORY_SUFFIX);
110 | intent.putExtra(LISConstant.PRE_IMG_START_POSITION, 0);
111 | intent.putParcelableArrayListExtra(LISConstant.PRE_IMG_DATAS, getSelectImgs());
112 | startActivity(intent);
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/gestures/CupcakeGestureDetector.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview.gestures;
17 |
18 | import android.content.Context;
19 | import android.util.FloatMath;
20 | import android.util.Log;
21 | import android.view.MotionEvent;
22 | import android.view.VelocityTracker;
23 | import android.view.ViewConfiguration;
24 |
25 | public class CupcakeGestureDetector implements GestureDetector {
26 |
27 | protected OnGestureListener mListener;
28 | private static final String LOG_TAG = "CupcakeGestureDetector";
29 | float mLastTouchX;
30 | float mLastTouchY;
31 | final float mTouchSlop;
32 | final float mMinimumVelocity;
33 |
34 | @Override
35 | public void setOnGestureListener(OnGestureListener listener) {
36 | this.mListener = listener;
37 | }
38 |
39 | public CupcakeGestureDetector(Context context) {
40 | final ViewConfiguration configuration = ViewConfiguration
41 | .get(context);
42 | mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
43 | mTouchSlop = configuration.getScaledTouchSlop();
44 | }
45 |
46 | private VelocityTracker mVelocityTracker;
47 | private boolean mIsDragging;
48 |
49 | float getActiveX(MotionEvent ev) {
50 | return ev.getX();
51 | }
52 |
53 | float getActiveY(MotionEvent ev) {
54 | return ev.getY();
55 | }
56 |
57 | public boolean isScaling() {
58 | return false;
59 | }
60 |
61 | @Override
62 | public boolean onTouchEvent(MotionEvent ev) {
63 | switch (ev.getAction()) {
64 | case MotionEvent.ACTION_DOWN: {
65 | mVelocityTracker = VelocityTracker.obtain();
66 | if (null != mVelocityTracker) {
67 | mVelocityTracker.addMovement(ev);
68 | } else {
69 | Log.i(LOG_TAG, "Velocity tracker is null");
70 | }
71 |
72 | mLastTouchX = getActiveX(ev);
73 | mLastTouchY = getActiveY(ev);
74 | mIsDragging = false;
75 | break;
76 | }
77 |
78 | case MotionEvent.ACTION_MOVE: {
79 | final float x = getActiveX(ev);
80 | final float y = getActiveY(ev);
81 | final float dx = x - mLastTouchX, dy = y - mLastTouchY;
82 |
83 | if (!mIsDragging) {
84 | // Use Pythagoras to see if drag length is larger than
85 | // touch slop
86 | mIsDragging = Math.sqrt((dx * dx) + (dy * dy)) >= mTouchSlop;
87 | }
88 |
89 | if (mIsDragging) {
90 | mListener.onDrag(dx, dy);
91 | mLastTouchX = x;
92 | mLastTouchY = y;
93 |
94 | if (null != mVelocityTracker) {
95 | mVelocityTracker.addMovement(ev);
96 | }
97 | }
98 | break;
99 | }
100 |
101 | case MotionEvent.ACTION_CANCEL: {
102 | // Recycle Velocity Tracker
103 | if (null != mVelocityTracker) {
104 | mVelocityTracker.recycle();
105 | mVelocityTracker = null;
106 | }
107 | break;
108 | }
109 |
110 | case MotionEvent.ACTION_UP: {
111 | if (mIsDragging) {
112 | if (null != mVelocityTracker) {
113 | mLastTouchX = getActiveX(ev);
114 | mLastTouchY = getActiveY(ev);
115 |
116 | // Compute velocity within the last 1000ms
117 | mVelocityTracker.addMovement(ev);
118 | mVelocityTracker.computeCurrentVelocity(1000);
119 |
120 | final float vX = mVelocityTracker.getXVelocity(), vY = mVelocityTracker
121 | .getYVelocity();
122 |
123 | // If the velocity is greater than minVelocity, call
124 | // listener
125 | if (Math.max(Math.abs(vX), Math.abs(vY)) >= mMinimumVelocity) {
126 | mListener.onFling(mLastTouchX, mLastTouchY, -vX,
127 | -vY);
128 | }
129 | }
130 | }
131 |
132 | // Recycle Velocity Tracker
133 | if (null != mVelocityTracker) {
134 | mVelocityTracker.recycle();
135 | mVelocityTracker = null;
136 | }
137 | break;
138 | }
139 | }
140 |
141 | return true;
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/AlbumHelper.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis;
2 |
3 | import android.content.Context;
4 | import android.database.Cursor;
5 | import android.provider.MediaStore.Images.Media;
6 |
7 | import com.cocolover2.lis.entity.ImageBucket;
8 | import com.cocolover2.lis.entity.ImageItem;
9 |
10 | import java.io.File;
11 | import java.util.ArrayList;
12 | import java.util.HashMap;
13 | import java.util.Map;
14 |
15 |
16 | public final class AlbumHelper {
17 | //存储文件夹名,和文件夹内容
18 | private HashMap bucketMap = new HashMap<>();
19 | //所有的图片集合
20 | private ArrayList imageList = new ArrayList<>();
21 | private static ArrayList hasSelectImgs = new ArrayList<>();
22 | private static int MAXSIZE;
23 |
24 |
25 | public static void setMaxSize(int size) {
26 | if (size <= 0) {
27 | MAXSIZE = 0;
28 | } else {
29 | MAXSIZE = size;
30 | }
31 | }
32 |
33 | public static int getMaxSize() {
34 | return MAXSIZE;
35 | }
36 |
37 | /**
38 | * 获取sd卡中的图片,并创建图片文件夹的列表
39 | */
40 | private void buildImagesBucketList(Context context) {
41 | File file;
42 | String[] columns = {Media._ID, Media.BUCKET_ID, Media.DATA, Media.BUCKET_DISPLAY_NAME};
43 | Cursor cur = context.getContentResolver().query(Media.EXTERNAL_CONTENT_URI, columns, null, null,
44 | "_id DESC");
45 | if (cur != null && cur.getCount() <= 0) {
46 | throw new NullPointerException("do not find any picture");
47 | }
48 | if (cur != null && cur.moveToFirst()) {
49 | final int photoIdIndex = cur.getColumnIndexOrThrow(Media._ID);
50 | final int photoPathIndex = cur.getColumnIndexOrThrow(Media.DATA);//图片路径字段
51 | final int bucketDisplayNameIndex = cur.getColumnIndexOrThrow(Media.BUCKET_DISPLAY_NAME);
52 | final int bucketIdIndex = cur.getColumnIndexOrThrow(Media.BUCKET_ID);
53 | do {
54 | int id = cur.getInt(photoIdIndex);
55 | String path = cur.getString(photoPathIndex);
56 | int bucketId = cur.getInt(bucketIdIndex);
57 | String bucketname = cur.getString(bucketDisplayNameIndex);
58 | file = new File(path);
59 | if (!file.exists() || file.length() == 0)
60 | continue;
61 | ImageItem i = new ImageItem();
62 | i.imageId = id;
63 | i.imagePath = path;
64 | i.imageSize = file.length();
65 | i.createTime = file.lastModified();
66 | imageList.add(i);
67 | ImageBucket bucket;
68 | if (this.bucketMap.containsKey(bucketId))
69 | bucket = this.bucketMap.get(bucketId);
70 | else {
71 | bucket = new ImageBucket();
72 | bucketMap.put(bucketId, bucket);
73 | bucket.bucketName = bucketname;
74 | bucket.imageList = new ArrayList<>();
75 | }
76 | bucket.count++;
77 | bucket.imageList.add(i);
78 | } while (cur.moveToNext());
79 | }
80 | if (cur != null)
81 | cur.close();
82 | }
83 |
84 | /**
85 | * 获取图片的文件夹列表
86 | *
87 | * @return
88 | */
89 | public ArrayList getImageBucketList(Context context) {
90 | if (bucketMap == null || bucketMap.size() == 0)
91 | buildImagesBucketList(context);
92 | ArrayList allBuckets = new ArrayList<>();
93 | ImageBucket allBucket = new ImageBucket();
94 | allBucket.bucketName = LISConstant.ALL_IMG_BUCKET;
95 | allBucket.imageList = imageList;
96 | allBucket.count = imageList.size();
97 | allBucket.isSelected = true;
98 | allBuckets.add(allBucket);
99 | for (Map.Entry entry : bucketMap.entrySet()) {
100 | allBuckets.add(entry.getValue());
101 | }
102 | return allBuckets;
103 | }
104 |
105 | public static void clearSelectedImgs() {
106 | hasSelectImgs.clear();
107 | }
108 |
109 | public static ArrayList getHasSelectImgs() {
110 | return hasSelectImgs;
111 | }
112 |
113 | public static boolean addtoSelectImgs(ImageItem imageItem) {
114 | return hasSelectImgs.add(imageItem);
115 | }
116 |
117 | public static boolean addtoSelectImgs(ArrayList list) {
118 | return hasSelectImgs.addAll(list);
119 | }
120 |
121 | public static void removeItem(ImageItem item) {
122 | final int _size = hasSelectImgs.size();
123 | for (int j = 0; j < _size; j++) {
124 | if (item.imageId == hasSelectImgs.get(j).imageId) {
125 | hasSelectImgs.remove(j);
126 | break;
127 | }
128 | }
129 | }
130 |
131 | public static int getHasSelectCount() {
132 | return hasSelectImgs.size();
133 | }
134 |
135 | public static void initDataList(ArrayList dataRes) {
136 | final int size = hasSelectImgs.size();
137 | for (ImageItem img : dataRes) {
138 | img.isSelected = false;
139 | }
140 | for (int i = 0; i < size; i++) {
141 | for (ImageItem img : dataRes) {
142 | if (img.imageId == hasSelectImgs.get(i).imageId) {
143 | img.isSelected = true;
144 | break;
145 | }
146 | }
147 | }
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/adapter/ImageGridAdapter.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.adapter;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.graphics.Color;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.View.OnClickListener;
10 | import android.view.ViewGroup;
11 | import android.widget.BaseAdapter;
12 | import android.widget.ImageView;
13 | import android.widget.RelativeLayout;
14 | import android.widget.Toast;
15 |
16 | import com.cocolover2.lis.AlbumHelper;
17 | import com.cocolover2.lis.LISConstant;
18 | import com.cocolover2.lis.LocalImageLoader;
19 | import com.cocolover2.lis.interf.OnSelectResultListener;
20 | import com.cocolover2.lis.R;
21 | import com.cocolover2.lis.entity.ImageItem;
22 |
23 | import java.util.ArrayList;
24 |
25 |
26 | public class ImageGridAdapter extends BaseAdapter {
27 | final String FILTER_COLOR = "#88000000";
28 | // private int maxSize = 9;
29 | private OnSelectResultListener resultCallBack = null;
30 | private ArrayList dataList;// 数据源
31 | private Context context;
32 | private RelativeLayout.LayoutParams lp = null;
33 | private static boolean isPreView;//是否支持预览
34 |
35 | // public void setMaxSelect(int maxSize) {
36 | // this.maxSize = maxSize;
37 | // }
38 |
39 | public static void setIsPreView(boolean flag) {
40 | isPreView = flag;
41 | }
42 |
43 | public void setResultCallBack(OnSelectResultListener resultCallBack) {
44 | this.resultCallBack = resultCallBack;
45 | }
46 |
47 |
48 | public ImageGridAdapter(Context context, ArrayList dataList, int imgSize) {
49 | this.dataList = dataList;
50 | this.context = context;
51 | lp = new RelativeLayout.LayoutParams(imgSize, imgSize);
52 | }
53 |
54 | @Override
55 | public int getCount() {
56 | return dataList == null ? 0 : dataList.size();
57 | }
58 |
59 | public void refresh() {
60 | AlbumHelper.initDataList(dataList);
61 | notifyDataSetChanged();
62 | }
63 |
64 | @Override
65 | public ImageItem getItem(int position) {
66 | return dataList.get(position);
67 | }
68 |
69 | @Override
70 | public long getItemId(int position) {
71 | return position;
72 | }
73 |
74 | @SuppressLint("InflateParams")
75 | @Override
76 | public View getView(final int position, View convertView, ViewGroup parent) {
77 | final Holder holder;
78 | final ImageItem item = dataList.get(position);
79 | if (convertView == null) {
80 | holder = new Holder();
81 | convertView = LayoutInflater.from(context).inflate(
82 | R.layout.gridview_select_pic_item, parent, false);
83 | holder.iv = (ImageView) convertView
84 | .findViewById(R.id.select_pic_item_iv_img);
85 | holder.selected = (ImageView) convertView
86 | .findViewById(R.id.select_pic_item_iv_check);
87 | convertView.setTag(holder);
88 | } else {
89 | holder = (Holder) convertView.getTag();
90 | }
91 | holder.iv.setLayoutParams(lp);
92 |
93 | if (AlbumHelper.getMaxSize() <= 1) {
94 | holder.selected.setVisibility(View.INVISIBLE);
95 | } else {
96 | holder.selected.setVisibility(View.VISIBLE);
97 | if (item.isSelected) {
98 | holder.selected.setImageResource(R.drawable.ic_select_yes);
99 | //设置选中变暗
100 | holder.iv.setColorFilter(Color.parseColor(FILTER_COLOR));
101 | } else {
102 | holder.selected.setImageResource(R.drawable.ic_select_no);
103 | holder.iv.setColorFilter(null);
104 | }
105 | }
106 | LocalImageLoader.getInstance().loadImage(item.imagePath, holder.iv, R.drawable.default_img);
107 | setClickListener(holder, item, position);
108 | return convertView;
109 | }
110 |
111 | private void setClickListener(final Holder holder, final ImageItem item, final int position) {
112 | holder.selected.setOnClickListener(new OnClickListener() {
113 | @Override
114 | public void onClick(View v) {
115 | doSelectClicked(item, holder);
116 | }
117 | });
118 | holder.iv.setOnClickListener(new OnClickListener() {
119 | @Override
120 | public void onClick(View v) {
121 | if (isPreView && AlbumHelper.getMaxSize() > 1) {
122 | doPreViewImgClicked(position);
123 | } else {
124 | doSelectClicked(item, holder);
125 | }
126 | }
127 | });
128 |
129 | }
130 |
131 | private void doPreViewImgClicked(int position) {
132 | Intent intent = new Intent(LISConstant.ACTION_PRE);
133 | intent.addCategory(context.getPackageName() + LISConstant.CATEGORY_SUFFIX);
134 | intent.putExtra(LISConstant.PRE_IMG_START_POSITION, position);
135 | intent.putParcelableArrayListExtra(LISConstant.PRE_IMG_DATAS, dataList);
136 | context.startActivity(intent);
137 | }
138 |
139 | private void doSelectClicked(ImageItem item, Holder holder) {
140 | if (item.isSelected) {
141 | holder.selected.setImageResource(R.drawable.ic_select_no);
142 | AlbumHelper.removeItem(item);
143 | holder.iv.setColorFilter(null);
144 | item.isSelected = false;
145 | } else {
146 | if (AlbumHelper.getHasSelectCount() >= AlbumHelper.getMaxSize()) {
147 | if (AlbumHelper.getMaxSize() > 0)
148 | Toast.makeText(context, "最多选择" + AlbumHelper.getMaxSize() + "张图片", Toast.LENGTH_SHORT).show();
149 | else
150 | Toast.makeText(context, "当前你不能选择图片", Toast.LENGTH_SHORT).show();
151 | } else {
152 | holder.selected.setImageResource(R.drawable.ic_select_yes);
153 | holder.iv.setColorFilter(Color.parseColor(FILTER_COLOR));
154 | AlbumHelper.addtoSelectImgs(item);
155 | item.isSelected = true;
156 | }
157 | }
158 | if (resultCallBack != null)
159 | resultCallBack.onSelectImgs(AlbumHelper.getHasSelectCount());
160 | }
161 |
162 |
163 | final static class Holder {
164 | private ImageView iv;
165 | private ImageView selected;
166 | }
167 |
168 | }
169 |
--------------------------------------------------------------------------------
/library-lis/library-lis.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | generateDebugAndroidTestSources
19 | generateDebugSources
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/activity/LisBasePreviewPagerActivity.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.activity;
2 |
3 | import android.os.Bundle;
4 | import android.os.Parcelable;
5 | import android.support.v4.app.Fragment;
6 | import android.support.v4.app.FragmentManager;
7 | import android.support.v4.app.FragmentStatePagerAdapter;
8 | import android.support.v4.view.ViewPager;
9 | import android.support.v7.app.AppCompatActivity;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.animation.Animation;
13 | import android.view.animation.AnimationUtils;
14 | import android.widget.FrameLayout;
15 |
16 | import com.cocolover2.lis.LISConstant;
17 | import com.cocolover2.lis.interf.OnPagerUpdateListener;
18 | import com.cocolover2.lis.R;
19 | import com.cocolover2.lis.view.HackyViewPager;
20 |
21 | import java.util.ArrayList;
22 |
23 |
24 | public abstract class LisBasePreviewPagerActivity extends AppCompatActivity {
25 |
26 | private FrameLayout topLayout, bottomLayout;
27 | private ImagePagerAdapter mAdapter;
28 |
29 | private int startPos;
30 | private ArrayList mImgDatas;
31 | private OnPagerUpdateListener pagerUpdateListener;
32 |
33 |
34 | @Override
35 | protected void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | setContentView(R.layout.activity_previewpager);
38 | mImgDatas = (ArrayList) getIntent().getParcelableArrayListExtra(LISConstant.PRE_IMG_DATAS);
39 | startPos = getIntent().getIntExtra(LISConstant.PRE_IMG_START_POSITION, 0);
40 | if (getSupportActionBar() != null && getSupportActionBar().isShowing()) {
41 | getSupportActionBar().hide();
42 | }
43 | initView();
44 | onMyCreate(savedInstanceState);
45 | }
46 |
47 | public T getItem(int position) {
48 | return mImgDatas.get(position);
49 | }
50 |
51 | protected void setOnPagerUpdateListener(OnPagerUpdateListener listener) {
52 | pagerUpdateListener = listener;
53 | }
54 |
55 |
56 | private void initView() {
57 | topLayout = (FrameLayout) findViewById(R.id.previewpager_topbar);
58 | if (getTopBarLayoutId() > 0) {
59 | final View topBar = LayoutInflater.from(this).inflate(getTopBarLayoutId(), topLayout, false);
60 | topLayout.addView(topBar, topBar.getLayoutParams());
61 | }
62 | bottomLayout = (FrameLayout) findViewById(R.id.previewpager_bottom_layout);
63 | if (getBottomLayoutId() > 0) {
64 | final View bottomBar = LayoutInflater.from(this).inflate(getBottomLayoutId(), bottomLayout, false);
65 | bottomLayout.addView(bottomBar, bottomBar.getLayoutParams());
66 | }
67 | initViewPager();
68 | }
69 |
70 | private void initViewPager() {
71 | final HackyViewPager mViewPager = (HackyViewPager) findViewById(R.id.previewpager_viewpager_pager);
72 | /*禁用ViewPager左右两侧拉到边界的渐变颜色*/
73 | mViewPager.setOverScrollMode(View.OVER_SCROLL_NEVER);
74 | mAdapter = new ImagePagerAdapter(getSupportFragmentManager());
75 | mViewPager.setAdapter(mAdapter);
76 | mViewPager.setCurrentItem(startPos);
77 | mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
78 | @Override
79 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
80 | }
81 |
82 | @Override
83 | public void onPageSelected(int position) {
84 | if (pagerUpdateListener != null)
85 | pagerUpdateListener.onSelect(position);
86 | }
87 |
88 | @Override
89 | public void onPageScrollStateChanged(int state) {
90 | }
91 | });
92 | }
93 |
94 | protected int getStartPos() {
95 | return startPos;
96 | }
97 |
98 | protected int getAllDatasSize() {
99 | return mImgDatas.size();
100 | }
101 |
102 | protected void remove(int position) {
103 | if (position < 0 || position > mImgDatas.size()) {
104 | throw new IndexOutOfBoundsException("index is" + position + "and size is" + mImgDatas.size());
105 | }
106 | mImgDatas.remove(position);
107 | mAdapter.notifyDataSetChanged();
108 | if (pagerUpdateListener != null)
109 | pagerUpdateListener.onDeleted(position);
110 | }
111 |
112 | protected ArrayList getmImgDatas() {
113 | return mImgDatas;
114 | }
115 |
116 | public abstract int getTopBarLayoutId();
117 |
118 | public abstract int getBottomLayoutId();
119 |
120 | public abstract void onMyCreate(Bundle savedInstanceState);
121 |
122 | public abstract Fragment showContentFragment(T content);
123 |
124 |
125 | private Animation mAnimationTOP, mAnimationBottom;
126 | protected boolean isShowTopBottom = true;
127 |
128 | protected void showTopAndBottomLayout() {
129 | if (topLayout.getVisibility() != View.VISIBLE)
130 | topLayout.setVisibility(View.VISIBLE);
131 | if (bottomLayout.getVisibility() != View.VISIBLE)
132 | bottomLayout.setVisibility(View.VISIBLE);
133 | mAnimationTOP = AnimationUtils.loadAnimation(this, R.anim.slide_top_in);
134 | mAnimationBottom = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_in);
135 | topLayout.startAnimation(mAnimationTOP);
136 | bottomLayout.startAnimation(mAnimationBottom);
137 | isShowTopBottom = true;
138 | }
139 |
140 | protected void hideTopAndBottomLayout() {
141 | mAnimationTOP = AnimationUtils.loadAnimation(this, R.anim.slide_top_out);
142 | mAnimationTOP.setAnimationListener(new Animation.AnimationListener() {
143 | @Override
144 | public void onAnimationStart(Animation animation) {
145 | }
146 |
147 | @Override
148 | public void onAnimationEnd(Animation animation) {
149 | topLayout.setVisibility(View.GONE);
150 | }
151 |
152 | @Override
153 | public void onAnimationRepeat(Animation animation) {
154 | }
155 | });
156 | mAnimationBottom = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_out);
157 | mAnimationBottom.setAnimationListener(new Animation.AnimationListener() {
158 | @Override
159 | public void onAnimationStart(Animation animation) {
160 | }
161 |
162 | @Override
163 | public void onAnimationEnd(Animation animation) {
164 | bottomLayout.setVisibility(View.GONE);
165 | }
166 |
167 | @Override
168 | public void onAnimationRepeat(Animation animation) {
169 | }
170 | });
171 | topLayout.startAnimation(mAnimationTOP);
172 | bottomLayout.startAnimation(mAnimationBottom);
173 | isShowTopBottom = false;
174 | }
175 |
176 | /*这里建议使用FragmentStatePagerAdapter,不建议使用FragmentPagerAdapter,因为FragmentPagerAdapter,会缓存页面,容易造成OOM*/
177 | private class ImagePagerAdapter extends FragmentStatePagerAdapter {
178 | public ImagePagerAdapter(FragmentManager fm) {
179 | super(fm);
180 | }
181 |
182 | @Override
183 | public Fragment getItem(int position) {
184 | return showContentFragment(mImgDatas.get(position));
185 | }
186 |
187 | @Override
188 | public int getCount() {
189 | return mImgDatas == null ? 0 : mImgDatas.size();
190 | }
191 | }
192 | }
193 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/PhotoView.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview;
17 |
18 | import uk.co.senab.photoview.PhotoViewAttacher.OnMatrixChangedListener;
19 | import uk.co.senab.photoview.PhotoViewAttacher.OnPhotoTapListener;
20 | import uk.co.senab.photoview.PhotoViewAttacher.OnViewTapListener;
21 | import android.content.Context;
22 | import android.graphics.Bitmap;
23 | import android.graphics.Matrix;
24 | import android.graphics.RectF;
25 | import android.graphics.drawable.Drawable;
26 | import android.net.Uri;
27 | import android.util.AttributeSet;
28 | import android.widget.ImageView;
29 |
30 | public class PhotoView extends ImageView implements IPhotoView {
31 |
32 | private final PhotoViewAttacher mAttacher;
33 |
34 | private ScaleType mPendingScaleType;
35 |
36 | public PhotoView(Context context) {
37 | this(context, null);
38 | }
39 |
40 | public PhotoView(Context context, AttributeSet attr) {
41 | this(context, attr, 0);
42 | }
43 |
44 | public PhotoView(Context context, AttributeSet attr, int defStyle) {
45 | super(context, attr, defStyle);
46 | super.setScaleType(ScaleType.MATRIX);
47 | mAttacher = new PhotoViewAttacher(this);
48 |
49 | if (null != mPendingScaleType) {
50 | setScaleType(mPendingScaleType);
51 | mPendingScaleType = null;
52 | }
53 | }
54 |
55 | @Override
56 | public void setPhotoViewRotation(float rotationDegree) {
57 | mAttacher.setPhotoViewRotation(rotationDegree);
58 | }
59 |
60 | @Override
61 | public boolean canZoom() {
62 | return mAttacher.canZoom();
63 | }
64 |
65 | @Override
66 | public RectF getDisplayRect() {
67 | return mAttacher.getDisplayRect();
68 | }
69 |
70 | @Override
71 | public Matrix getDisplayMatrix() {
72 | return mAttacher.getDrawMatrix();
73 | }
74 |
75 | @Override
76 | public boolean setDisplayMatrix(Matrix finalRectangle) {
77 | return mAttacher.setDisplayMatrix(finalRectangle);
78 | }
79 |
80 | @Override
81 | @Deprecated
82 | public float getMinScale() {
83 | return getMinimumScale();
84 | }
85 |
86 | @Override
87 | public float getMinimumScale() {
88 | return mAttacher.getMinimumScale();
89 | }
90 |
91 | @Override
92 | @Deprecated
93 | public float getMidScale() {
94 | return getMediumScale();
95 | }
96 |
97 | @Override
98 | public float getMediumScale() {
99 | return mAttacher.getMediumScale();
100 | }
101 |
102 | @Override
103 | @Deprecated
104 | public float getMaxScale() {
105 | return getMaximumScale();
106 | }
107 |
108 | @Override
109 | public float getMaximumScale() {
110 | return mAttacher.getMaximumScale();
111 | }
112 |
113 | @Override
114 | public float getScale() {
115 | return mAttacher.getScale();
116 | }
117 |
118 | @Override
119 | public ScaleType getScaleType() {
120 | return mAttacher.getScaleType();
121 | }
122 |
123 | @Override
124 | public void setAllowParentInterceptOnEdge(boolean allow) {
125 | mAttacher.setAllowParentInterceptOnEdge(allow);
126 | }
127 |
128 | @Override
129 | @Deprecated
130 | public void setMinScale(float minScale) {
131 | setMinimumScale(minScale);
132 | }
133 |
134 | @Override
135 | public void setMinimumScale(float minimumScale) {
136 | mAttacher.setMinimumScale(minimumScale);
137 | }
138 |
139 | @Override
140 | @Deprecated
141 | public void setMidScale(float midScale) {
142 | setMediumScale(midScale);
143 | }
144 |
145 | @Override
146 | public void setMediumScale(float mediumScale) {
147 | mAttacher.setMediumScale(mediumScale);
148 | }
149 |
150 | @Override
151 | @Deprecated
152 | public void setMaxScale(float maxScale) {
153 | setMaximumScale(maxScale);
154 | }
155 |
156 | @Override
157 | public void setMaximumScale(float maximumScale) {
158 | mAttacher.setMaximumScale(maximumScale);
159 | }
160 |
161 | @Override
162 | // setImageBitmap calls through to this method
163 | public void setImageDrawable(Drawable drawable) {
164 | super.setImageDrawable(drawable);
165 | if (null != mAttacher) {
166 | mAttacher.update();
167 | }
168 | }
169 |
170 | @Override
171 | public void setImageResource(int resId) {
172 | super.setImageResource(resId);
173 | if (null != mAttacher) {
174 | mAttacher.update();
175 | }
176 | }
177 |
178 | @Override
179 | public void setImageURI(Uri uri) {
180 | super.setImageURI(uri);
181 | if (null != mAttacher) {
182 | mAttacher.update();
183 | }
184 | }
185 |
186 | @Override
187 | public void setOnMatrixChangeListener(OnMatrixChangedListener listener) {
188 | mAttacher.setOnMatrixChangeListener(listener);
189 | }
190 |
191 | @Override
192 | public void setOnLongClickListener(OnLongClickListener l) {
193 | mAttacher.setOnLongClickListener(l);
194 | }
195 |
196 | @Override
197 | public void setOnPhotoTapListener(OnPhotoTapListener listener) {
198 | mAttacher.setOnPhotoTapListener(listener);
199 | }
200 |
201 | @Override
202 | public OnPhotoTapListener getOnPhotoTapListener() {
203 | return mAttacher.getOnPhotoTapListener();
204 | }
205 |
206 | @Override
207 | public void setOnViewTapListener(OnViewTapListener listener) {
208 | mAttacher.setOnViewTapListener(listener);
209 | }
210 |
211 | @Override
212 | public OnViewTapListener getOnViewTapListener() {
213 | return mAttacher.getOnViewTapListener();
214 | }
215 |
216 | @Override
217 | public void setScale(float scale) {
218 | mAttacher.setScale(scale);
219 | }
220 |
221 | @Override
222 | public void setScale(float scale, boolean animate) {
223 | mAttacher.setScale(scale, animate);
224 | }
225 |
226 | @Override
227 | public void setScale(float scale, float focalX, float focalY, boolean animate) {
228 | mAttacher.setScale(scale, focalX, focalY, animate);
229 | }
230 |
231 | @Override
232 | public void setScaleType(ScaleType scaleType) {
233 | if (null != mAttacher) {
234 | mAttacher.setScaleType(scaleType);
235 | } else {
236 | mPendingScaleType = scaleType;
237 | }
238 | }
239 |
240 | @Override
241 | public void setZoomable(boolean zoomable) {
242 | mAttacher.setZoomable(zoomable);
243 | }
244 |
245 | @Override
246 | public Bitmap getVisibleRectangleBitmap() {
247 | return mAttacher.getVisibleRectangleBitmap();
248 | }
249 |
250 | @Override
251 | public void setZoomTransitionDuration(int milliseconds) {
252 | mAttacher.setZoomTransitionDuration(milliseconds);
253 | }
254 |
255 | @Override
256 | protected void onDetachedFromWindow() {
257 | mAttacher.cleanup();
258 | super.onDetachedFromWindow();
259 | }
260 |
261 | }
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/LocalImageLoader.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis;
2 |
3 | import android.graphics.Bitmap;
4 | import android.os.Handler;
5 | import android.os.HandlerThread;
6 | import android.os.Message;
7 | import android.widget.AbsListView;
8 | import android.widget.ImageView;
9 |
10 | import com.cocolover2.lis.utils.ImageCache;
11 | import com.cocolover2.lis.utils.ImageUtils;
12 |
13 | import java.util.LinkedList;
14 | import java.util.concurrent.ExecutorService;
15 | import java.util.concurrent.Executors;
16 | import java.util.concurrent.Semaphore;
17 |
18 | public class LocalImageLoader {
19 | private final String key_prefix = "loal_thumbnails_";
20 | private ExecutorService mThreadPool;
21 | private Type mType = Type.LIFO;
22 | private LinkedList mTasks;
23 | private HandlerThread mPoolThread;
24 | private Handler mPoolThreadHander;
25 | private WeakHandler mHandler;
26 | private volatile Semaphore mSemaphore = new Semaphore(0);
27 | private volatile Semaphore mPoolSemaphore;
28 |
29 | private static LocalImageLoader mInstance;
30 | private int imgWidth = 180, imgHeight = 180;
31 | private boolean isFling = false;
32 | private boolean isScrolling = false;
33 |
34 | public enum Type {
35 | FIFO, LIFO
36 | }
37 |
38 | public static LocalImageLoader getInstance() {
39 | if (mInstance == null) {
40 | synchronized (LocalImageLoader.class) {
41 | if (mInstance == null) {
42 | mInstance = new LocalImageLoader(3, Type.LIFO);
43 | }
44 | }
45 | }
46 | return mInstance;
47 | }
48 |
49 | private LocalImageLoader(int threadCount, Type type) {
50 | init(threadCount, type);
51 | }
52 |
53 | private void init(int threadCount, Type type) {
54 | mThreadPool = Executors.newFixedThreadPool(threadCount);
55 | mPoolSemaphore = new Semaphore(threadCount);
56 | mTasks = new LinkedList<>();
57 | mType = type == null ? Type.FIFO : type;
58 | mPoolThread = new HandlerThread("loop thread");
59 | mPoolThread.start();
60 | mPoolThreadHander = new Handler(mPoolThread.getLooper(), new Handler.Callback() {
61 | @Override
62 | public boolean handleMessage(Message msg) {
63 | Runnable r = getTask();
64 | if (r != null) {
65 | mThreadPool.execute(r);
66 | try {
67 | mPoolSemaphore.acquire();
68 | } catch (InterruptedException e) {
69 | }
70 | }
71 | return true;
72 | }
73 | });
74 | // 释放一个信号量
75 | mSemaphore.release();
76 | }
77 |
78 | /**
79 | * 加载图片
80 | *
81 | * @param path
82 | * @param imageView
83 | */
84 | public void loadImage(final String path, final ImageView imageView, int defaultImgId) {
85 | if (isScrolling) {
86 | if (defaultImgId != 0)
87 | imageView.setImageResource(defaultImgId);
88 | }
89 |
90 | if (isFling) {
91 | return;
92 | }
93 | // set tag
94 | imageView.setTag(path);
95 | // UI线程
96 | if (mHandler == null) {
97 | mHandler = new WeakHandler();
98 | }
99 | Bitmap bm = getBitmapFromLruCache(path);
100 | if (bm != null) {
101 | ImgBeanHolder holder = new ImgBeanHolder();
102 | holder.bitmap = bm;
103 | holder.imageView = imageView;
104 | holder.path = path;
105 | Message message = Message.obtain();
106 | message.obj = holder;
107 | mHandler.sendMessage(message);
108 | } else {
109 | addTask(new Runnable() {
110 | @Override
111 | public void run() {
112 | Bitmap bm = ImageUtils.compressImgBySize(path, imgWidth,
113 | imgHeight);
114 | addBitmapToLruCache(path, bm);
115 | ImgBeanHolder holder = new ImgBeanHolder();
116 | holder.bitmap = getBitmapFromLruCache(path);
117 | holder.imageView = imageView;
118 | holder.path = path;
119 | Message message = Message.obtain();
120 | message.obj = holder;
121 | mHandler.sendMessage(message);
122 | mPoolSemaphore.release();
123 | }
124 | });
125 | }
126 |
127 | }
128 |
129 | /**
130 | * 设置显示图片的大小
131 | *
132 | * @param width
133 | * @param height
134 | */
135 | public void setImgSize(int width, int height) {
136 | this.imgWidth = width;
137 | this.imgHeight = height;
138 | }
139 |
140 | static class WeakHandler extends Handler {
141 | @Override
142 | public void handleMessage(Message msg) {
143 | ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
144 | ImageView imageView = holder.imageView;
145 | Bitmap bm = holder.bitmap;
146 | String path = holder.path;
147 | if (imageView.getTag().toString().equals(path) && bm != null) {
148 | imageView.setImageBitmap(bm);
149 | }
150 | }
151 | }
152 |
153 | /**
154 | * 添加一个任务
155 | *
156 | * @param runnable
157 | */
158 | private synchronized void addTask(Runnable runnable) {
159 | try {
160 | // 请求信号量,防止mPoolThreadHander为null
161 | if (mPoolThreadHander == null)
162 | mSemaphore.acquire();
163 | } catch (InterruptedException e) {
164 | }
165 | mTasks.add(runnable);
166 | mPoolThreadHander.sendEmptyMessage(0x110);
167 | }
168 |
169 | /**
170 | * 取出一个任务
171 | *
172 | * @return
173 | */
174 | private synchronized Runnable getTask() {
175 | if (mTasks.size() == 0)
176 | return null;
177 | if (mType == Type.FIFO) {
178 | return mTasks.removeFirst();
179 | } else if (mType == Type.LIFO) {
180 | return mTasks.removeLast();
181 | }
182 | return null;
183 | }
184 |
185 | /**
186 | * 单例获得该实例对象
187 | *
188 | * @return
189 | */
190 | public static LocalImageLoader getInstance(int threadCount, Type type) {
191 |
192 | if (mInstance == null) {
193 | synchronized (LocalImageLoader.class) {
194 | if (mInstance == null) {
195 | mInstance = new LocalImageLoader(threadCount, type);
196 | }
197 | }
198 | }
199 | return mInstance;
200 | }
201 |
202 |
203 | /**
204 | * 从LruCache中获取一张图片,如果不存在就返回null。
205 | */
206 | private Bitmap getBitmapFromLruCache(String key) {
207 | return ImageCache.getInstance().get(key_prefix + key);
208 | }
209 |
210 | /**
211 | * 往LruCache中添加一张图片
212 | *
213 | * @param key
214 | * @param bitmap
215 | */
216 | private void addBitmapToLruCache(String key, Bitmap bitmap) {
217 | if (getBitmapFromLruCache(key) == null) {
218 | if (bitmap != null)
219 | ImageCache.getInstance().put(key_prefix + key, bitmap);
220 | }
221 | }
222 |
223 |
224 | public void clearChache() {
225 | if (mTasks != null)
226 | mTasks.clear();
227 | }
228 |
229 | private class ImgBeanHolder {
230 | Bitmap bitmap;
231 | ImageView imageView;
232 | String path;
233 | }
234 |
235 | int previousFirstVisibleItem = 0;
236 | long previousEventTime = 0;
237 | double speed = 0;
238 | int mScrollState = 0;
239 |
240 | public void setFlingStopLoading(final AbsListView listView) {
241 |
242 | listView.setOnScrollListener(new AbsListView.OnScrollListener() {
243 | @Override
244 | public void onScrollStateChanged(AbsListView view, int scrollState) {
245 | mScrollState = scrollState;
246 | if (scrollState == SCROLL_STATE_IDLE) {
247 | isScrolling = false;
248 | } else {
249 | isScrolling = true;
250 | }
251 | }
252 |
253 | @Override
254 | public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
255 | if (previousFirstVisibleItem != firstVisibleItem) {
256 | long currTime = System.currentTimeMillis();
257 | long timeToScrollOneElement = currTime - previousEventTime;
258 | speed = ((double) 1 / timeToScrollOneElement) * 1000;
259 | previousFirstVisibleItem = firstVisibleItem;
260 | previousEventTime = currTime;
261 | }
262 | if (speed > 25 && AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL == mScrollState) {
263 | isFling = true;
264 | } else
265 | isFling = false;
266 | }
267 | });
268 | }
269 | }
270 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The Artistic License 2.0
2 |
3 | Copyright (c) 2015 BOLIU
4 |
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | This license establishes the terms under which a given free software
11 | Package may be copied, modified, distributed, and/or redistributed.
12 | The intent is that the Copyright Holder maintains some artistic
13 | control over the development of that Package while still keeping the
14 | Package available as open source and free software.
15 |
16 | You are always permitted to make arrangements wholly outside of this
17 | license directly with the Copyright Holder of a given Package. If the
18 | terms of this license do not permit the full use that you propose to
19 | make of the Package, you should contact the Copyright Holder and seek
20 | a different licensing arrangement.
21 |
22 | Definitions
23 |
24 | "Copyright Holder" means the individual(s) or organization(s)
25 | named in the copyright notice for the entire Package.
26 |
27 | "Contributor" means any party that has contributed code or other
28 | material to the Package, in accordance with the Copyright Holder's
29 | procedures.
30 |
31 | "You" and "your" means any person who would like to copy,
32 | distribute, or modify the Package.
33 |
34 | "Package" means the collection of files distributed by the
35 | Copyright Holder, and derivatives of that collection and/or of
36 | those files. A given Package may consist of either the Standard
37 | Version, or a Modified Version.
38 |
39 | "Distribute" means providing a copy of the Package or making it
40 | accessible to anyone else, or in the case of a company or
41 | organization, to others outside of your company or organization.
42 |
43 | "Distributor Fee" means any fee that you charge for Distributing
44 | this Package or providing support for this Package to another
45 | party. It does not mean licensing fees.
46 |
47 | "Standard Version" refers to the Package if it has not been
48 | modified, or has been modified only in ways explicitly requested
49 | by the Copyright Holder.
50 |
51 | "Modified Version" means the Package, if it has been changed, and
52 | such changes were not explicitly requested by the Copyright
53 | Holder.
54 |
55 | "Original License" means this Artistic License as Distributed with
56 | the Standard Version of the Package, in its current version or as
57 | it may be modified by The Perl Foundation in the future.
58 |
59 | "Source" form means the source code, documentation source, and
60 | configuration files for the Package.
61 |
62 | "Compiled" form means the compiled bytecode, object code, binary,
63 | or any other form resulting from mechanical transformation or
64 | translation of the Source form.
65 |
66 |
67 | Permission for Use and Modification Without Distribution
68 |
69 | (1) You are permitted to use the Standard Version and create and use
70 | Modified Versions for any purpose without restriction, provided that
71 | you do not Distribute the Modified Version.
72 |
73 |
74 | Permissions for Redistribution of the Standard Version
75 |
76 | (2) You may Distribute verbatim copies of the Source form of the
77 | Standard Version of this Package in any medium without restriction,
78 | either gratis or for a Distributor Fee, provided that you duplicate
79 | all of the original copyright notices and associated disclaimers. At
80 | your discretion, such verbatim copies may or may not include a
81 | Compiled form of the Package.
82 |
83 | (3) You may apply any bug fixes, portability changes, and other
84 | modifications made available from the Copyright Holder. The resulting
85 | Package will still be considered the Standard Version, and as such
86 | will be subject to the Original License.
87 |
88 |
89 | Distribution of Modified Versions of the Package as Source
90 |
91 | (4) You may Distribute your Modified Version as Source (either gratis
92 | or for a Distributor Fee, and with or without a Compiled form of the
93 | Modified Version) provided that you clearly document how it differs
94 | from the Standard Version, including, but not limited to, documenting
95 | any non-standard features, executables, or modules, and provided that
96 | you do at least ONE of the following:
97 |
98 | (a) make the Modified Version available to the Copyright Holder
99 | of the Standard Version, under the Original License, so that the
100 | Copyright Holder may include your modifications in the Standard
101 | Version.
102 |
103 | (b) ensure that installation of your Modified Version does not
104 | prevent the user installing or running the Standard Version. In
105 | addition, the Modified Version must bear a name that is different
106 | from the name of the Standard Version.
107 |
108 | (c) allow anyone who receives a copy of the Modified Version to
109 | make the Source form of the Modified Version available to others
110 | under
111 |
112 | (i) the Original License or
113 |
114 | (ii) a license that permits the licensee to freely copy,
115 | modify and redistribute the Modified Version using the same
116 | licensing terms that apply to the copy that the licensee
117 | received, and requires that the Source form of the Modified
118 | Version, and of any works derived from it, be made freely
119 | available in that license fees are prohibited but Distributor
120 | Fees are allowed.
121 |
122 |
123 | Distribution of Compiled Forms of the Standard Version
124 | or Modified Versions without the Source
125 |
126 | (5) You may Distribute Compiled forms of the Standard Version without
127 | the Source, provided that you include complete instructions on how to
128 | get the Source of the Standard Version. Such instructions must be
129 | valid at the time of your distribution. If these instructions, at any
130 | time while you are carrying out such distribution, become invalid, you
131 | must provide new instructions on demand or cease further distribution.
132 | If you provide valid instructions or cease distribution within thirty
133 | days after you become aware that the instructions are invalid, then
134 | you do not forfeit any of your rights under this license.
135 |
136 | (6) You may Distribute a Modified Version in Compiled form without
137 | the Source, provided that you comply with Section 4 with respect to
138 | the Source of the Modified Version.
139 |
140 |
141 | Aggregating or Linking the Package
142 |
143 | (7) You may aggregate the Package (either the Standard Version or
144 | Modified Version) with other packages and Distribute the resulting
145 | aggregation provided that you do not charge a licensing fee for the
146 | Package. Distributor Fees are permitted, and licensing fees for other
147 | components in the aggregation are permitted. The terms of this license
148 | apply to the use and Distribution of the Standard or Modified Versions
149 | as included in the aggregation.
150 |
151 | (8) You are permitted to link Modified and Standard Versions with
152 | other works, to embed the Package in a larger work of your own, or to
153 | build stand-alone binary or bytecode versions of applications that
154 | include the Package, and Distribute the result without restriction,
155 | provided the result does not expose a direct interface to the Package.
156 |
157 |
158 | Items That are Not Considered Part of a Modified Version
159 |
160 | (9) Works (including, but not limited to, modules and scripts) that
161 | merely extend or make use of the Package, do not, by themselves, cause
162 | the Package to be a Modified Version. In addition, such works are not
163 | considered parts of the Package itself, and are not subject to the
164 | terms of this license.
165 |
166 |
167 | General Provisions
168 |
169 | (10) Any use, modification, and distribution of the Standard or
170 | Modified Versions is governed by this Artistic License. By using,
171 | modifying or distributing the Package, you accept this license. Do not
172 | use, modify, or distribute the Package, if you do not accept this
173 | license.
174 |
175 | (11) If your Modified Version has been derived from a Modified
176 | Version made by someone other than you, you are nevertheless required
177 | to ensure that your Modified Version complies with the requirements of
178 | this license.
179 |
180 | (12) This license does not grant you the right to use any trademark,
181 | service mark, tradename, or logo of the Copyright Holder.
182 |
183 | (13) This license includes the non-exclusive, worldwide,
184 | free-of-charge patent license to make, have made, use, offer to sell,
185 | sell, import and otherwise transfer the Package with respect to any
186 | patent claims licensable by the Copyright Holder that are necessarily
187 | infringed by the Package. If you institute patent litigation
188 | (including a cross-claim or counterclaim) against any party alleging
189 | that the Package constitutes direct or contributory patent
190 | infringement, then this Artistic License to you shall terminate on the
191 | date that such litigation is filed.
192 |
193 | (14) Disclaimer of Warranty:
194 | THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
195 | IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
196 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
197 | NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
198 | LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
199 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
200 | DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
201 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
202 |
203 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/uk/co/senab/photoview/IPhotoView.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2011, 2012 Chris Banes.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | *******************************************************************************/
16 | package uk.co.senab.photoview;
17 |
18 | import android.graphics.Bitmap;
19 | import android.graphics.Matrix;
20 | import android.graphics.RectF;
21 | import android.view.View;
22 | import android.widget.ImageView;
23 |
24 |
25 | public interface IPhotoView {
26 |
27 | public static final float DEFAULT_MAX_SCALE = 3.0f;
28 | public static final float DEFAULT_MID_SCALE = 1.75f;
29 | public static final float DEFAULT_MIN_SCALE = 1.0f;
30 | public static final int DEFAULT_ZOOM_DURATION = 200;
31 |
32 | /**
33 | * Returns true if the PhotoView is set to allow zooming of Photos.
34 | *
35 | * @return true if the PhotoView allows zooming.
36 | */
37 | boolean canZoom();
38 |
39 | /**
40 | * Gets the Display Rectangle of the currently displayed Drawable. The Rectangle is relative to
41 | * this View and includes all scaling and translations.
42 | *
43 | * @return - RectF of Displayed Drawable
44 | */
45 | RectF getDisplayRect();
46 |
47 | /**
48 | * Sets the Display Matrix of the currently displayed Drawable. The Rectangle is considered
49 | * relative to this View and includes all scaling and translations.
50 | *
51 | * @return - true if rectangle was applied successfully
52 | */
53 | boolean setDisplayMatrix(Matrix finalMatrix);
54 |
55 | /**
56 | * Gets the Display Matrix of the currently displayed Drawable. The Rectangle is considered
57 | * relative to this View and includes all scaling and translations.
58 | *
59 | * @return - true if rectangle was applied successfully
60 | */
61 | Matrix getDisplayMatrix();
62 |
63 | /**
64 | * Use {@link #getMinimumScale()} instead, this will be removed in future release
65 | *
66 | * @return The current minimum scale level. What this value represents depends on the current
67 | * {@link ImageView.ScaleType}.
68 | */
69 | @Deprecated
70 | float getMinScale();
71 |
72 | /**
73 | * @return The current minimum scale level. What this value represents depends on the current
74 | * {@link ImageView.ScaleType}.
75 | */
76 | float getMinimumScale();
77 |
78 | /**
79 | * Use {@link #getMediumScale()} instead, this will be removed in future release
80 | *
81 | * @return The current middle scale level. What this value represents depends on the current
82 | * {@link ImageView.ScaleType}.
83 | */
84 | @Deprecated
85 | float getMidScale();
86 |
87 | /**
88 | * @return The current medium scale level. What this value represents depends on the current
89 | * {@link ImageView.ScaleType}.
90 | */
91 | float getMediumScale();
92 |
93 | /**
94 | * Use {@link #getMaximumScale()} instead, this will be removed in future release
95 | *
96 | * @return The current maximum scale level. What this value represents depends on the current
97 | * {@link ImageView.ScaleType}.
98 | */
99 | @Deprecated
100 | float getMaxScale();
101 |
102 | /**
103 | * @return The current maximum scale level. What this value represents depends on the current
104 | * {@link ImageView.ScaleType}.
105 | */
106 | float getMaximumScale();
107 |
108 | /**
109 | * Returns the current scale value
110 | *
111 | * @return float - current scale value
112 | */
113 | float getScale();
114 |
115 | /**
116 | * Return the current scale type in use by the ImageView.
117 | */
118 | ImageView.ScaleType getScaleType();
119 |
120 | /**
121 | * Whether to allow the ImageView's parent to intercept the touch event when the photo is scroll
122 | * to it's horizontal edge.
123 | */
124 | void setAllowParentInterceptOnEdge(boolean allow);
125 |
126 | /**
127 | * Use {@link #setMinimumScale(float minimumScale)} instead, this will be removed in future
128 | * release
129 | *
130 | * Sets the minimum scale level. What this value represents depends on the current {@link
131 | * ImageView.ScaleType}.
132 | */
133 | @Deprecated
134 | void setMinScale(float minScale);
135 |
136 | /**
137 | * Sets the minimum scale level. What this value represents depends on the current {@link
138 | * ImageView.ScaleType}.
139 | */
140 | void setMinimumScale(float minimumScale);
141 |
142 | /**
143 | * Use {@link #setMediumScale(float mediumScale)} instead, this will be removed in future
144 | * release
145 | *
146 | * Sets the middle scale level. What this value represents depends on the current {@link
147 | * ImageView.ScaleType}.
148 | */
149 | @Deprecated
150 | void setMidScale(float midScale);
151 |
152 | /*
153 | * Sets the medium scale level. What this value represents depends on the current {@link android.widget.ImageView.ScaleType}.
154 | */
155 | void setMediumScale(float mediumScale);
156 |
157 | /**
158 | * Use {@link #setMaximumScale(float maximumScale)} instead, this will be removed in future
159 | * release
160 | *
161 | * Sets the maximum scale level. What this value represents depends on the current {@link
162 | * ImageView.ScaleType}.
163 | */
164 | @Deprecated
165 | void setMaxScale(float maxScale);
166 |
167 | /**
168 | * Sets the maximum scale level. What this value represents depends on the current {@link
169 | * ImageView.ScaleType}.
170 | */
171 | void setMaximumScale(float maximumScale);
172 |
173 | /**
174 | * Register a callback to be invoked when the Photo displayed by this view is long-pressed.
175 | *
176 | * @param listener - Listener to be registered.
177 | */
178 | void setOnLongClickListener(View.OnLongClickListener listener);
179 |
180 | /**
181 | * Register a callback to be invoked when the Matrix has changed for this View. An example would
182 | * be the user panning or scaling the Photo.
183 | *
184 | * @param listener - Listener to be registered.
185 | */
186 | void setOnMatrixChangeListener(PhotoViewAttacher.OnMatrixChangedListener listener);
187 |
188 | /**
189 | * Register a callback to be invoked when the Photo displayed by this View is tapped with a
190 | * single tap.
191 | *
192 | * @param listener - Listener to be registered.
193 | */
194 | void setOnPhotoTapListener(PhotoViewAttacher.OnPhotoTapListener listener);
195 |
196 | /**
197 | * Returns a listener to be invoked when the Photo displayed by this View is tapped with a
198 | * single tap.
199 | *
200 | * @return PhotoViewAttacher.OnPhotoTapListener currently set, may be null
201 | */
202 | PhotoViewAttacher.OnPhotoTapListener getOnPhotoTapListener();
203 |
204 | /**
205 | * Register a callback to be invoked when the View is tapped with a single tap.
206 | *
207 | * @param listener - Listener to be registered.
208 | */
209 | void setOnViewTapListener(PhotoViewAttacher.OnViewTapListener listener);
210 |
211 | /**
212 | * Returns a callback listener to be invoked when the View is tapped with a single tap.
213 | *
214 | * @return PhotoViewAttacher.OnViewTapListener currently set, may be null
215 | */
216 | PhotoViewAttacher.OnViewTapListener getOnViewTapListener();
217 |
218 | /**
219 | * Changes the current scale to the specified value.
220 | *
221 | * @param scale - Value to scale to
222 | */
223 | void setScale(float scale);
224 |
225 | /**
226 | * Changes the current scale to the specified value.
227 | *
228 | * @param scale - Value to scale to
229 | * @param animate - Whether to animate the scale
230 | */
231 | void setScale(float scale, boolean animate);
232 |
233 | /**
234 | * Changes the current scale to the specified value, around the given focal point.
235 | *
236 | * @param scale - Value to scale to
237 | * @param focalX - X Focus Point
238 | * @param focalY - Y Focus Point
239 | * @param animate - Whether to animate the scale
240 | */
241 | void setScale(float scale, float focalX, float focalY, boolean animate);
242 |
243 | /**
244 | * Controls how the image should be resized or moved to match the size of the ImageView. Any
245 | * scaling or panning will happen within the confines of this {@link
246 | * ImageView.ScaleType}.
247 | *
248 | * @param scaleType - The desired scaling mode.
249 | */
250 | void setScaleType(ImageView.ScaleType scaleType);
251 |
252 | /**
253 | * Allows you to enable/disable the zoom functionality on the ImageView. When disable the
254 | * ImageView reverts to using the FIT_CENTER matrix.
255 | *
256 | * @param zoomable - Whether the zoom functionality is enabled.
257 | */
258 | void setZoomable(boolean zoomable);
259 |
260 | /**
261 | * Enables rotation via PhotoView internal functions. Name is chosen so it won't collide with
262 | * View.setRotation(float) in API since 11
263 | *
264 | * @param rotationDegree - Degree to rotate PhotoView by, should be in range 0 to 360
265 | */
266 | void setPhotoViewRotation(float rotationDegree);
267 |
268 | /**
269 | * Extracts currently visible area to Bitmap object, if there is no image loaded yet or the
270 | * ImageView is already destroyed, returns {@code null}
271 | *
272 | * @return currently visible area as bitmap or null
273 | */
274 | Bitmap getVisibleRectangleBitmap();
275 |
276 | /**
277 | * Allows to change zoom transition speed, default value is 200 (PhotoViewAttacher.DEFAULT_ZOOM_DURATION).
278 | * Will default to 200 if provided negative value
279 | *
280 | * @param milliseconds duration of zoom interpolation
281 | */
282 | void setZoomTransitionDuration(int milliseconds);
283 | }
284 |
--------------------------------------------------------------------------------
/library-lis/src/main/java/com/cocolover2/lis/activity/LisBaseListImgsActivity.java:
--------------------------------------------------------------------------------
1 | package com.cocolover2.lis.activity;
2 |
3 | import android.os.Bundle;
4 | import android.os.Handler;
5 | import android.os.HandlerThread;
6 | import android.os.Message;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.animation.Animation;
11 | import android.view.animation.AnimationUtils;
12 | import android.widget.AdapterView;
13 | import android.widget.FrameLayout;
14 | import android.widget.GridView;
15 | import android.widget.ImageView;
16 | import android.widget.LinearLayout;
17 | import android.widget.ListView;
18 |
19 | import com.cocolover2.lis.AlbumHelper;
20 | import com.cocolover2.lis.LISConstant;
21 | import com.cocolover2.lis.LocalImageLoader;
22 | import com.cocolover2.lis.interf.OnSelectResultListener;
23 | import com.cocolover2.lis.R;
24 | import com.cocolover2.lis.adapter.ImageBucketAdapter;
25 | import com.cocolover2.lis.adapter.ImageGridAdapter;
26 | import com.cocolover2.lis.entity.ImageBucket;
27 | import com.cocolover2.lis.entity.ImageItem;
28 |
29 | import java.util.ArrayList;
30 |
31 |
32 | public abstract class LisBaseListImgsActivity extends AppCompatActivity {
33 | private ArrayList dataList = new ArrayList<>();//本地图片的数据源
34 | private ImageBucket selectedBucket;//先去选择的文件夹
35 | private ArrayList mBucketLists = new ArrayList<>(); //所有图片文件夹
36 |
37 | private int itemWidth;//图片宽度
38 | private Handler alphaHandler;
39 | private boolean isChangeAlpha;
40 | private int mAlpha = 0;
41 | private OnSelectResultListener selectResultListener;
42 |
43 |
44 | private GridView gridView;
45 | private ImageGridAdapter adapter;
46 | //pop
47 | private LinearLayout popLayout;
48 | private ListView popListview;
49 | private Animation popAnim;
50 | private boolean isPopShow;
51 |
52 | private boolean isrefresh;
53 |
54 |
55 | public abstract int getTopLayoutId();
56 |
57 | public abstract int getBottomLayoutId();
58 |
59 | public abstract void onMyCreate(Bundle savedInstanceState);
60 |
61 | public abstract void onBucketSelect(String bucketName);
62 |
63 |
64 | protected boolean isPopShow() {
65 | return isPopShow;
66 | }
67 |
68 | protected boolean isShowActionBar() {
69 | return false;
70 | }
71 |
72 | @Override
73 | protected void onCreate(Bundle savedInstanceState) {
74 | super.onCreate(savedInstanceState);
75 | if (!isShowActionBar() && getSupportActionBar() != null) {
76 | getSupportActionBar().hide();
77 | }
78 | setContentView(R.layout.lis_activity_img_list);
79 | initView();
80 | onMyCreate(savedInstanceState);
81 | setUpView();
82 |
83 | }
84 |
85 | private void initView() {
86 | itemWidth = getResources().getDisplayMetrics().widthPixels / 3;
87 | gridView = (GridView) findViewById(R.id.lis_activity_img_list_gv);
88 | gridView.setColumnWidth(itemWidth);
89 | popLayout = (LinearLayout) findViewById(R.id.layout_bucket_pop_container);
90 | popListview = (ListView) findViewById(R.id.layout_bucket_pop_listview);
91 | if (getTopLayoutId() > 0) {
92 | final FrameLayout topLayout = (FrameLayout) findViewById(R.id.lis_activity_img_list_top);
93 | final View topView = LayoutInflater.from(this).inflate(getTopLayoutId(), topLayout, false);
94 | topLayout.addView(topView, topView.getLayoutParams());
95 | }
96 | if (getBottomLayoutId() > 0) {
97 | final FrameLayout bottomLayout = (FrameLayout) findViewById(R.id.lis_activity_img_list_bottom);
98 | final View bottomView = LayoutInflater.from(this).inflate(getBottomLayoutId(), bottomLayout, false);
99 | bottomLayout.addView(bottomView, bottomView.getLayoutParams());
100 | }
101 | popLayout.getBackground().setAlpha(0);
102 | popLayout.setOnClickListener(new View.OnClickListener() {
103 | @Override
104 | public void onClick(View v) {
105 | if (isPopShow) {
106 | hidePop();
107 | }
108 | }
109 | });
110 | }
111 |
112 | protected void setOnSelectResultListener(OnSelectResultListener listener) {
113 | selectResultListener = listener;
114 | }
115 |
116 | protected int getSelectImgCount() {
117 | return AlbumHelper.getHasSelectCount();
118 | }
119 |
120 | private void setUpView() {
121 | if (mBucketLists.size() <= 0)
122 | mBucketLists = new AlbumHelper().getImageBucketList(this);
123 | initPop();
124 | dataList.clear();
125 | dataList.addAll(mBucketLists.get(0).imageList);
126 | adapter = new ImageGridAdapter(this, dataList, itemWidth);
127 | gridView.setAdapter(adapter);
128 | LocalImageLoader.getInstance().setFlingStopLoading(gridView);
129 | adapter.setResultCallBack(selectResultListener);
130 | }
131 |
132 | @Override
133 | protected void onStart() {
134 | super.onStart();
135 | if (isrefresh) {
136 | adapter.refresh();
137 | }
138 | isrefresh = false;
139 | }
140 |
141 | protected void clearSelectedImgs() {
142 | AlbumHelper.clearSelectedImgs();
143 | }
144 |
145 | @Override
146 | protected void onPause() {
147 | super.onPause();
148 | isrefresh = true;
149 | }
150 |
151 | private void changeBucket(ArrayList imageList) {
152 | dataList.clear();
153 | dataList.addAll(imageList);
154 | gridView.smoothScrollToPosition(0);
155 | adapter.refresh();
156 | }
157 |
158 | protected void setMaxSize(int maxSize) {
159 | AlbumHelper.setMaxSize(maxSize);
160 | }
161 |
162 | protected int getMaxSize() {
163 | return AlbumHelper.getMaxSize();
164 | }
165 |
166 | protected ArrayList getSelectImgs() {
167 | return AlbumHelper.getHasSelectImgs();
168 | }
169 |
170 | protected ArrayList getSelectImgPaths() {
171 | final ArrayList datas = new ArrayList<>();
172 | if (getSelectImgs() == null)
173 | return null;
174 | else {
175 | for (ImageItem item : getSelectImgs()) {
176 | datas.add(item.imagePath);
177 | }
178 | }
179 | return datas;
180 | }
181 |
182 | protected void setIsPreView(boolean flag) {
183 | ImageGridAdapter.setIsPreView(flag);
184 | }
185 |
186 | protected void showPop() {
187 | isPopShow = true;
188 | popAnim = AnimationUtils.loadAnimation(this, R.anim.bucket_pop_in);
189 | popLayout.setVisibility(View.VISIBLE);
190 | popAnim.setAnimationListener(new Animation.AnimationListener() {
191 | @Override
192 | public void onAnimationStart(Animation animation) {
193 | isChangeAlpha = true;
194 | changeAlpha(true);
195 | }
196 |
197 | @Override
198 | public void onAnimationEnd(Animation animation) {
199 | isChangeAlpha = false;
200 | }
201 |
202 | @Override
203 | public void onAnimationRepeat(Animation animation) {
204 | }
205 | });
206 | popListview.startAnimation(popAnim);
207 | }
208 |
209 | protected void hidePop() {
210 | isPopShow = false;
211 | popAnim = AnimationUtils.loadAnimation(this, R.anim.bucket_pop_out);
212 | popAnim.setAnimationListener(new Animation.AnimationListener() {
213 | @Override
214 | public void onAnimationStart(Animation animation) {
215 | isChangeAlpha = true;
216 | changeAlpha(false);
217 | }
218 |
219 | @Override
220 | public void onAnimationEnd(Animation animation) {
221 | isChangeAlpha = false;
222 | popLayout.setVisibility(View.GONE);
223 | }
224 |
225 | @Override
226 | public void onAnimationRepeat(Animation animation) {
227 | }
228 | });
229 | popListview.startAnimation(popAnim);
230 | }
231 |
232 | private void initPop() {
233 | selectedBucket = mBucketLists.get(0);
234 | final ImageBucketAdapter bucketAdapter = new ImageBucketAdapter(this, mBucketLists);
235 | popListview.setAdapter(bucketAdapter);
236 | popListview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
237 | @Override
238 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
239 | final ImageBucket curBucket = mBucketLists.get(position);
240 | if (curBucket != selectedBucket) {
241 | ImageView selectBucketFlagIv = (ImageView) view
242 | .findViewById(R.id.img_bucket_item_choose_flag);
243 | selectBucketFlagIv.setImageResource(R.drawable.ic_selected);
244 | curBucket.isSelected = true;
245 | selectedBucket.isSelected = false;
246 | selectedBucket = curBucket;
247 | onBucketSelect(curBucket.bucketName);
248 | changeBucket(curBucket.imageList);
249 | bucketAdapter.notifyDataSetChanged();
250 | }
251 | hidePop();
252 | }
253 | });
254 | }
255 |
256 | private Handler mHandler = new Handler(new Handler.Callback() {
257 | @Override
258 | public boolean handleMessage(Message msg) {
259 | switch (msg.what) {
260 | case 0:
261 | popLayout.getBackground().setAlpha(0);
262 | break;
263 | case 255:
264 | popLayout.getBackground().setAlpha(255);
265 | break;
266 | case 1:
267 | popLayout.getBackground().setAlpha(mAlpha);
268 | break;
269 | }
270 | return true;
271 | }
272 | });
273 | private Runnable upAlphaRunnable = new Runnable() {
274 | @Override
275 | public void run() {
276 | if (mAlpha > 255 || !isChangeAlpha) {
277 | mHandler.sendEmptyMessage(255);
278 | alphaHandler.removeCallbacks(upAlphaRunnable);
279 | } else {
280 | mHandler.sendEmptyMessage(1);
281 | alphaHandler.postDelayed(upAlphaRunnable, 15);
282 | }
283 | mAlpha += 8;
284 | }
285 | };
286 |
287 | private Runnable downAlphaRunnable = new Runnable() {
288 | @Override
289 | public void run() {
290 | if (mAlpha < 0 || !isChangeAlpha) {
291 | mHandler.sendEmptyMessage(0);
292 | alphaHandler.removeCallbacks(downAlphaRunnable);
293 | } else {
294 | mHandler.sendEmptyMessage(1);
295 | alphaHandler.postDelayed(downAlphaRunnable, 15);
296 | }
297 | mAlpha -= 8;
298 | }
299 | };
300 |
301 | //更改透明度
302 | private void changeAlpha(final boolean isIncrement) {
303 | if (!isChangeAlpha) {
304 | return;
305 | }
306 | final HandlerThread coverAlphaThread = new HandlerThread("changeAlphaThreadd");
307 | coverAlphaThread.start();
308 | alphaHandler = new Handler(coverAlphaThread.getLooper());
309 | if (!isIncrement) {
310 | mAlpha = 255;
311 | alphaHandler.post(downAlphaRunnable);
312 | } else {
313 | mAlpha = 0;
314 | alphaHandler.post(upAlphaRunnable);
315 | }
316 | }
317 |
318 | @Override
319 | protected void onDestroy() {
320 | super.onDestroy();
321 | mBucketLists.clear();
322 | mBucketLists = null;
323 | AlbumHelper.clearSelectedImgs();
324 | }
325 | }
326 |
--------------------------------------------------------------------------------