├── .idea
├── .name
├── copyright
│ └── profiles_settings.xml
├── vcs.xml
├── modules.xml
├── gradle.xml
├── compiler.xml
└── misc.xml
├── app
├── .gitignore
├── libs
│ └── uil.jar
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── drawable-xhdpi
│ │ │ │ ├── back.png
│ │ │ │ ├── icon_go.png
│ │ │ │ ├── icon_back2.png
│ │ │ │ ├── post_add_pic.png
│ │ │ │ ├── progress_icon.png
│ │ │ │ ├── album_finish.9.png
│ │ │ │ ├── albumset_selected.png
│ │ │ │ ├── btn_posts_camera_l.png
│ │ │ │ ├── post_pager_delete.png
│ │ │ │ ├── albumset_preselected.png
│ │ │ │ └── dangkr_no_picture_small.png
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── values
│ │ │ │ ├── strings.xml
│ │ │ │ ├── standard_color.xml
│ │ │ │ ├── standard_dimens.xml
│ │ │ │ ├── styles.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── dimens.xml
│ │ │ ├── drawable
│ │ │ │ ├── white_gray_bg_selector.xml
│ │ │ │ └── picture_setting_album_checkbox.xml
│ │ │ ├── menu
│ │ │ │ └── menu_main.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── anim
│ │ │ │ └── rotate_loading.xml
│ │ │ └── layout
│ │ │ │ ├── simple_list_item.xml
│ │ │ │ ├── item_albumfoler.xml
│ │ │ │ ├── item_album_pager.xml
│ │ │ │ ├── album_item_header_bar.xml
│ │ │ │ ├── local_album.xml
│ │ │ │ ├── local_album_detail.xml
│ │ │ │ └── post_dynamic.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── localalbum
│ │ │ ├── ui
│ │ │ ├── BaseActivity.java
│ │ │ ├── LocalAlbum.java
│ │ │ ├── DynamicPost.java
│ │ │ └── LocalAlbumDetail.java
│ │ │ ├── widget
│ │ │ ├── FilterImageView.java
│ │ │ ├── AlbumViewPager.java
│ │ │ └── MatrixImageView.java
│ │ │ ├── common
│ │ │ ├── MethodsCompat.java
│ │ │ ├── ExtraKey.java
│ │ │ ├── StringUtils.java
│ │ │ ├── LocalImageHelper.java
│ │ │ └── ImageUtils.java
│ │ │ ├── AppManager.java
│ │ │ └── AppContext.java
│ └── androidTest
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── localalbum
│ │ └── ApplicationTest.java
├── proguard-rules.pro
├── build.gradle
└── app.iml
├── settings.gradle
├── README.md
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── .gitignore
├── gradle.properties
├── LocalAlbum.iml
├── gradlew.bat
└── gradlew
/.idea/.name:
--------------------------------------------------------------------------------
1 | LocalAlbum
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/app/libs/uil.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/libs/uil.jar
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LocalAlbum
2 | 本地相册,遍历本地图片,支持多选图片功能。
3 | 博客地址 http://www.cnblogs.com/linjzong/p/4629800.html
4 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | /local.properties
3 | /.idea/workspace.xml
4 | /.idea/libraries
5 | .DS_Store
6 | /build
7 | /captures
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/back.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_go.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/icon_go.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/icon_back2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/icon_back2.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/post_add_pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/post_add_pic.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/progress_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/progress_icon.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/album_finish.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/album_finish.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/albumset_selected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/albumset_selected.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/btn_posts_camera_l.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/btn_posts_camera_l.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/post_pager_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/post_pager_delete.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/albumset_preselected.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/albumset_preselected.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/dangkr_no_picture_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LinJZong/LocalAlbum/HEAD/app/src/main/res/drawable-xhdpi/dangkr_no_picture_small.png
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | LocalAlbum
3 |
4 | Hello world!
5 | Settings
6 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
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.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/white_gray_bg_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/picture_setting_album_checkbox.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/example/localalbum/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum;
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/standard_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #333333
4 | #666666
5 | #999999
6 | #ffcccccc
7 | #ffeeeeee
8 | #ffffffff
9 | #15aeed
10 | #546893
11 | #6a7989
12 |
--------------------------------------------------------------------------------
/app/src/main/res/anim/rotate_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/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 /Users/linjizong/SDK/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 22
5 | buildToolsVersion '21.1.2'
6 |
7 | defaultConfig {
8 | applicationId "com.example.localalbum"
9 | minSdkVersion 15
10 | targetSdkVersion 22
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:22.2.0'
25 | compile files('libs/uil.jar')
26 | }
27 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/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
--------------------------------------------------------------------------------
/app/src/main/res/layout/simple_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
14 |
15 |
24 |
--------------------------------------------------------------------------------
/LocalAlbum.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/standard_dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 2.0dip
4 | 3.0dip
5 | 5.0dip
6 | 10.0dip
7 | 15.0dip
8 | 20.0dip
9 | 0.5dip
10 | 1dip
11 | 5dip
12 | 10dip
13 |
14 | 10dip
15 | 11dip
16 | 12dip
17 | 13dip
18 | 14dip
19 | 15.0dip
20 | 16dip
21 | 17dip
22 | 18.0dip
23 | 18dip
24 | 18dip
25 | 100dip
26 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_albumfoler.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
17 |
18 |
28 |
35 |
--------------------------------------------------------------------------------
/.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 | 1.7
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_album_pager.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
15 |
16 |
23 |
29 |
30 |
36 |
37 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/ui/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.ui;
2 |
3 | import android.app.Activity;
4 | import android.content.Intent;
5 | import android.content.pm.ActivityInfo;
6 | import android.os.Bundle;
7 | import android.os.Handler;
8 | import android.os.Message;
9 | import android.view.Window;
10 |
11 | import com.example.localalbum.AppContext;
12 | import com.example.localalbum.AppManager;
13 |
14 |
15 | /**
16 | * @Description:Activity基类
17 | * @author linjizong
18 | * @date 2015-3-18
19 | */
20 |
21 | /**
22 | * @Description:
23 | * @author linjizong
24 | * @date 2015-3-30
25 | */
26 | public class BaseActivity extends Activity {
27 | //应用是否销毁标志
28 | protected boolean isDestroy;
29 | //防止重复点击设置的标志,涉及到点击打开其他Activity时,将该标志设置为false,在onResume事件中设置为true
30 | private boolean clickable=true;
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 | isDestroy=false;
35 | //设置无标题
36 | requestWindowFeature(Window.FEATURE_NO_TITLE);
37 | //垂直显示
38 | setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
39 | // 添加Activity到堆栈
40 | AppManager.getAppManager().addActivity(this);
41 | }
42 |
43 | @Override
44 | protected void onDestroy() {
45 | super.onDestroy();
46 | isDestroy=true;
47 | // 结束Activity&从堆栈中移除
48 | AppManager.getAppManager().finishActivity(this);
49 | }
50 |
51 | @Override
52 | protected void onResume() {
53 | super.onResume();
54 | //每次返回界面时,将点击标志设置为可点击
55 | clickable=true;
56 | }
57 |
58 | /**
59 | * 当前是否可以点击
60 | * @return
61 | */
62 | protected boolean isClickable(){
63 | return clickable;
64 | }
65 |
66 | /**
67 | * 锁定点击
68 | */
69 | protected void lockClick(){
70 | clickable=false;
71 | }
72 |
73 |
74 |
75 | @Override
76 | public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
77 | if(isClickable()) {
78 | lockClick();
79 | super.startActivityForResult(intent, requestCode,options);
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/widget/FilterImageView.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.graphics.PorterDuff;
6 | import android.graphics.drawable.Drawable;
7 | import android.util.AttributeSet;
8 | import android.view.MotionEvent;
9 | import android.widget.ImageView;
10 |
11 |
12 | /**
13 | * @ClassName: ThumbnailView
14 | * @Description: 点击时显示明暗变化(滤镜效果)的ImageView
15 | * @author LinJ
16 | * @date 2015-1-6 下午2:13:46
17 | *
18 | */
19 | public class FilterImageView extends ImageView{
20 | public FilterImageView(Context context){
21 | super(context);
22 | }
23 | public FilterImageView(Context context, AttributeSet attrs) {
24 | super(context, attrs);
25 | // TODO Auto-generated constructor stub
26 | }
27 | public FilterImageView(Context context, AttributeSet attrs, int defStyle) {
28 | super(context, attrs, defStyle);
29 |
30 | }
31 | @Override
32 | public boolean onTouchEvent(MotionEvent event) {
33 | switch (event.getActionMasked()) {
34 | case MotionEvent.ACTION_DOWN:
35 | //在按下事件中设置滤镜
36 | setFilter();
37 | break;
38 | case MotionEvent.ACTION_UP:
39 | //由于捕获了Touch事件,需要手动触发Click事件
40 | performClick();
41 | case MotionEvent.ACTION_CANCEL:
42 | //在CANCEL和UP事件中清除滤镜
43 | removeFilter();
44 | break;
45 | default:
46 | break;
47 | }
48 | return true;
49 | }
50 |
51 | /**
52 | * 设置滤镜
53 | */
54 | private void setFilter() {
55 | //先获取设置的src图片
56 | Drawable drawable=getDrawable();
57 | //当src图片为Null,获取背景图片
58 | if (drawable==null) {
59 | drawable=getBackground();
60 | }
61 | if(drawable!=null){
62 | //设置滤镜
63 | drawable.setColorFilter(Color.GRAY,PorterDuff.Mode.MULTIPLY);;
64 | }
65 | }
66 | /**
67 | * 清除滤镜
68 | */
69 | private void removeFilter() {
70 | //先获取设置的src图片
71 | Drawable drawable=getDrawable();
72 | //当src图片为Null,获取背景图片
73 | if (drawable==null) {
74 | drawable=getBackground();
75 | }
76 | if(drawable!=null){
77 | //清除滤镜
78 | drawable.clearColorFilter();
79 | }
80 | }
81 |
82 |
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/common/MethodsCompat.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.common;
2 |
3 | import android.annotation.TargetApi;
4 | import android.app.Activity;
5 | import android.content.ContentResolver;
6 | import android.content.Context;
7 | import android.graphics.Bitmap;
8 | import android.graphics.BitmapFactory.Options;
9 | import android.graphics.Paint;
10 | import android.os.Build;
11 | import android.provider.MediaStore;
12 | import android.view.View;
13 | import android.view.Window;
14 |
15 | import java.io.File;
16 |
17 | /**
18 | * Android各版本的兼容方法
19 | * @author liux (http://my.oschina.net/liux)
20 | * @version 1.0
21 | * @created 2012-8-6
22 | */
23 | public class MethodsCompat {
24 |
25 | @TargetApi(5)
26 | public static void overridePendingTransition(Activity activity, int enter_anim, int exit_anim) {
27 | activity.overridePendingTransition(enter_anim, exit_anim);
28 | }
29 |
30 | @TargetApi(7)
31 | public static Bitmap getThumbnail(ContentResolver cr, long origId, int kind, Options options) {
32 | return MediaStore.Images.Thumbnails.getThumbnail(cr,origId,kind, options);
33 | }
34 |
35 | @TargetApi(8)
36 | public static File getExternalCacheDir(Context context) {
37 |
38 | // // return context.getExternalCacheDir(); API level 8
39 | //
40 | // // e.g. "/Android/data//cache/"
41 | // final File extCacheDir = new File(Environment.getExternalStorageDirectory(),
42 | // "/Android/data/" + context.getApplicationInfo().packageName + "/cache/");
43 | // extCacheDir.mkdirs();
44 | // return extCacheDir;
45 |
46 | return context.getExternalCacheDir();
47 | }
48 |
49 | @TargetApi(11)
50 | public static void recreate(Activity activity) {
51 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
52 | activity.recreate();
53 | }
54 | }
55 |
56 | @TargetApi(11)
57 | public static void setLayerType(View view, int layerType, Paint paint) {
58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
59 | view.setLayerType(layerType, paint);
60 | }
61 | }
62 |
63 | @TargetApi(14)
64 | public static void setUiOptions(Window window, int uiOptions) {
65 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
66 | window.setUiOptions(uiOptions);
67 | }
68 | }
69 |
70 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/common/ExtraKey.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.common;
2 |
3 | /**
4 | * @Description: 界面跳转时 传递的key 命名方式为:来源Activity_目标Activity_KEY名称
5 | * @author linjizong
6 | * @date 2015-3-24
7 | */
8 | public class ExtraKey {
9 |
10 | public static final String USERINFO_EDIT_TITLE="title";//标题
11 | public static final String USERINFO_EDIT_VALUE="value";//内容
12 | public static final String USER_PROPERTYKEY="key";//在property文件中得key
13 | public static final String USERINFO_EDIT_NUMBER="number";//输入格式是否位数字
14 | public static final String USERINFO_MAX_LENGTH="max";//输入最大长度
15 | public static final String EDIT_USERINFO_VALUE="value";//修改后返回的值
16 | public static final String SELECTINTEREST_USERINFO_VALUE="interest";//选择爱好后返回的值
17 | public static final String PROVINCE_CITY_NAME="province";//当前选择的省份
18 | public static final String CLUB_CLUBINFO_ID="clubid";//当前选择的俱乐部ID
19 | public static final String STATUS="status";//状态码,不同状态代表不同请求.0:关注 1:粉丝 2:想去 3:已报名
20 | public static final String MAIN_POSITION="position";//主界面当前标签位置,主要用以登录时切换到“我的”界面
21 | public static final String USERINFO_SIGNTURE = "signture";
22 |
23 | public static final String BROWSER_TITLE="browser_title";//浏览器标题
24 | public static final String BROWSER_URL="browser_url";//浏览器链接
25 |
26 | public static final String ACTIVITY_ID="activity_id";//活动ID
27 | public static final String CLUB_ID="club_id";//俱乐部ID
28 |
29 | public static final String FROM_ACTIVITY="from_activity";//在地区选择界面使用,标记是否从activity界面进入
30 | public static final String URL_ARRAYLIST="url_arraylist";//图片查看界面的url数组
31 | public static final String URL_ARRAYLIST_ACTIVE="url_arraylist_active";//当前选择的图片
32 |
33 | public static final String ACTIVITY_TYPE="activity_type";//活动类型:想去或带领的活动
34 | public static final String ACTIVITY_STATUS="activity_status";//活动状态:进行中或已结束
35 |
36 | public static final String DANGKR_TYPE="dangkr_type";//荡客界面跳转到列表界面时的请求类型
37 | public static final String DANGKR_TITLE="dangkr_title";//荡客界面跳转到列表界面时的标题
38 | public static final String HOME_PAGE_ID="home_page_id";//跳转到个人主页传递的人物ID
39 | public static final String HOME_PAGE_IS_LEADER="home_page_is_leader";//个人主页是否领队
40 |
41 | public static final String USER_ID="user_id";//跳转到动态界面的人物ID
42 | public static final String USER_NAME="user_name";//跳转到动态界面传递的人物名称
43 | public static final String LOCAL_FOLDER_NAME="local_folder_name";//跳转到相册页的文件夹名称
44 |
45 | public static final String DYNAMIC_ID_AND_DATE="dynamic_id_and_date";//动态ID和时间戳字符串
46 | }
47 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/AppManager.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 |
6 |
7 | import java.util.Stack;
8 |
9 |
10 | /**
11 | * @Description:Activity管理类
12 | * @author linjizong
13 | * @date 2015-4-11
14 | */
15 | public class AppManager {
16 | private static Stack activityStack;
17 | private static AppManager instance;
18 | private AppManager(){}
19 | /**
20 | * 单一实例
21 | */
22 | public static AppManager getAppManager(){
23 | if(instance==null){
24 | instance=new AppManager();
25 | }
26 | return instance;
27 | }
28 | /**
29 | * 添加Activity到堆栈
30 | */
31 | public void addActivity(Activity activity){
32 | if(activityStack==null){
33 | activityStack=new Stack();
34 | }
35 | activityStack.add(activity);
36 | }
37 | /**
38 | * 获取当前Activity(堆栈中最后一个压入的)
39 | */
40 | public Activity currentActivity(){
41 | Activity activity=activityStack.lastElement();
42 | return activity;
43 | }
44 | /**
45 | * 结束当前Activity(堆栈中最后一个压入的)
46 | */
47 | public void finishActivity(){
48 | Activity activity=activityStack.lastElement();
49 | finishActivity(activity);
50 | }
51 | /**
52 | * 结束指定的Activity
53 | */
54 | public void finishActivity(Activity activity){
55 | // //应用即将全部关闭,清理缓存
56 | // if(activityStack.size()==1){
57 | // ((AppContext)activity.getApplication()).clearWebViewCache();
58 | //
59 | // }
60 | if(activity!=null){
61 | activityStack.remove(activity);
62 | activity.finish();
63 | activity=null;
64 | }
65 | }
66 | /**
67 | * 结束指定类名的Activity
68 | */
69 | public void finishActivity(Class> cls){
70 | for (Activity activity : activityStack) {
71 | if(activity.getClass().equals(cls) ){
72 | finishActivity(activity);
73 | }
74 | }
75 | }
76 | //获取指定类名的Activity
77 | public Activity getActivity(Class> cls){
78 | for (Activity activity : activityStack) {
79 | if(activity.getClass().equals(cls) ){
80 | return activity ;
81 | }
82 | }
83 | return null;
84 | }
85 |
86 | /**
87 | * 结束所有Activity
88 | */
89 | public void finishAllActivity(){
90 | for (int i = 0, size = activityStack.size(); i < size; i++){
91 | if (null != activityStack.get(i)){
92 | activityStack.get(i).finish();
93 | }
94 | }
95 | activityStack.clear();
96 | }
97 | /**
98 | * 退出应用程序
99 | */
100 | public void AppExit(Context context) {
101 | try {
102 | finishAllActivity();
103 | System.exit(0);
104 | } catch (Exception e) { }
105 | }
106 |
107 |
108 |
109 |
110 |
111 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/album_item_header_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
22 |
23 |
34 |
35 |
45 |
46 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
24 |
25 |
26 |
35 |
36 |
37 |
46 |
47 |
48 |
49 |
50 |
55 |
56 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/local_album.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
24 |
25 |
34 |
35 |
43 |
44 |
45 |
46 |
47 |
48 |
55 |
56 |
62 |
63 |
70 |
71 |
79 |
80 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/AppContext.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import android.view.Display;
6 | import android.view.WindowManager;
7 |
8 | import com.example.localalbum.common.LocalImageHelper;
9 | import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
10 | import com.nostra13.universalimageloader.core.ImageLoader;
11 | import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
12 | import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
13 | import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
14 |
15 | import java.io.File;
16 |
17 | //
18 |
19 | /**
20 | * 全局应用程序类:用于保存和调用全局应用配置及访问网络数据
21 | *
22 | * @author linjizong
23 | * @created 2015-3-22
24 | */
25 | public class AppContext extends Application {
26 | private static final String TAG = AppContext.class.getSimpleName();
27 | private static final String APP_CACAHE_DIRNAME = "/webcache";
28 |
29 | //singleton
30 | private static AppContext appContext = null;
31 | private Display display;
32 |
33 |
34 |
35 | @Override
36 | public void onCreate() {
37 | super.onCreate();
38 | appContext = this;
39 | init();
40 | }
41 |
42 | public static AppContext getInstance() {
43 | return appContext;
44 | }
45 |
46 | /**
47 | * 初始化
48 | */
49 | private void init() {
50 | initImageLoader(getApplicationContext());
51 | //本地图片辅助类初始化
52 | LocalImageHelper.init(this);
53 | if (display == null) {
54 | WindowManager windowManager = (WindowManager)
55 | getSystemService(Context.WINDOW_SERVICE);
56 | display = windowManager.getDefaultDisplay();
57 | }
58 | }
59 |
60 |
61 | public static void initImageLoader(Context context) {
62 | ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
63 | config.threadPriority(Thread.NORM_PRIORITY);
64 | config.denyCacheImageMultipleSizesInMemory();
65 | config.memoryCacheSize((int) Runtime.getRuntime().maxMemory() / 4);
66 | config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
67 | config.diskCacheSize(100 * 1024 * 1024); // 100 MiB
68 | config.tasksProcessingOrder(QueueProcessingType.LIFO);
69 | //修改连接超时时间5秒,下载超时时间5秒
70 | config.imageDownloader(new BaseImageDownloader(appContext, 5 * 1000, 5 * 1000));
71 | // config.writeDebugLogs(); // Remove for release app
72 | // Initialize ImageLoader with configuration.
73 | ImageLoader.getInstance().init(config.build());
74 | }
75 |
76 | public String getCachePath() {
77 | File cacheDir;
78 | if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
79 | cacheDir = getExternalCacheDir();
80 | else
81 | cacheDir = getCacheDir();
82 | if (!cacheDir.exists())
83 | cacheDir.mkdirs();
84 | return cacheDir.getAbsolutePath();
85 | }
86 | /**
87 | * @return
88 | * @Description: 获取当前屏幕的宽度
89 | */
90 | public int getWindowWidth() {
91 | return display.getWidth();
92 | }
93 |
94 | /**
95 | * @return
96 | * @Description: 获取当前屏幕的高度
97 | */
98 | public int getWindowHeight() {
99 | return display.getHeight();
100 | }
101 |
102 | /**
103 | * @return
104 | * @Description: 获取当前屏幕一半宽度
105 | */
106 | public int getHalfWidth() {
107 | return display.getWidth() / 2;
108 | }
109 |
110 | /**
111 | * @return
112 | * @Description: 获取当前屏幕1/4宽度
113 | */
114 | public int getQuarterWidth() {
115 | return display.getWidth() / 4;
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #ffffffff
5 | #ff363636
6 | #00000000
7 | #ffeeeeee
8 | #00000000
9 | #000000
10 | #c6c6c6
11 | #037BFF
12 | #FD4A2E
13 | #8F8F8F
14 | #aa111213
15 | #ffeeeeee
16 | #fffcfcfd
17 |
18 |
19 | #fffded
20 | #bdbdbd
21 | #3799df
22 | #ffffffff
23 | #646464
24 | #8f8f8f
25 | #cbcbcb
26 |
27 |
28 | #4da0e4
29 | #ffffff
30 | #e3f1fa
31 |
32 |
33 | #00adef
34 | #ffffff
35 |
36 |
37 | #f8f8f8
38 | #2c2c2c
39 | #1cb6f4
40 |
41 |
42 | #ffffff
43 | #d9d9d9
44 | #cacaca
45 | #333333
46 | #999999
47 | #f6f7fb
48 | #9c9f9d
49 | #6fbce6
50 | #e7e8ea
51 | #656565
52 | #e7e7e7
53 | #313131
54 | #707070
55 | #f54c61
56 |
57 |
58 | #333333
59 | #999999
60 |
61 |
62 | #333333
63 | #3e9de0
64 |
65 |
66 | #f6f7fb
67 |
68 | #999999
69 | #333333
70 |
71 |
72 | #20b2ee
73 | #0392cd
74 | #dedede
75 |
76 |
77 | #eeeeee
78 | #333333
79 | #536893
80 |
81 | #cccccc
82 | #666666
83 |
84 | #eeeeee
85 |
86 |
87 | #ffffff
88 | #eeeeee
89 | #eeeeee
90 | #b0b0b0
91 | #333333
92 | #f1f1f1
93 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 12.0dip
5 | 12.0dip
6 | 45.0dip
7 | 10dip
8 | 10dip
9 | 15dip
10 | 0.5dip
11 | 50.0dip
12 |
13 |
14 | 15dip
15 | 44dip
16 | 20dip
17 | 25dip
18 | 15dip
19 | 15dip
20 | 15dip
21 | 20dip
22 | 75dip
23 |
24 | 40dip
25 | 15dip
26 | 18dip
27 | 15dip
28 | 20dip
29 | 45dip
30 | 4dip
31 |
32 |
33 | 45dip
34 | 20dip
35 | 25dip
36 | 20dip
37 | 90dip
38 | 40dip
39 | 15dip
40 |
41 |
42 | 55dip
43 | 8dip
44 | 4dip
45 | 3dip
46 |
47 |
48 | 15dip
49 | 150dip
50 | 36dip
51 | 6dip
52 | 65dip
53 | 25dip
54 | 50dip
55 | 41dip
56 | 30dip
57 | 15dip
58 | 15dip
59 | 180dip
60 | 30dip
61 | 80dip
62 | 60dip
63 | 20dip
64 | 5dip
65 | 30dip
66 | 18dip
67 | 10dip
68 | 6dip
69 | 8dip
70 | 5dip
71 | 140dip
72 | 90dip
73 | 77dip
74 | 28dip
75 |
76 |
77 | 95dip
78 | 50dip
79 | 18dip
80 | 25dip
81 |
82 |
83 | 65dip
84 | 45dip
85 |
86 |
87 | 190dip
88 |
89 |
90 | 10dip
91 | 20dip
92 | 50dip
93 |
94 |
95 | 35dip
96 | 10dip
97 | 55dip
98 | 15dip
99 |
100 |
101 | 44dip
102 | 27dip
103 |
104 |
105 | 190dip
106 | 80dip
107 | 10dip
108 | 60dip
109 |
110 | 200dip
111 |
112 |
113 | 12dip
114 | 15sp
115 | 45dip
116 |
117 |
--------------------------------------------------------------------------------
/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 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/local_album_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
24 |
25 |
37 |
38 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
67 |
68 |
73 |
74 |
79 |
80 |
85 |
86 |
95 |
96 |
107 |
108 |
121 |
122 |
133 |
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/post_dynamic.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
13 |
14 |
15 |
16 |
21 |
22 |
31 |
32 |
40 |
41 |
52 |
53 |
54 |
58 |
59 |
72 |
73 |
84 |
85 |
92 |
93 |
100 |
101 |
106 |
107 |
108 |
109 |
120 |
121 |
125 |
126 |
127 |
132 |
133 |
138 |
139 |
145 |
146 |
147 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/widget/AlbumViewPager.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.widget;
2 |
3 |
4 | import android.content.Context;
5 | import android.graphics.Bitmap;
6 | import android.support.v4.view.PagerAdapter;
7 | import android.support.v4.view.ViewPager;
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.TextView;
13 |
14 | import com.example.localalbum.R;
15 | import com.example.localalbum.common.LocalImageHelper;
16 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
17 | import com.nostra13.universalimageloader.core.ImageLoader;
18 | import com.nostra13.universalimageloader.core.assist.FailReason;
19 | import com.nostra13.universalimageloader.core.assist.ImageScaleType;
20 | import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
21 | import com.nostra13.universalimageloader.core.imageaware.ImageViewAware;
22 | import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
23 | import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener;
24 |
25 | import java.util.List;
26 |
27 |
28 | /**
29 | * @ClassName: AlbumViewPager
30 | * @Description: 自定义viewpager 优化了事件拦截
31 | * @author LinJ
32 | * @date 2015-1-9 下午5:33:33
33 | *
34 | */
35 | public class AlbumViewPager extends ViewPager implements MatrixImageView.OnMovingListener {
36 | public final static String TAG="AlbumViewPager";
37 |
38 |
39 | /** 当前子控件是否处理拖动状态 */
40 | private boolean mChildIsBeingDragged=false;
41 |
42 | /** 界面单击事件 用以显示和隐藏菜单栏 */
43 | private MatrixImageView.OnSingleTapListener onSingleTapListener;
44 | DisplayImageOptions options;
45 | //本地图片的option
46 | DisplayImageOptions localOptions;
47 |
48 | private class ProcressListener implements ImageLoadingProgressListener {
49 | private View mView = null;
50 |
51 | public ProcressListener(View view){
52 | this.mView = view;
53 | }
54 | @Override
55 | public void onProgressUpdate(String arg0, View view, int current, int total) {
56 | TextView loadText = (TextView) mView.findViewById(R.id.current_procress);
57 | loadText.setText(String.valueOf(100 * current / total) + "%");
58 | loadText.bringToFront();
59 | }
60 |
61 | }
62 |
63 |
64 | private ImageLoadingListener loadingListenerr = new ImageLoadingListener(){
65 |
66 | @Override
67 | public void onLoadingCancelled(String arg0, View arg1) {
68 | }
69 |
70 | @Override
71 | public void onLoadingComplete(String arg0, View view, Bitmap arg2) {
72 | view.setVisibility(View.VISIBLE);
73 | view.getParent().bringChildToFront(view);
74 | }
75 |
76 | @Override
77 | public void onLoadingFailed(String arg0, View view, FailReason arg2) {
78 | // view.setVisibility(View.VISIBLE);
79 | // view.getParent().bringChildToFront(view);
80 | }
81 |
82 | @Override
83 | public void onLoadingStarted(String arg0, View arg1) {
84 | }
85 |
86 | };
87 |
88 |
89 |
90 |
91 |
92 | /** 播放按钮点击事件 */
93 | public AlbumViewPager(Context context, AttributeSet attrs) {
94 | super(context, attrs);
95 | localOptions=new DisplayImageOptions.Builder()
96 | .cacheInMemory(true)
97 | .cacheOnDisk(false)
98 | .bitmapConfig(Bitmap.Config.RGB_565)
99 | .imageScaleType(ImageScaleType.EXACTLY)
100 | .displayer(new SimpleBitmapDisplayer()).build();
101 | //DisplayImageOptions.getDefaltOpitions(0, R.drawable.dangkr_no_picture,
102 | //((AppContext)context.getApplicationContext()).getWindowWidth());
103 | }
104 |
105 |
106 |
107 |
108 |
109 |
110 | @Override
111 | public boolean onInterceptTouchEvent(MotionEvent arg0) {
112 | if(mChildIsBeingDragged)
113 | return false;
114 | return super.onInterceptTouchEvent(arg0);
115 | }
116 |
117 | @Override
118 | public void startDrag() {
119 | // TODO Auto-generated method stub
120 | mChildIsBeingDragged=true;
121 | }
122 |
123 |
124 | @Override
125 | public void stopDrag() {
126 | // TODO Auto-generated method stub
127 | mChildIsBeingDragged=false;
128 | }
129 |
130 | public void setOnSingleTapListener(MatrixImageView.OnSingleTapListener onSingleTapListener) {
131 | this.onSingleTapListener = onSingleTapListener;
132 | }
133 |
134 | public class ViewPagerAdapter extends PagerAdapter {
135 | private List paths;//大图地址 如果为网络图片 则为大图url
136 | public ViewPagerAdapter(List paths){
137 | this.paths=paths;
138 | }
139 |
140 | @Override
141 | public int getCount() {
142 | return paths.size();
143 | }
144 |
145 | @Override
146 | public Object instantiateItem(ViewGroup viewGroup, int position) {
147 | //注意,这里不可以加inflate的时候直接添加到viewGroup下,而需要用addView重新添加
148 | //因为直接加到viewGroup下会导致返回的view为viewGroup
149 | View imageLayout = inflate(getContext(),R.layout.item_album_pager, null);
150 | viewGroup.addView(imageLayout);
151 | assert imageLayout != null;
152 | MatrixImageView imageView = (MatrixImageView) imageLayout.findViewById(R.id.image);
153 | imageView.setOnMovingListener(AlbumViewPager.this);
154 | imageView.setOnSingleTapListener(onSingleTapListener);
155 | String path=paths.get(position);
156 | ImageLoader.getInstance().displayImage(path, imageView, localOptions, loadingListenerr, new ProcressListener(imageLayout));
157 | return imageLayout;
158 | }
159 |
160 |
161 |
162 | @Override
163 | public int getItemPosition(Object object) {
164 | //在notifyDataSetChanged时返回None,重新绘制
165 | return POSITION_NONE;
166 | }
167 |
168 | @Override
169 | public void destroyItem(ViewGroup container, int arg1, Object object) {
170 | ((ViewPager) container).removeView((View) object);
171 | }
172 |
173 | @Override
174 | public boolean isViewFromObject(View arg0, Object arg1) {
175 | return arg0 == arg1;
176 | }
177 |
178 |
179 | }
180 |
181 | public class LocalViewPagerAdapter extends PagerAdapter {
182 | private List paths;//大图地址 如果为网络图片 则为大图url
183 | public LocalViewPagerAdapter(List paths){
184 | this.paths=paths;
185 | }
186 |
187 | @Override
188 | public int getCount() {
189 | return paths.size();
190 | }
191 |
192 | @Override
193 | public Object instantiateItem(ViewGroup viewGroup, int position) {
194 | //注意,这里不可以加inflate的时候直接添加到viewGroup下,而需要用addView重新添加
195 | //因为直接加到viewGroup下会导致返回的view为viewGroup
196 | View imageLayout = inflate(getContext(), R.layout.item_album_pager, null);
197 | viewGroup.addView(imageLayout);
198 | assert imageLayout != null;
199 | MatrixImageView imageView = (MatrixImageView) imageLayout.findViewById(R.id.image);
200 | imageView.setOnMovingListener(AlbumViewPager.this);
201 | imageView.setOnSingleTapListener(onSingleTapListener);
202 | LocalImageHelper.LocalFile path=paths.get(position);
203 | ImageLoader.getInstance().displayImage(path.getOriginalUri(), new ImageViewAware(imageView), localOptions, loadingListenerr,
204 | new ProcressListener(imageLayout),path.getOrientation());
205 |
206 | return imageLayout;
207 | }
208 |
209 |
210 |
211 | @Override
212 | public int getItemPosition(Object object) {
213 | //在notifyDataSetChanged时返回None,重新绘制
214 | return POSITION_NONE;
215 | }
216 |
217 | @Override
218 | public void destroyItem(ViewGroup container, int arg1, Object object) {
219 | ((ViewPager) container).removeView((View) object);
220 | }
221 |
222 | @Override
223 | public boolean isViewFromObject(View arg0, Object arg1) {
224 | return arg0 == arg1;
225 | }
226 | }
227 |
228 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/common/StringUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.common;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.InputStreamReader;
8 | import java.security.MessageDigest;
9 | import java.text.ParseException;
10 | import java.text.SimpleDateFormat;
11 | import java.util.Calendar;
12 | import java.util.Date;
13 | import java.util.TimeZone;
14 | import java.util.regex.Pattern;
15 | import java.util.zip.GZIPInputStream;
16 |
17 | /**
18 | * 字符串操作工具包
19 | *
20 | * @author liux (http://my.oschina.net/liux)
21 | * @version 1.0
22 | * @created 2012-3-21
23 | */
24 | public class StringUtils {
25 | private final static Pattern emailer = Pattern
26 | .compile("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*");
27 | // private final static SimpleDateFormat dateFormater = new
28 | // SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
29 | // private final static SimpleDateFormat dateFormater2 = new
30 | // SimpleDateFormat("yyyy-MM-dd");
31 |
32 | private final static ThreadLocal dateFormater = new ThreadLocal() {
33 | @Override
34 | protected SimpleDateFormat initialValue() {
35 | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
36 | }
37 | };
38 |
39 | private final static ThreadLocal dateFormater2 = new ThreadLocal() {
40 | @Override
41 | protected SimpleDateFormat initialValue() {
42 | return new SimpleDateFormat("yyyy-MM-dd");
43 | }
44 | };
45 |
46 | /**
47 | * 将字符串转为日期类型
48 | *
49 | * @param sdate
50 | * @return
51 | */
52 | public static Date toDate(String sdate) {
53 | try {
54 | return dateFormater.get().parse(sdate);
55 | } catch (ParseException e) {
56 | return null;
57 | }
58 | }
59 |
60 |
61 | /**
62 | * 判断给定字符串时间是否为今日
63 | *
64 | * @param sdate
65 | * @return boolean
66 | */
67 | public static boolean isToday(String sdate) {
68 | boolean b = false;
69 | Date time = toDate(sdate);
70 | Date today = new Date();
71 | if (time != null) {
72 | String nowDate = dateFormater2.get().format(today);
73 | String timeDate = dateFormater2.get().format(time);
74 | if (nowDate.equals(timeDate)) {
75 | b = true;
76 | }
77 | }
78 | return b;
79 | }
80 |
81 | /**
82 | * 返回long类型的今天的日期
83 | *
84 | * @return
85 | */
86 | public static long getToday() {
87 | Calendar cal = Calendar.getInstance();
88 | String curDate = dateFormater2.get().format(cal.getTime());
89 | curDate = curDate.replace("-", "");
90 | return Long.parseLong(curDate);
91 | }
92 |
93 | /**
94 | * @Description: 返回字符串格式的当前时间
95 | *@return
96 | */
97 | public static String getCurrentTime(){
98 | return dateFormater.get().format(new Date());
99 | }
100 | /**
101 | * 判断给定字符串是否空白串。 空白串是指由空格、制表符、回车符、换行符组成的字符串 若输入字符串为null或空字符串,返回true
102 | *
103 | * @param input
104 | * @return boolean
105 | */
106 | public static boolean isEmpty(String input) {
107 | if (input == null || "".equals(input))
108 | return true;
109 |
110 | for (int i = 0; i < input.length(); i++) {
111 | char c = input.charAt(i);
112 | if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
113 | return false;
114 | }
115 | }
116 | return true;
117 | }
118 |
119 |
120 | /**
121 | * 字符串转整数
122 | *
123 | * @param str
124 | * @param defValue
125 | * @return
126 | */
127 | public static int toInt(String str, int defValue) {
128 | try {
129 | return Integer.parseInt(str);
130 | } catch (Exception e) {
131 | }
132 | return defValue;
133 | }
134 |
135 | /**
136 | * 对象转整数
137 | *
138 | * @param obj
139 | * @return 转换异常返回 0
140 | */
141 | public static int toInt(Object obj) {
142 | if (obj == null)
143 | return 0;
144 | return toInt(obj.toString(), 0);
145 | }
146 |
147 | /**
148 | * 对象转整数
149 | *
150 | * @param obj
151 | * @return 转换异常返回 0
152 | */
153 | public static long toLong(String obj) {
154 | try {
155 | return Long.parseLong(obj);
156 | } catch (Exception e) {
157 | }
158 | return 0;
159 | }
160 |
161 |
162 | /**
163 | * 对象转浮点
164 | *
165 | * @param obj
166 | * @return 转换异常返回 0
167 | */
168 | public static double toDouble(String obj) {
169 | try {
170 | return Double.parseDouble(obj);
171 | } catch (Exception e) {
172 | }
173 | return 0;
174 | }
175 | /**
176 | * 字符串转布尔值
177 | *
178 | * @param b
179 | * @return 转换异常返回 false
180 | */
181 | public static boolean toBool(String b) {
182 | try {
183 | return Boolean.parseBoolean(b);
184 | } catch (Exception e) {
185 | }
186 | return false;
187 | }
188 |
189 | /**
190 | * 将一个InputStream流转换成字符串
191 | *
192 | * @param is
193 | * @return
194 | */
195 | public static String toConvertString(InputStream is) {
196 | StringBuffer res = new StringBuffer();
197 | InputStreamReader isr = new InputStreamReader(is);
198 | BufferedReader read = new BufferedReader(isr);
199 | try {
200 | String line;
201 | line = read.readLine();
202 | while (line != null) {
203 | res.append(line);
204 | line = read.readLine();
205 | }
206 | } catch (IOException e) {
207 | e.printStackTrace();
208 | } finally {
209 | try {
210 | if (null != isr) {
211 | isr.close();
212 | isr.close();
213 | }
214 | if (null != read) {
215 | read.close();
216 | read = null;
217 | }
218 | if (null != is) {
219 | is.close();
220 | is = null;
221 | }
222 | } catch (IOException e) {
223 | }
224 | }
225 | return res.toString();
226 | }
227 | // 解压缩
228 | public static String uncompress(InputStream str) throws IOException {
229 | if (str == null ) {
230 | return "";
231 | }
232 | ByteArrayOutputStream out = new ByteArrayOutputStream();
233 |
234 | GZIPInputStream gunzip = new GZIPInputStream(str);
235 | byte[] buffer = new byte[256];
236 | int n;
237 | while ((n = gunzip.read(buffer))>= 0) {
238 | out.write(buffer, 0, n);
239 | }
240 | // toString()使用平台默认编码,也可以显式的指定如toString("GBK")
241 | return out.toString("utf-8");
242 | }
243 | //M5D加密
244 | public static String MD5(String s) {
245 | char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
246 | try {
247 | byte[] btInput = s.getBytes();
248 | // 获得MD5摘要算法的 MessageDigest 对象
249 | MessageDigest mdInst = MessageDigest.getInstance("MD5");
250 | // 使用指定的字节更新摘要
251 | mdInst.update(btInput);
252 | // 获得密文
253 | byte[] md = mdInst.digest();
254 | // 把密文转换成十六进制的字符串形式
255 | int j = md.length;
256 | char str[] = new char[j * 2];
257 | int k = 0;
258 | for (int i = 0; i < j; i++) {
259 | byte byte0 = md[i];
260 | str[k++] = hexDigits[byte0 >>> 4 & 0xf];
261 | str[k++] = hexDigits[byte0 & 0xf];
262 | }
263 | return new String(str);
264 | } catch (Exception e) {
265 | e.printStackTrace();
266 | return null;
267 | }
268 | }
269 |
270 | private static final double EARTH_RADIUS = 6378137.0;
271 | public static double gps2m(double lat_a, double lng_a, double lat_b, double lng_b) {
272 | double radLat1 = (lat_a * Math.PI / 180.0);
273 | double radLat2 = (lat_b * Math.PI / 180.0);
274 | double a = radLat1 - radLat2;
275 | double b = (lng_a - lng_b) * Math.PI / 180.0;
276 | double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
277 | + Math.cos(radLat1) * Math.cos(radLat2)
278 | * Math.pow(Math.sin(b / 2), 2)));
279 | s = s * EARTH_RADIUS;
280 | s = Math.round(s * 10000) / 10000;
281 | return s;
282 | }
283 | }
284 |
--------------------------------------------------------------------------------
/app/app.iml:
--------------------------------------------------------------------------------
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 |
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 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/common/LocalImageHelper.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.common;
2 |
3 | import android.database.Cursor;
4 | import android.provider.MediaStore;
5 |
6 |
7 | import com.example.localalbum.AppContext;
8 |
9 | import java.io.File;
10 | import java.text.SimpleDateFormat;
11 | import java.util.ArrayList;
12 | import java.util.Date;
13 | import java.util.HashMap;
14 | import java.util.List;
15 | import java.util.Map;
16 |
17 | /**
18 | * Created by linjizong on 15/6/11.
19 | */
20 | public class LocalImageHelper {
21 | private static LocalImageHelper instance;
22 | private final AppContext context;
23 | final List checkedItems = new ArrayList<>();
24 |
25 | public int getCurrentSize() {
26 | return currentSize;
27 | }
28 |
29 | public void setCurrentSize(int currentSize) {
30 | this.currentSize = currentSize;
31 | }
32 |
33 | //当前选中得图片个数
34 | private int currentSize;
35 | public String getCameraImgPath() {
36 | return CameraImgPath;
37 | }
38 |
39 | public String setCameraImgPath() {
40 | String foloder= AppContext.getInstance().getCachePath()
41 | + "/PostPicture/";
42 | File savedir = new File(foloder);
43 | if (!savedir.exists()) {
44 | savedir.mkdirs();
45 | }
46 | String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss")
47 | .format(new Date());
48 | // 照片命名
49 | String picName = timeStamp + ".jpg";
50 | // 裁剪头像的绝对路径
51 | CameraImgPath = foloder + picName;
52 | return CameraImgPath;
53 | }
54 |
55 | //拍照时指定保存图片的路径
56 | private String CameraImgPath;
57 | //大图遍历字段
58 | private static final String[] STORE_IMAGES = {
59 | MediaStore.Images.Media._ID,
60 | MediaStore.Images.Media.DATA,
61 | MediaStore.Images.Media.ORIENTATION
62 | };
63 | //小图遍历字段
64 | private static final String[] THUMBNAIL_STORE_IMAGE = {
65 | MediaStore.Images.Thumbnails._ID,
66 | MediaStore.Images.Thumbnails.DATA
67 | };
68 |
69 | final List paths = new ArrayList<>();
70 |
71 | final Map> folders = new HashMap<>();
72 |
73 | private LocalImageHelper(AppContext context) {
74 | this.context = context;
75 | }
76 |
77 | public Map> getFolderMap() {
78 | return folders;
79 | }
80 |
81 | public static LocalImageHelper getInstance() {
82 | return instance;
83 | }
84 |
85 | public static void init(AppContext context) {
86 | instance = new LocalImageHelper(context);
87 | new Thread(new Runnable() {
88 | @Override
89 | public void run() {
90 | instance.initImage();
91 | }
92 | }).start();
93 | }
94 |
95 | public boolean isInited() {
96 | return paths.size() > 0;
97 | }
98 |
99 | public List getCheckedItems() {
100 | return checkedItems;
101 | }
102 |
103 | private boolean resultOk;
104 |
105 | public boolean isResultOk() {
106 | return resultOk;
107 | }
108 |
109 | public void setResultOk(boolean ok) {
110 | resultOk = ok;
111 | }
112 |
113 | private boolean isRunning = false;
114 |
115 | public synchronized void initImage() {
116 | if (isRunning)
117 | return;
118 | isRunning=true;
119 | if (isInited())
120 | return;
121 | //获取大图的游标
122 | Cursor cursor = context.getContentResolver().query(
123 | MediaStore.Images.Media.EXTERNAL_CONTENT_URI, // 大图URI
124 | STORE_IMAGES, // 字段
125 | null, // No where clause
126 | null, // No where clause
127 | MediaStore.Images.Media.DATE_TAKEN + " DESC"); //根据时间升序
128 | if (cursor == null)
129 | return;
130 | while (cursor.moveToNext()) {
131 | int id = cursor.getInt(0);//大图ID
132 | String path = cursor.getString(1);//大图路径
133 | File file = new File(path);
134 | //判断大图是否存在
135 | if (file.exists()) {
136 | //小图URI
137 | String thumbUri = getThumbnail(id, path);
138 | //获取大图URI
139 | String uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon().
140 | appendPath(Integer.toString(id)).build().toString();
141 | if(StringUtils.isEmpty(uri))
142 | continue;
143 | if (StringUtils.isEmpty(thumbUri))
144 | thumbUri = uri;
145 | //获取目录名
146 | String folder = file.getParentFile().getName();
147 |
148 | LocalFile localFile = new LocalFile();
149 | localFile.setOriginalUri(uri);
150 | localFile.setThumbnailUri(thumbUri);
151 | int degree = cursor.getInt(2);
152 | if (degree != 0) {
153 | degree = degree + 180;
154 | }
155 | localFile.setOrientation(360-degree);
156 |
157 | paths.add(localFile);
158 | //判断文件夹是否已经存在
159 | if (folders.containsKey(folder)) {
160 | folders.get(folder).add(localFile);
161 | } else {
162 | List files = new ArrayList<>();
163 | files.add(localFile);
164 | folders.put(folder, files);
165 | }
166 | }
167 | }
168 | folders.put("所有图片", paths);
169 | cursor.close();
170 | isRunning=false;
171 | }
172 |
173 | private String getThumbnail(int id, String path) {
174 | //获取大图的缩略图
175 | Cursor cursor = context.getContentResolver().query(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
176 | THUMBNAIL_STORE_IMAGE,
177 | MediaStore.Images.Thumbnails.IMAGE_ID + " = ?",
178 | new String[]{id + ""},
179 | null);
180 | if (cursor.getCount() > 0) {
181 | cursor.moveToFirst();
182 | int thumId = cursor.getInt(0);
183 | String uri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI.buildUpon().
184 | appendPath(Integer.toString(thumId)).build().toString();
185 | cursor.close();
186 | return uri;
187 | }
188 | cursor.close();
189 | return null;
190 | }
191 |
192 | public List getFolder(String folder) {
193 | return folders.get(folder);
194 | }
195 |
196 | public void clear(){
197 | checkedItems.clear();
198 | currentSize=(0);
199 | String foloder= AppContext.getInstance().getCachePath()
200 | + "/PostPicture/";
201 | File savedir = new File(foloder);
202 | if (savedir.exists()) {
203 | deleteFile(savedir);
204 | }
205 | }
206 | public void deleteFile(File file) {
207 |
208 | if (file.exists()) {
209 | if (file.isFile()) {
210 | file.delete();
211 | } else if (file.isDirectory()) {
212 | File files[] = file.listFiles();
213 | for (int i = 0; i < files.length; i++) {
214 | deleteFile(files[i]);
215 | }
216 | }
217 | } else {
218 | }
219 | }
220 | public static class LocalFile {
221 | private String originalUri;//原图URI
222 | private String thumbnailUri;//缩略图URI
223 | private int orientation;//图片旋转角度
224 |
225 | public String getThumbnailUri() {
226 | return thumbnailUri;
227 | }
228 |
229 | public void setThumbnailUri(String thumbnailUri) {
230 | this.thumbnailUri = thumbnailUri;
231 | }
232 |
233 | public String getOriginalUri() {
234 | return originalUri;
235 | }
236 |
237 | public void setOriginalUri(String originalUri) {
238 | this.originalUri = originalUri;
239 | }
240 |
241 |
242 | public int getOrientation() {
243 | return orientation;
244 | }
245 |
246 | public void setOrientation(int exifOrientation) {
247 | orientation = exifOrientation;
248 | }
249 |
250 | }
251 | }
252 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/ui/LocalAlbum.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.ui;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.content.res.Configuration;
6 | import android.graphics.Bitmap;
7 | import android.media.ExifInterface;
8 | import android.net.Uri;
9 | import android.os.Bundle;
10 | import android.os.Handler;
11 | import android.provider.MediaStore;
12 | import android.view.LayoutInflater;
13 | import android.view.View;
14 | import android.view.ViewGroup;
15 | import android.view.animation.Animation;
16 | import android.view.animation.AnimationUtils;
17 | import android.widget.AdapterView;
18 | import android.widget.BaseAdapter;
19 | import android.widget.ImageView;
20 | import android.widget.ListView;
21 | import android.widget.TextView;
22 | import android.widget.Toast;
23 |
24 |
25 | import com.example.localalbum.AppContext;
26 | import com.example.localalbum.R;
27 | import com.example.localalbum.common.ExtraKey;
28 | import com.example.localalbum.common.ImageUtils;
29 | import com.example.localalbum.common.LocalImageHelper;
30 | import com.example.localalbum.common.StringUtils;
31 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
32 | import com.nostra13.universalimageloader.core.ImageLoader;
33 | import com.nostra13.universalimageloader.core.assist.ImageSize;
34 | import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
35 | import com.nostra13.universalimageloader.core.imageaware.ImageViewAware;
36 |
37 | import java.io.File;
38 | import java.io.IOException;
39 | import java.util.ArrayList;
40 | import java.util.Collections;
41 | import java.util.Comparator;
42 | import java.util.Iterator;
43 | import java.util.List;
44 | import java.util.Map;
45 |
46 | /**
47 | * Created by linjizong on 15/6/12.
48 | * 本地相册
49 | */
50 | public class LocalAlbum extends BaseActivity {
51 | ListView listView;
52 | ImageView progress;
53 | LocalImageHelper helper;
54 | View camera;
55 | List folderNames;
56 |
57 | @Override
58 | protected void onCreate(Bundle savedInstanceState) {
59 | super.onCreate(savedInstanceState);
60 | setContentView(R.layout.local_album);
61 | listView = (ListView) findViewById(R.id.local_album_list);
62 | camera = findViewById(R.id.loacal_album_camera);
63 | camera.setOnClickListener(onClickListener);
64 | camera.setVisibility(View.GONE);
65 | progress = (ImageView) findViewById(R.id.progress_bar);
66 | helper = LocalImageHelper.getInstance();
67 | Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate_loading);
68 | progress.startAnimation(animation);
69 | findViewById(R.id.album_back).setOnClickListener(new View.OnClickListener() {
70 | @Override
71 | public void onClick(View view) {
72 | finish();
73 | }
74 | });
75 | new Thread(new Runnable() {
76 | @Override
77 | public void run() {
78 | //开启线程初始化本地图片列表,该方法是synchronized的,因此当AppContent在初始化时,此处阻塞
79 | LocalImageHelper.getInstance().initImage();
80 | runOnUiThread(new Runnable() {
81 | @Override
82 | public void run() {
83 | //初始化完毕后,显示文件夹列表
84 | if (!isDestroy) {
85 | initAdapter();
86 | progress.clearAnimation();
87 | ((View) progress.getParent()).setVisibility(View.GONE);
88 | listView.setVisibility(View.VISIBLE);
89 | camera.setVisibility(View.VISIBLE);
90 | }
91 | }
92 | });
93 | }
94 | }).start();
95 | listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
96 | @Override
97 | public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
98 | Intent intent = new Intent(LocalAlbum.this, LocalAlbumDetail.class);
99 | intent.putExtra(ExtraKey.LOCAL_FOLDER_NAME, folderNames.get(i));
100 | intent.setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
101 | startActivity(intent);
102 | }
103 | });
104 | }
105 |
106 | public void initAdapter() {
107 | listView.setAdapter(new FolderAdapter(this, helper.getFolderMap()));
108 | }
109 |
110 | View.OnClickListener onClickListener = new View.OnClickListener() {
111 | @Override
112 | public void onClick(View view) {
113 | if(LocalImageHelper.getInstance().getCurrentSize()+LocalImageHelper.getInstance().getCheckedItems().size()>=9){
114 | Toast.makeText(LocalAlbum.this,"最多选择9张图片",Toast.LENGTH_SHORT).show();
115 | return;
116 | }
117 | Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
118 | // 拍照后保存图片的绝对路径
119 | String cameraPath = LocalImageHelper.getInstance().setCameraImgPath();
120 | File file = new File(cameraPath);
121 | intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));
122 | startActivityForResult(intent,
123 | ImageUtils.REQUEST_CODE_GETIMAGE_BYCAMERA);
124 | }
125 | };
126 |
127 | @Override
128 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
129 | if (resultCode == RESULT_OK) {
130 | switch (requestCode) {
131 | case ImageUtils.REQUEST_CODE_GETIMAGE_BYCAMERA:
132 | String cameraPath = LocalImageHelper.getInstance().getCameraImgPath();
133 | if (StringUtils.isEmpty(cameraPath)) {
134 | Toast.makeText(this, "图片获取失败", Toast.LENGTH_SHORT).show();
135 | return;
136 | }
137 | File file = new File(cameraPath);
138 | if (file.exists()) {
139 | Uri uri = Uri.fromFile(file);
140 | LocalImageHelper.LocalFile localFile = new LocalImageHelper.LocalFile();
141 | localFile.setThumbnailUri(uri.toString());
142 | localFile.setOriginalUri(uri.toString());
143 | localFile.setOrientation(getBitmapDegree(cameraPath));
144 | LocalImageHelper.getInstance().getCheckedItems().add(localFile);
145 | LocalImageHelper.getInstance().setResultOk(true);
146 | new Thread(new Runnable() {
147 | @Override
148 | public void run() {
149 |
150 | }
151 | });
152 | //这里本来有个弹出progressDialog的,在拍照结束后关闭,但是要延迟1秒,原因是由于三星手机的相机会强制切换到横屏,
153 | //此处必须等它切回竖屏了才能结束,否则会有异常
154 | new Handler().postDelayed(new Runnable() {
155 | @Override
156 | public void run() {
157 | finish();
158 | }
159 | },1000);
160 | } else {
161 | Toast.makeText(this, "图片获取失败", Toast.LENGTH_SHORT).show();
162 | }
163 | break;
164 | default:
165 | break;
166 | }
167 | }
168 | }
169 |
170 | /**
171 | * 读取图片的旋转的角度,还是三星的问题,需要根据图片的旋转角度正确显示
172 | *
173 | * @param path 图片绝对路径
174 | * @return 图片的旋转角度
175 | */
176 | private int getBitmapDegree(String path) {
177 | int degree = 0;
178 | try {
179 | // 从指定路径下读取图片,并获取其EXIF信息
180 | ExifInterface exifInterface = new ExifInterface(path);
181 | // 获取图片的旋转信息
182 | int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
183 | ExifInterface.ORIENTATION_NORMAL);
184 | switch (orientation) {
185 | case ExifInterface.ORIENTATION_ROTATE_90:
186 | degree = 90;
187 | break;
188 | case ExifInterface.ORIENTATION_ROTATE_180:
189 | degree = 180;
190 | break;
191 | case ExifInterface.ORIENTATION_ROTATE_270:
192 | degree = 270;
193 | break;
194 | }
195 | } catch (IOException e) {
196 | e.printStackTrace();
197 | }
198 | return degree;
199 | }
200 |
201 | @Override
202 | public void onConfigurationChanged(Configuration newConfig) {
203 | super.onConfigurationChanged(newConfig);
204 | }
205 |
206 | public class FolderAdapter extends BaseAdapter {
207 | Map> folders;
208 | Context context;
209 | DisplayImageOptions options;
210 |
211 | FolderAdapter(Context context, Map> folders) {
212 | this.folders = folders;
213 | this.context = context;
214 | folderNames = new ArrayList<>();
215 |
216 | options = new DisplayImageOptions.Builder()
217 | .cacheInMemory(true)
218 | .cacheOnDisk(false)
219 | .showImageForEmptyUri(R.drawable.dangkr_no_picture_small)
220 | .showImageOnFail(R.drawable.dangkr_no_picture_small)
221 | .showImageOnLoading(R.drawable.dangkr_no_picture_small)
222 | .bitmapConfig(Bitmap.Config.RGB_565)
223 | .setImageSize(new ImageSize(((AppContext) context.getApplicationContext()).getQuarterWidth(), 0))
224 | .displayer(new SimpleBitmapDisplayer()).build();
225 |
226 | Iterator iter = folders.entrySet().iterator();
227 | while (iter.hasNext()) {
228 | Map.Entry entry = (Map.Entry) iter.next();
229 | String key = (String) entry.getKey();
230 | folderNames.add(key);
231 | }
232 | //根据文件夹内的图片数量降序显示
233 | Collections.sort(folderNames, new Comparator() {
234 | public int compare(String arg0, String arg1) {
235 | Integer num1 = helper.getFolder(arg0).size();
236 | Integer num2 = helper.getFolder(arg1).size();
237 | return num2.compareTo(num1);
238 | }
239 | });
240 | }
241 |
242 | @Override
243 | public int getCount() {
244 | return folders.size();
245 | }
246 |
247 | @Override
248 | public Object getItem(int i) {
249 | return null;
250 | }
251 |
252 | @Override
253 | public long getItemId(int i) {
254 | return 0;
255 | }
256 |
257 | @Override
258 | public View getView(int i, View convertView, ViewGroup viewGroup) {
259 | ViewHolder viewHolder;
260 | if (convertView == null || convertView.getTag() == null) {
261 | viewHolder = new ViewHolder();
262 | convertView = LayoutInflater.from(context).inflate(R.layout.item_albumfoler, null);
263 | viewHolder.imageView = (ImageView) convertView.findViewById(R.id.imageView);
264 | viewHolder.textView = (TextView) convertView.findViewById(R.id.textview);
265 | convertView.setTag(viewHolder);
266 | } else {
267 | viewHolder = (ViewHolder) convertView.getTag();
268 | }
269 | String name = folderNames.get(i);
270 | List files = folders.get(name);
271 | viewHolder.textView.setText(name + "(" + files.size() + ")");
272 | if (files.size() > 0) {
273 | ImageLoader.getInstance().displayImage(files.get(0).getThumbnailUri(), new ImageViewAware(viewHolder.imageView), options,
274 | null, null, files.get(0).getOrientation());
275 | }
276 | return convertView;
277 | }
278 |
279 | private class ViewHolder {
280 | ImageView imageView;
281 | TextView textView;
282 | }
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/widget/MatrixImageView.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Color;
6 | import android.graphics.Matrix;
7 | import android.graphics.PointF;
8 | import android.util.AttributeSet;
9 | import android.view.GestureDetector;
10 | import android.view.GestureDetector.SimpleOnGestureListener;
11 | import android.view.MotionEvent;
12 | import android.view.View;
13 | import android.view.ViewTreeObserver;
14 | import android.widget.ImageView;
15 |
16 | /**
17 | * @ClassName: MatrixImageView
18 | * @Description: 带放大、缩小、移动效果的ImageView
19 | * @author LinJ
20 | * @date 2015-1-7 上午11:15:07
21 | *
22 | */
23 | public class MatrixImageView extends ImageView{
24 | public final static String TAG="MatrixImageView";
25 | private GestureDetector mGestureDetector;
26 | /** 模板Matrix,用以初始化 */
27 | private Matrix mMatrix=new Matrix();
28 | /** 图片长度*/
29 | private float mImageWidth;
30 | /** 图片高度 */
31 | private float mImageHeight;
32 | /** 原始缩放级别 */
33 | private float mScale
34 | ;
35 | private OnMovingListener moveListener;
36 | private OnSingleTapListener singleTapListener;
37 |
38 | public MatrixImageView(Context context, AttributeSet attrs) {
39 | super(context, attrs);
40 | MatrixTouchListener mListener=new MatrixTouchListener();
41 | setOnTouchListener(mListener);
42 | mGestureDetector=new GestureDetector(getContext(), new GestureListener(mListener));
43 | //背景设置为balck
44 | setBackgroundColor(Color.BLACK);
45 | //将缩放类型设置为CENTER_INSIDE,表示把图片居中显示,并且宽高最大值为控件宽高
46 | setScaleType(ScaleType.FIT_CENTER);
47 | }
48 | public MatrixImageView(Context context) {
49 | super(context, null);
50 | MatrixTouchListener mListener=new MatrixTouchListener();
51 | setOnTouchListener(mListener);
52 | mGestureDetector=new GestureDetector(getContext(), new GestureListener(mListener));
53 | //背景设置为balck
54 | setBackgroundColor(Color.BLACK);
55 | //将缩放类型设置为CENTER_INSIDE,表示把图片居中显示,并且宽高最大值为控件宽高
56 | setScaleType(ScaleType.FIT_CENTER);
57 | }
58 | public void setOnMovingListener(OnMovingListener listener){
59 | moveListener=listener;
60 | }
61 | public void setOnSingleTapListener(OnSingleTapListener onSingleTapListener) {
62 | this.singleTapListener = onSingleTapListener;
63 | }
64 | @Override
65 | public void setImageBitmap(Bitmap bm) {
66 | // TODO Auto-generated method stub
67 | super.setImageBitmap(bm);
68 | //大小为0 表示当前控件大小未测量 设置监听函数 在绘制前赋值
69 | if(getWidth()==0){
70 | ViewTreeObserver vto = getViewTreeObserver();
71 | vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener()
72 | {
73 | public boolean onPreDraw()
74 | {
75 | initData();
76 | //赋值结束后,移除该监听函数
77 | MatrixImageView.this.getViewTreeObserver().removeOnPreDrawListener(this);
78 | return true;
79 | }
80 | });
81 | }else {
82 | initData();
83 | }
84 | }
85 |
86 | /**
87 | * 初始化模板Matrix和图片的其他数据
88 | */
89 | private void initData() {
90 | //设置完图片后,获取该图片的坐标变换矩阵
91 | mMatrix.set(getImageMatrix());
92 | float[] values=new float[9];
93 | mMatrix.getValues(values);
94 | //图片宽度为屏幕宽度除缩放倍数
95 | mImageWidth=getWidth()/values[Matrix.MSCALE_X];
96 | mImageHeight=(getHeight()-values[Matrix.MTRANS_Y]*2)/values[Matrix.MSCALE_Y];
97 | mScale=values[Matrix.MSCALE_X];
98 | }
99 |
100 | public class MatrixTouchListener implements OnTouchListener{
101 | /** 拖拉照片模式 */
102 | private static final int MODE_DRAG = 1;
103 | /** 放大缩小照片模式 */
104 | private static final int MODE_ZOOM = 2;
105 | /** 不支持Matrix */
106 | private static final int MODE_UNABLE=3;
107 | /** 最大缩放级别*/
108 | float mMaxScale=6;
109 | /** 双击时的缩放级别*/
110 | float mDobleClickScale=2;
111 | private int mMode = 0;//
112 | /** 缩放开始时的手指间距 */
113 | private float mStartDis;
114 | /** 当前Matrix*/
115 | private Matrix mCurrentMatrix = new Matrix();
116 |
117 | /** 用于记录开始时候的坐标位置 */
118 |
119 | /** 和ViewPager交互相关,判断当前是否可以左移、右移 */
120 | boolean mLeftDragable;
121 | boolean mRightDragable;
122 | /** 是否第一次移动 */
123 | boolean mFirstMove=false;
124 | private PointF mStartPoint = new PointF();
125 | @Override
126 | public boolean onTouch(View v, MotionEvent event) {
127 | // TODO Auto-generated method stub
128 | switch (event.getActionMasked()) {
129 | case MotionEvent.ACTION_DOWN:
130 | //设置拖动模式
131 | mMode=MODE_DRAG;
132 | mStartPoint.set(event.getX(), event.getY());
133 | isMatrixEnable();
134 | startDrag();
135 | checkDragable();
136 | break;
137 | case MotionEvent.ACTION_UP:
138 | case MotionEvent.ACTION_CANCEL:
139 | reSetMatrix();
140 | stopDrag();
141 | break;
142 | case MotionEvent.ACTION_MOVE:
143 | if (mMode == MODE_ZOOM) {
144 | setZoomMatrix(event);
145 | }else if (mMode==MODE_DRAG) {
146 | setDragMatrix(event);
147 | }else {
148 | stopDrag();
149 | }
150 | break;
151 | case MotionEvent.ACTION_POINTER_DOWN:
152 | if(mMode==MODE_UNABLE) return true;
153 | mMode=MODE_ZOOM;
154 | mStartDis = distance(event);
155 | break;
156 | case MotionEvent.ACTION_POINTER_UP:
157 |
158 | break;
159 | default:
160 | break;
161 | }
162 | return mGestureDetector.onTouchEvent(event);
163 | }
164 |
165 | /**
166 | * 子控件开始进入移动状态,令ViewPager无法拦截对子控件的Touch事件
167 | */
168 | private void startDrag(){
169 | if(moveListener!=null) moveListener.startDrag();
170 |
171 | }
172 | /**
173 | * 子控件开始停止移动状态,ViewPager将拦截对子控件的Touch事件
174 | */
175 | private void stopDrag(){
176 | if(moveListener!=null) moveListener.stopDrag();
177 | }
178 |
179 | /**
180 | * 根据当前图片左右边缘设置可拖拽状态
181 | */
182 | private void checkDragable() {
183 | mLeftDragable=true;
184 | mRightDragable=true;
185 | mFirstMove=true;
186 | float[] values=new float[9];
187 | getImageMatrix().getValues(values);
188 | //图片左边缘离开左边界,表示不可右移
189 | if(values[Matrix.MTRANS_X]>=0)
190 | mRightDragable=false;
191 | //图片右边缘离开右边界,表示不可左移
192 | if((mImageWidth)*values[Matrix.MSCALE_X]+values[Matrix.MTRANS_X]<=getWidth()){
193 | mLeftDragable=false;
194 | }
195 | }
196 |
197 | /**
198 | * 设置拖拽状态下的Matrix
199 | * @param event
200 | */
201 | public void setDragMatrix(MotionEvent event) {
202 | if(isZoomChanged()){
203 | float dx = event.getX() - mStartPoint.x; // 得到x轴的移动距离
204 | float dy = event.getY() - mStartPoint.y; // 得到x轴的移动距离
205 | //避免和双击冲突,大于10f才算是拖动
206 | if(Math.sqrt(dx*dx+dy*dy)>10f){
207 | mStartPoint.set(event.getX(), event.getY());
208 | //在当前基础上移动
209 | mCurrentMatrix.set(getImageMatrix());
210 | float[] values=new float[9];
211 | mCurrentMatrix.getValues(values);
212 | dy=checkDyBound(values,dy);
213 | dx=checkDxBound(values,dx,dy);
214 |
215 | mCurrentMatrix.postTranslate(dx, dy);
216 | setImageMatrix(mCurrentMatrix);
217 | }
218 | }else {
219 | stopDrag();
220 | }
221 | }
222 |
223 | /**
224 | * 判断缩放级别是否是改变过
225 | * @return true表示非初始值,false表示初始值
226 | */
227 | private boolean isZoomChanged() {
228 | float[] values=new float[9];
229 | getImageMatrix().getValues(values);
230 | //获取当前X轴缩放级别
231 | float scale=values[Matrix.MSCALE_X];
232 | //获取模板的X轴缩放级别,两者做比较
233 | return scale!=mScale;
234 | }
235 |
236 | /**
237 | * 和当前矩阵对比,检验dy,使图像移动后不会超出ImageView边界
238 | * @param values
239 | * @param dy
240 | * @return
241 | */
242 | private float checkDyBound(float[] values, float dy) {
243 | float height=getHeight();
244 | if(mImageHeight*values[Matrix.MSCALE_Y]0)
247 | dy=-values[Matrix.MTRANS_Y];
248 | else if(values[Matrix.MTRANS_Y]+dy<-(mImageHeight*values[Matrix.MSCALE_Y]-height))
249 | dy=-(mImageHeight*values[Matrix.MSCALE_Y]-height)-values[Matrix.MTRANS_Y];
250 | return dy;
251 | }
252 |
253 | /**
254 | * 和当前矩阵对比,检验dx,使图像移动后不会超出ImageView边界
255 | * @param values
256 | * @param dx
257 | * @return
258 | */
259 | private float checkDxBound(float[] values,float dx,float dy) {
260 | float width=getWidth();
261 | if(!mLeftDragable&&dx<0){
262 | //加入和y轴的对比,表示在监听到垂直方向的手势时不切换Item
263 | if(Math.abs(dx)*0.4f>Math.abs(dy)&&mFirstMove){
264 | stopDrag();
265 | }
266 | return 0;
267 | }
268 | if(!mRightDragable&&dx>0){
269 | //加入和y轴的对比,表示在监听到垂直方向的手势时不切换Item
270 | if(Math.abs(dx)*0.4f>Math.abs(dy)&&mFirstMove){
271 | stopDrag();
272 | }
273 | return 0;
274 | }
275 | mLeftDragable=true;
276 | mRightDragable=true;
277 | if(mFirstMove) mFirstMove=false;
278 | if(mImageWidth*values[Matrix.MSCALE_X]0){
283 | dx=-values[Matrix.MTRANS_X];
284 | }
285 | else if(values[Matrix.MTRANS_X]+dx<-(mImageWidth*values[Matrix.MSCALE_X]-width)){
286 | dx=-(mImageWidth*values[Matrix.MSCALE_X]-width)-values[Matrix.MTRANS_X];
287 | }
288 | return dx;
289 | }
290 |
291 | /**
292 | * 设置缩放Matrix
293 | * @param event
294 | */
295 | private void setZoomMatrix(MotionEvent event) {
296 | //只有同时触屏两个点的时候才执行
297 | if(event.getPointerCount()<2) return;
298 | float endDis = distance(event);// 结束距离
299 | if (endDis > 10f) { // 两个手指并拢在一起的时候像素大于10
300 | float scale = endDis / mStartDis;// 得到缩放倍数
301 | mStartDis=endDis;//重置距离
302 | mCurrentMatrix.set(getImageMatrix());//初始化Matrix
303 | float[] values=new float[9];
304 | mCurrentMatrix.getValues(values);
305 | scale = checkMaxScale(scale, values);
306 | PointF centerF=getCenter(scale,values);
307 | mCurrentMatrix.postScale(scale, scale,centerF.x,centerF.y);
308 | setImageMatrix(mCurrentMatrix);
309 | }
310 | }
311 |
312 | /**
313 | * 获取缩放的中心点。
314 | * @param scale
315 | * @param values
316 | * @return
317 | */
318 | private PointF getCenter(float scale,float[] values) {
319 | //缩放级别小于原始缩放级别时或者为放大状态时,返回ImageView中心点作为缩放中心点
320 | if(scale*values[Matrix.MSCALE_X]=1){
321 | return new PointF(getWidth()/2,getHeight()/2);
322 | }
323 | float cx=getWidth()/2;
324 | float cy=getHeight()/2;
325 | //以ImageView中心点为缩放中心,判断缩放后的图片左边缘是否会离开ImageView左边缘,是的话以左边缘为X轴中心
326 | if((getWidth()/2-values[Matrix.MTRANS_X])*scalemMaxScale)
342 | scale=mMaxScale/values[Matrix.MSCALE_X];
343 | return scale;
344 | }
345 |
346 | /**
347 | * 重置Matrix
348 | */
349 | private void reSetMatrix() {
350 | if(checkRest()){
351 | mCurrentMatrix.set(mMatrix);
352 | setImageMatrix(mCurrentMatrix);
353 | }else {
354 | //判断Y轴是否需要更正
355 | float[] values=new float[9];
356 | getImageMatrix().getValues(values);
357 | float height=mImageHeight*values[Matrix.MSCALE_Y];
358 | if(height pictures = new ArrayList<>();//图片路径数组
58 | HorizontalScrollView scrollView;//滚动的图片容器
59 | View editContainer;//动态编辑部分
60 | View pagerContainer;//图片显示部分
61 |
62 | //显示大图的viewpager 集成到了Actvity中 下面是和viewpager相关的控件
63 | AlbumViewPager viewpager;//大图显示pager
64 | ImageView mBackView;//返回/关闭大图
65 | TextView mCountView;//大图数量提示
66 | View mHeaderBar;//大图顶部栏
67 | ImageView delete;//删除按钮
68 |
69 | int size;//小图大小
70 | int padding;//小图间距
71 | DisplayImageOptions options;
72 |
73 | @Override
74 | protected void onCreate(Bundle savedInstanceState) {
75 | // TODO Auto-generated method stub
76 | super.onCreate(savedInstanceState);
77 | setContentView(R.layout.post_dynamic);
78 | imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
79 | //设置ImageLoader参数
80 | options = new DisplayImageOptions.Builder()
81 | .cacheInMemory(true)
82 | .cacheOnDisk(false)
83 | .showImageForEmptyUri(R.drawable.dangkr_no_picture_small)
84 | .showImageOnFail(R.drawable.dangkr_no_picture_small)
85 | .showImageOnLoading(R.drawable.dangkr_no_picture_small)
86 | .bitmapConfig(Bitmap.Config.RGB_565)
87 | .displayer(new SimpleBitmapDisplayer()).build();
88 | initViews();
89 | initData();
90 | }
91 |
92 |
93 | /**
94 | * @Description: 初始化Views
95 | */
96 | private void initViews() {
97 | // TODO Auto-generated method stub
98 | mBack = (ImageView) findViewById(R.id.post_back);
99 | mSend = findViewById(R.id.post_send);
100 | mContent = (EditText) findViewById(R.id.post_content);
101 | textRemain = (TextView) findViewById(R.id.post_text_remain);
102 | picRemain = (TextView) findViewById(R.id.post_pic_remain);
103 | add = (ImageView) findViewById(R.id.post_add_pic);
104 | picContainer = (LinearLayout) findViewById(R.id.post_pic_container);
105 | scrollView = (HorizontalScrollView) findViewById(R.id.post_scrollview);
106 | viewpager = (AlbumViewPager) findViewById(R.id.albumviewpager);
107 | mBackView = (ImageView) findViewById(R.id.header_bar_photo_back);
108 | mCountView = (TextView) findViewById(R.id.header_bar_photo_count);
109 | mHeaderBar = findViewById(R.id.album_item_header_bar);
110 | delete = (ImageView) findViewById(R.id.header_bar_photo_delete);
111 | editContainer = findViewById(R.id.post_edit_container);
112 | pagerContainer = findViewById(R.id.pagerview);
113 | delete.setVisibility(View.VISIBLE);
114 |
115 | viewpager.setOnPageChangeListener(pageChangeListener);
116 | viewpager.setOnSingleTapListener(this);
117 | mBackView.setOnClickListener(this);
118 | mCountView.setOnClickListener(this);
119 | mBack.setOnClickListener(this);
120 | mSend.setOnClickListener(this);
121 | add.setOnClickListener(this);
122 | delete.setOnClickListener(this);
123 |
124 | mContent.addTextChangedListener(new TextWatcher() {
125 |
126 | @Override
127 | public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
128 | // TODO Auto-generated method stub
129 |
130 | }
131 |
132 | @Override
133 | public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
134 | int arg3) {
135 | // TODO Auto-generated method stub
136 |
137 | }
138 |
139 | @Override
140 | public void afterTextChanged(Editable content) {
141 | textRemain.setText(content.toString().length() + "/140");
142 | }
143 | });
144 | }
145 |
146 | private void initData() {
147 | size = (int) getResources().getDimension(R.dimen.size_100);
148 | padding = (int) getResources().getDimension(R.dimen.padding_10);
149 | }
150 |
151 | @Override
152 | public void onBackPressed() {
153 | if (pagerContainer.getVisibility() != View.VISIBLE) {
154 | //showSaveDialog();
155 | }
156 | else {
157 | hideViewPager();
158 | }
159 | }
160 |
161 |
162 |
163 | @Override
164 | public void onClick(View view) {
165 | // TODO Auto-generated method stub
166 | switch (view.getId()) {
167 | case R.id.post_back:
168 | // showSaveDialog();
169 | break;
170 | case R.id.header_bar_photo_back:
171 | case R.id.header_bar_photo_count:
172 | hideViewPager();
173 | break;
174 | case R.id.header_bar_photo_delete:
175 | final int index = viewpager.getCurrentItem();
176 | // new AlertDialog(this).builder()
177 | // .setTitle("提示")
178 | // .setMsg("要删除这张照片吗?")
179 | // .setNegativeButton("取消", new OnClickListener() {
180 | //
181 | // @Override
182 | // public void onClick(View arg0) {
183 | // // TODO Auto-generated method stub
184 | //
185 | // }
186 | // })
187 | // .setPositiveButton("确定", new OnClickListener() {
188 | //
189 | // @Override
190 | // public void onClick(View arg0) {
191 | // // TODO Auto-generated method stub
192 | // pictures.remove(index);
193 | // if (pictures.size() == 9) {
194 | // add.setVisibility(View.GONE);
195 | // } else {
196 | // add.setVisibility(View.VISIBLE);
197 | // }
198 | // if (pictures.size() == 0) {
199 | // hideViewPager();
200 | // }
201 | // picContainer.removeView(picContainer.getChildAt(index));
202 | // picRemain.setText(pictures.size() + "/9");
203 | // mCountView.setText((viewpager.getCurrentItem() + 1) + "/" + pictures.size());
204 | // viewpager.getAdapter().notifyDataSetChanged();
205 | // LocalImageHelper.getInstance().setCurrentSize(pictures.size());
206 | // }
207 | // }).show();
208 |
209 | break;
210 | case R.id.post_send:
211 | imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
212 | String content = mContent.getText().toString();
213 | if (StringUtils.isEmpty(content) && pictures.isEmpty()) {
214 | Toast.makeText(this, "请添写动态内容或至少添加一张图片", Toast.LENGTH_SHORT).show();
215 | return;
216 | } else {
217 | //设置为不可点击,防止重复提交
218 | view.setEnabled(false);
219 | }
220 | break;
221 | case R.id.post_add_pic:
222 | Intent intent = new Intent(DynamicPost.this, LocalAlbum.class);
223 | startActivityForResult(intent, ImageUtils.REQUEST_CODE_GETIMAGE_BYCROP);
224 | break;
225 | default:
226 | if (view instanceof FilterImageView) {
227 | for (int i = 0; i < picContainer.getChildCount(); i++) {
228 | if (view == picContainer.getChildAt(i)) {
229 | showViewPager(i);
230 | }
231 | }
232 | }
233 | break;
234 | }
235 | }
236 |
237 |
238 |
239 |
240 |
241 | private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
242 |
243 | @Override
244 | public void onPageSelected(int position) {
245 | if (viewpager.getAdapter() != null) {
246 | String text = (position + 1) + "/" + viewpager.getAdapter().getCount();
247 | mCountView.setText(text);
248 | } else {
249 | mCountView.setText("0/0");
250 | }
251 | }
252 |
253 | @Override
254 | public void onPageScrolled(int arg0, float arg1, int arg2) {
255 | // TODO Auto-generated method stub
256 |
257 | }
258 |
259 | @Override
260 | public void onPageScrollStateChanged(int arg0) {
261 | // TODO Auto-generated method stub
262 |
263 | }
264 | };
265 |
266 | //显示大图pager
267 | private void showViewPager(int index) {
268 | pagerContainer.setVisibility(View.VISIBLE);
269 | editContainer.setVisibility(View.GONE);
270 | viewpager.setAdapter(viewpager.new LocalViewPagerAdapter(pictures));
271 | viewpager.setCurrentItem(index);
272 | mCountView.setText((index + 1) + "/" + pictures.size());
273 | AnimationSet set = new AnimationSet(true);
274 | ScaleAnimation scaleAnimation = new ScaleAnimation((float) 0.9, 1, (float) 0.9, 1, pagerContainer.getWidth() / 2, pagerContainer.getHeight() / 2);
275 | scaleAnimation.setDuration(200);
276 | set.addAnimation(scaleAnimation);
277 | AlphaAnimation alphaAnimation = new AlphaAnimation((float) 0.1, 1);
278 | alphaAnimation.setDuration(200);
279 | set.addAnimation(alphaAnimation);
280 | pagerContainer.startAnimation(set);
281 | }
282 |
283 | //关闭大图显示
284 | private void hideViewPager() {
285 | pagerContainer.setVisibility(View.GONE);
286 | editContainer.setVisibility(View.VISIBLE);
287 | AnimationSet set = new AnimationSet(true);
288 | ScaleAnimation scaleAnimation = new ScaleAnimation(1, (float) 0.9, 1, (float) 0.9, pagerContainer.getWidth() / 2, pagerContainer.getHeight() / 2);
289 | scaleAnimation.setDuration(200);
290 | set.addAnimation(scaleAnimation);
291 | AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
292 | alphaAnimation.setDuration(200);
293 | set.addAnimation(alphaAnimation);
294 | pagerContainer.startAnimation(set);
295 | }
296 |
297 | @Override
298 | public void onSingleTap() {
299 | hideViewPager();
300 | }
301 |
302 |
303 | @Override
304 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
305 | switch (requestCode) {
306 | case ImageUtils.REQUEST_CODE_GETIMAGE_BYCROP:
307 | if (LocalImageHelper.getInstance().isResultOk()) {
308 | LocalImageHelper.getInstance().setResultOk(false);
309 | //获取选中的图片
310 | List files = LocalImageHelper.getInstance().getCheckedItems();
311 | for (int i = 0; i < files.size(); i++) {
312 | LayoutParams params = new LayoutParams(size, size);
313 | params.rightMargin = padding;
314 | FilterImageView imageView = new FilterImageView(this);
315 | imageView.setLayoutParams(params);
316 | imageView.setScaleType(ScaleType.CENTER_CROP);
317 | ImageLoader.getInstance().displayImage(files.get(i).getThumbnailUri(), new ImageViewAware(imageView), options,
318 | null, null, files.get(i).getOrientation());
319 | imageView.setOnClickListener(this);
320 | pictures.add(files.get(i));
321 | if (pictures.size() == 9) {
322 | add.setVisibility(View.GONE);
323 | } else {
324 | add.setVisibility(View.VISIBLE);
325 | }
326 | picContainer.addView(imageView, picContainer.getChildCount() - 1);
327 | picRemain.setText(pictures.size() + "/9");
328 | LocalImageHelper.getInstance().setCurrentSize(pictures.size());
329 | }
330 | //清空选中的图片
331 | files.clear();
332 | //设置当前选中的图片数量
333 | LocalImageHelper.getInstance().setCurrentSize(pictures.size());
334 | //延迟滑动至最右边
335 | new Handler().postDelayed(new Runnable() {
336 | public void run() {
337 | scrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
338 | }
339 | }, 50L);
340 | }
341 | //清空选中的图片
342 | LocalImageHelper.getInstance().getCheckedItems().clear();
343 | break;
344 | default:
345 | break;
346 | }
347 | }
348 | }
349 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/ui/LocalAlbumDetail.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.ui;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Color;
6 | import android.graphics.PorterDuff;
7 | import android.os.Bundle;
8 | import android.support.v4.view.ViewPager;
9 | import android.text.TextUtils;
10 | import android.view.LayoutInflater;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.view.animation.AlphaAnimation;
14 | import android.view.animation.AnimationSet;
15 | import android.view.animation.ScaleAnimation;
16 | import android.widget.BaseAdapter;
17 | import android.widget.CheckBox;
18 | import android.widget.CompoundButton;
19 | import android.widget.GridView;
20 | import android.widget.ImageView;
21 | import android.widget.TextView;
22 | import android.widget.Toast;
23 |
24 |
25 | import com.example.localalbum.AppContext;
26 | import com.example.localalbum.AppManager;
27 | import com.example.localalbum.R;
28 | import com.example.localalbum.common.ExtraKey;
29 | import com.example.localalbum.common.LocalImageHelper;
30 | import com.example.localalbum.widget.AlbumViewPager;
31 | import com.example.localalbum.widget.MatrixImageView;
32 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
33 | import com.nostra13.universalimageloader.core.ImageLoader;
34 | import com.nostra13.universalimageloader.core.assist.ImageSize;
35 | import com.nostra13.universalimageloader.core.display.SimpleBitmapDisplayer;
36 | import com.nostra13.universalimageloader.core.imageaware.ImageViewAware;
37 | import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
38 |
39 | import java.util.List;
40 |
41 |
42 | /**
43 | * @author linjizong
44 | * @Description:欢迎页测试
45 | * @date 2015-4-11
46 | */
47 | public class LocalAlbumDetail extends BaseActivity implements MatrixImageView.OnSingleTapListener, View.OnClickListener
48 | ,CompoundButton.OnCheckedChangeListener{
49 |
50 | GridView gridView;
51 | TextView title;//标题
52 | View titleBar;//标题栏
53 | View pagerContainer;//图片显示部分
54 | TextView finish,headerFinish;
55 | AlbumViewPager viewpager;//大图显示pager
56 | String folder;
57 | TextView mCountView;
58 | List currentFolder = null;
59 |
60 | ImageView mBackView;
61 | View headerBar;
62 | CheckBox checkBox;
63 | LocalImageHelper helper = LocalImageHelper.getInstance();
64 | List checkedItems ;
65 | @Override
66 | protected void onCreate(Bundle savedInstanceState) {
67 | super.onCreate(savedInstanceState);
68 | setContentView(R.layout.local_album_detail);
69 | if(!LocalImageHelper.getInstance().isInited()){
70 | finish();
71 | return;
72 | }
73 | title = (TextView) findViewById(R.id.album_title);
74 | finish = (TextView) findViewById(R.id.album_finish);
75 | headerFinish=(TextView)findViewById(R.id.header_finish);
76 | gridView = (GridView) findViewById(R.id.gridview);
77 | titleBar = findViewById(R.id.album_title_bar);
78 | viewpager = (AlbumViewPager) findViewById(R.id.albumviewpager);
79 | pagerContainer = findViewById(R.id.pagerview);
80 | mCountView = (TextView) findViewById(R.id.header_bar_photo_count);
81 | viewpager.setOnPageChangeListener(pageChangeListener);
82 | viewpager.setOnSingleTapListener(this);
83 | mBackView = (ImageView) findViewById(R.id.header_bar_photo_back);
84 | headerBar =findViewById(R.id.album_item_header_bar);
85 | checkBox= (CheckBox) findViewById(R.id.checkbox);
86 | checkBox.setOnCheckedChangeListener(this);
87 | mBackView.setOnClickListener(this);
88 | finish.setOnClickListener(this);
89 | headerFinish.setOnClickListener(this);
90 | findViewById(R.id.album_back).setOnClickListener(this);
91 |
92 | folder = getIntent().getExtras().getString(ExtraKey.LOCAL_FOLDER_NAME);
93 | new Thread(new Runnable() {
94 | @Override
95 | public void run() {
96 | //防止停留在本界面时切换到桌面,导致应用被回收,图片数组被清空,在此处做一个初始化处理
97 | helper.initImage();
98 | //获取该文件夹下地所有文件
99 | final List folders = helper.getFolder(folder);
100 | runOnUiThread(new Runnable() {
101 | @Override
102 | public void run() {
103 | if (folders != null) {
104 | currentFolder = folders;
105 | MyAdapter adapter = new MyAdapter(LocalAlbumDetail.this, folders);
106 | title.setText(folder);
107 | gridView.setAdapter(adapter);
108 | //设置当前选中数量
109 | if (checkedItems.size()+LocalImageHelper.getInstance().getCurrentSize() > 0) {
110 | finish.setText("完成(" + (checkedItems.size()+LocalImageHelper.getInstance().getCurrentSize()) + "/9)");
111 | finish.setEnabled(true);
112 | headerFinish.setText("完成(" + (checkedItems.size()+LocalImageHelper.getInstance().getCurrentSize()) + "/9)");
113 | headerFinish.setEnabled(true);
114 | } else {
115 | finish.setText("完成");
116 | // finish.setEnabled(false);
117 | headerFinish.setText("完成");
118 | // headerFinish.setEnabled(false);
119 | }
120 | }
121 | }
122 | });
123 | }
124 | }).start();
125 | checkedItems=helper.getCheckedItems();
126 | LocalImageHelper.getInstance().setResultOk(false);
127 | }
128 |
129 |
130 | private void showViewPager(int index) {
131 | pagerContainer.setVisibility(View.VISIBLE);
132 | gridView.setVisibility(View.GONE);
133 | findViewById(R.id.album_title_bar).setVisibility(View.GONE);
134 | viewpager.setAdapter(viewpager.new LocalViewPagerAdapter(currentFolder));
135 | viewpager.setCurrentItem(index);
136 | mCountView.setText((index + 1) + "/" + currentFolder.size());
137 | //第一次载入第一张图时,需要手动修改
138 | if(index==0){
139 | checkBox.setTag(currentFolder.get(index));
140 | checkBox.setChecked(checkedItems.contains(currentFolder.get(index)));
141 | }
142 | AnimationSet set = new AnimationSet(true);
143 | ScaleAnimation scaleAnimation = new ScaleAnimation((float) 0.9, 1, (float) 0.9, 1, pagerContainer.getWidth() / 2, pagerContainer.getHeight() / 2);
144 | scaleAnimation.setDuration(300);
145 | set.addAnimation(scaleAnimation);
146 | AlphaAnimation alphaAnimation = new AlphaAnimation((float) 0.1, 1);
147 | alphaAnimation.setDuration(200);
148 | set.addAnimation(alphaAnimation);
149 | pagerContainer.startAnimation(set);
150 | }
151 |
152 | private void hideViewPager() {
153 | pagerContainer.setVisibility(View.GONE);
154 | gridView.setVisibility(View.VISIBLE);
155 | findViewById(R.id.album_title_bar).setVisibility(View.VISIBLE);
156 | AnimationSet set = new AnimationSet(true);
157 | ScaleAnimation scaleAnimation = new ScaleAnimation(1, (float) 0.9, 1, (float) 0.9, pagerContainer.getWidth() / 2, pagerContainer.getHeight() / 2);
158 | scaleAnimation.setDuration(200);
159 | set.addAnimation(scaleAnimation);
160 | AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0);
161 | alphaAnimation.setDuration(200);
162 | set.addAnimation(alphaAnimation);
163 | pagerContainer.startAnimation(set);
164 | ((BaseAdapter)gridView.getAdapter()).notifyDataSetChanged();
165 | }
166 |
167 | private ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() {
168 |
169 | @Override
170 | public void onPageSelected(int position) {
171 | if (viewpager.getAdapter() != null) {
172 | String text = (position + 1) + "/" + viewpager.getAdapter().getCount();
173 | mCountView.setText(text);
174 | checkBox.setTag(currentFolder.get(position));
175 | checkBox.setChecked(checkedItems.contains(currentFolder.get(position)));
176 | } else {
177 | mCountView.setText("0/0");
178 | }
179 | }
180 |
181 | @Override
182 | public void onPageScrolled(int arg0, float arg1, int arg2) {
183 | // TODO Auto-generated method stub
184 |
185 | }
186 |
187 | @Override
188 | public void onPageScrollStateChanged(int arg0) {
189 | // TODO Auto-generated method stub
190 |
191 | }
192 | };
193 |
194 | @Override
195 | public void onSingleTap() {
196 | if (headerBar.getVisibility() == View.VISIBLE) {
197 | AlphaAnimation animation=new AlphaAnimation(1, 0);
198 | animation.setDuration(300);
199 | headerBar.startAnimation(animation);
200 | headerBar.setVisibility(View.GONE);
201 | }
202 | else {
203 | headerBar.setVisibility(View.VISIBLE);
204 | AlphaAnimation animation=new AlphaAnimation(0, 1);
205 | animation.setDuration(300);
206 | headerBar.startAnimation(animation);
207 | }
208 | }
209 |
210 | @Override
211 | public void onClick(View view) {
212 | switch (view.getId()) {
213 | case R.id.header_bar_photo_back:
214 | hideViewPager();
215 | break;
216 | case R.id.album_finish:
217 | case R.id.header_finish:
218 | AppManager.getAppManager().finishActivity(LocalAlbum.class);
219 | LocalImageHelper.getInstance().setResultOk(true);
220 | finish();
221 | break;
222 | case R.id.album_back:
223 | finish();
224 | break;
225 | }
226 | }
227 | @Override
228 | public void onBackPressed() {
229 | if(pagerContainer.getVisibility()==View.VISIBLE){
230 | hideViewPager();
231 | }
232 | else {
233 | super.onBackPressed();
234 | }
235 | }
236 |
237 | @Override
238 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
239 | if (!b) {
240 | if (checkedItems.contains(compoundButton.getTag())) {
241 | checkedItems.remove(compoundButton.getTag());
242 | }
243 | } else {
244 | if (!checkedItems.contains(compoundButton.getTag())) {
245 | if(checkedItems.size()+LocalImageHelper.getInstance().getCurrentSize()>=9){
246 | Toast.makeText(this,"最多选择9张图片",Toast.LENGTH_SHORT).show();
247 | compoundButton.setChecked(false);
248 | return;
249 | }
250 | checkedItems.add((LocalImageHelper.LocalFile) compoundButton.getTag());
251 | }
252 | }
253 | if (checkedItems.size()+ LocalImageHelper.getInstance().getCurrentSize()> 0) {
254 | finish.setText("完成(" + (checkedItems.size()+LocalImageHelper.getInstance().getCurrentSize()) + "/9)");
255 | finish.setEnabled(true);
256 | headerFinish.setText("完成(" +(checkedItems.size()+LocalImageHelper.getInstance().getCurrentSize()) + "/9)");
257 | headerFinish.setEnabled(true);
258 | } else {
259 | finish.setText("完成");
260 | finish.setEnabled(false);
261 | headerFinish.setText("完成");
262 | headerFinish.setEnabled(false);
263 | }
264 | }
265 |
266 | public class MyAdapter extends BaseAdapter{
267 | private Context m_context;
268 | private LayoutInflater miInflater;
269 | DisplayImageOptions options;
270 | List paths;
271 |
272 | public MyAdapter(Context context, List paths) {
273 | m_context = context;
274 | this.paths = paths;
275 | options=new DisplayImageOptions.Builder()
276 | .cacheInMemory(true)
277 | .cacheOnDisk(false)
278 | .showImageForEmptyUri(R.drawable.dangkr_no_picture_small)
279 | .showImageOnFail(R.drawable.dangkr_no_picture_small)
280 | .showImageOnLoading(R.drawable.dangkr_no_picture_small)
281 | .bitmapConfig(Bitmap.Config.RGB_565)
282 | .setImageSize(new ImageSize(((AppContext) context.getApplicationContext()).getQuarterWidth(), 0))
283 | .displayer(new SimpleBitmapDisplayer()).build();
284 | }
285 |
286 | @Override
287 | public int getCount() {
288 | return paths.size();
289 | }
290 |
291 | @Override
292 | public LocalImageHelper.LocalFile getItem(int i) {
293 | return paths.get(i);
294 | }
295 |
296 | @Override
297 | public long getItemId(int i) {
298 | return 0;
299 | }
300 |
301 | @Override
302 | public View getView(final int i, View convertView, ViewGroup viewGroup) {
303 | ViewHolder viewHolder = new ViewHolder();
304 |
305 | if (convertView == null || convertView.getTag() == null) {
306 | viewHolder = new ViewHolder();
307 | LayoutInflater inflater = getLayoutInflater();
308 | convertView = inflater.inflate(R.layout.simple_list_item, null);
309 | viewHolder.imageView = (ImageView) convertView.findViewById(R.id.imageView);
310 | viewHolder.checkBox = (CheckBox) convertView.findViewById(R.id.checkbox);
311 | viewHolder.checkBox.setOnCheckedChangeListener(LocalAlbumDetail.this);
312 | convertView.setTag(viewHolder);
313 | } else {
314 | viewHolder = (ViewHolder) convertView.getTag();
315 | }
316 | ImageView imageView = viewHolder.imageView;
317 | LocalImageHelper.LocalFile localFile = paths.get(i);
318 | // FrescoLoader.getInstance().localDisplay(localFile.getThumbnailUri(), imageView, options);
319 | ImageLoader.getInstance().displayImage(localFile.getThumbnailUri(), new ImageViewAware(viewHolder.imageView), options,
320 | loadingListener, null, localFile.getOrientation());
321 | viewHolder.checkBox.setTag(localFile);
322 | viewHolder.checkBox.setChecked(checkedItems.contains(localFile));
323 | viewHolder.imageView.setOnClickListener(new View.OnClickListener() {
324 | @Override
325 | public void onClick(View view) {
326 | showViewPager(i);
327 | }
328 | });
329 | return convertView;
330 | }
331 |
332 | private class ViewHolder {
333 | ImageView imageView;
334 | CheckBox checkBox;
335 | }
336 | }
337 |
338 | SimpleImageLoadingListener loadingListener=new SimpleImageLoadingListener() {
339 | @Override
340 | public void onLoadingComplete(String imageUri, View view, final Bitmap bm) {
341 | if (TextUtils.isEmpty(imageUri)) {
342 | return;
343 | }
344 | //由于很多图片是白色背景,在此处加一个#eeeeee的滤镜,防止checkbox看不清
345 | try {
346 | ((ImageView) view).getDrawable().setColorFilter(Color.argb(0xff, 0xee, 0xee, 0xee), PorterDuff.Mode.MULTIPLY);
347 | } catch (Exception e) {
348 | e.printStackTrace();
349 | }
350 | }
351 | };
352 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/localalbum/common/ImageUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.localalbum.common;
2 |
3 | import android.app.Activity;
4 | import android.content.ContentResolver;
5 | import android.content.Context;
6 | import android.content.Intent;
7 | import android.database.Cursor;
8 | import android.graphics.Bitmap;
9 | import android.graphics.Bitmap.CompressFormat;
10 | import android.graphics.Bitmap.Config;
11 | import android.graphics.BitmapFactory;
12 | import android.graphics.Canvas;
13 | import android.graphics.LinearGradient;
14 | import android.graphics.Matrix;
15 | import android.graphics.Paint;
16 | import android.graphics.PixelFormat;
17 | import android.graphics.PorterDuff.Mode;
18 | import android.graphics.PorterDuffXfermode;
19 | import android.graphics.Rect;
20 | import android.graphics.RectF;
21 | import android.graphics.Shader.TileMode;
22 | import android.graphics.drawable.BitmapDrawable;
23 | import android.graphics.drawable.Drawable;
24 | import android.net.Uri;
25 | import android.os.Environment;
26 | import android.provider.MediaStore;
27 | import android.provider.MediaStore.MediaColumns;
28 | import android.util.DisplayMetrics;
29 |
30 |
31 | import com.example.localalbum.AppContext;
32 |
33 | import java.io.BufferedOutputStream;
34 | import java.io.ByteArrayOutputStream;
35 | import java.io.File;
36 | import java.io.FileInputStream;
37 | import java.io.FileNotFoundException;
38 | import java.io.FileOutputStream;
39 | import java.io.IOException;
40 | import java.io.InputStream;
41 | import java.io.OutputStream;
42 | import java.sql.Timestamp;
43 | import java.text.SimpleDateFormat;
44 |
45 | /**
46 | * 图片操作工具包
47 | *
48 | * @author liux (http://my.oschina.net/liux)
49 | * @version 1.0
50 | * @created 2012-3-21
51 | */
52 | public class ImageUtils {
53 |
54 | public final static String SDCARD_MNT = "/mnt/sdcard";
55 | public final static String SDCARD = "/sdcard";
56 |
57 | /** 请求相册 */
58 | public static final int REQUEST_CODE_GETIMAGE_BYSDCARD = 0;
59 | /** 请求相机 */
60 | public static final int REQUEST_CODE_GETIMAGE_BYCAMERA = 1;
61 | /** 请求裁剪 */
62 | public static final int REQUEST_CODE_GETIMAGE_BYCROP = 2;
63 |
64 | /**
65 | * 写图片文件 在Android系统中,文件保存在 /data/data/PACKAGE_NAME/files 目录下
66 | *
67 | * @throws IOException
68 | */
69 | public static void saveImage(Context context, String fileName, Bitmap bitmap)
70 | throws IOException {
71 | saveImage(context, fileName, bitmap, 100);
72 | }
73 |
74 | public static void saveImage(Context context, String fileName,
75 | Bitmap bitmap, int quality) throws IOException {
76 | if (bitmap == null || fileName == null || context == null)
77 | return;
78 |
79 | FileOutputStream fos = context.openFileOutput(fileName,
80 | Context.MODE_PRIVATE);
81 | ByteArrayOutputStream stream = new ByteArrayOutputStream();
82 | bitmap.compress(CompressFormat.JPEG, quality, stream);
83 | byte[] bytes = stream.toByteArray();
84 | fos.write(bytes);
85 | fos.close();
86 | }
87 |
88 | /**
89 | * 写图片文件到SD卡
90 | *
91 | * @throws IOException
92 | */
93 | public static void saveImageToSD(Context ctx, String filePath,
94 | Bitmap bitmap, int quality) throws IOException {
95 | if (bitmap != null) {
96 | File file = new File(filePath.substring(0,
97 | filePath.lastIndexOf(File.separator)));
98 | if (!file.exists()) {
99 | file.mkdirs();
100 | }
101 | BufferedOutputStream bos = new BufferedOutputStream(
102 | new FileOutputStream(filePath));
103 | bitmap.compress(CompressFormat.JPEG, quality, bos);
104 | bos.flush();
105 | bos.close();
106 | if (ctx != null) {
107 | scanPhoto(ctx, filePath);
108 | }
109 | }
110 | }
111 |
112 | public static void saveBackgroundImage(Context ctx, String filePath,
113 | Bitmap bitmap, int quality) throws IOException {
114 | if (bitmap != null) {
115 | File file = new File(filePath.substring(0,
116 | filePath.lastIndexOf(File.separator)));
117 | if (!file.exists()) {
118 | file.mkdirs();
119 | }
120 | BufferedOutputStream bos = new BufferedOutputStream(
121 | new FileOutputStream(filePath));
122 | bitmap.compress(CompressFormat.PNG, quality, bos);
123 | bos.flush();
124 | bos.close();
125 | if (ctx != null) {
126 | scanPhoto(ctx, filePath);
127 | }
128 | }
129 | }
130 |
131 | /**
132 | * 让Gallery上能马上看到该图片
133 | */
134 | private static void scanPhoto(Context ctx, String imgFileName) {
135 | Intent mediaScanIntent = new Intent(
136 | Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
137 | File file = new File(imgFileName);
138 | Uri contentUri = Uri.fromFile(file);
139 | mediaScanIntent.setData(contentUri);
140 | ctx.sendBroadcast(mediaScanIntent);
141 | }
142 |
143 | /**
144 | * 获取bitmap
145 | *
146 | * @param context
147 | * @param fileName
148 | * @return
149 | */
150 | public static Bitmap getBitmap(Context context, String fileName) {
151 | FileInputStream fis = null;
152 | Bitmap bitmap = null;
153 | try {
154 | fis = context.openFileInput(fileName);
155 | bitmap = BitmapFactory.decodeStream(fis);
156 | } catch (FileNotFoundException e) {
157 | e.printStackTrace();
158 | } catch (OutOfMemoryError e) {
159 | e.printStackTrace();
160 | } finally {
161 | try {
162 | fis.close();
163 | } catch (Exception e) {
164 | }
165 | }
166 | return bitmap;
167 | }
168 |
169 | /**
170 | * 获取bitmap
171 | *
172 | * @param filePath
173 | * @return
174 | */
175 | public static Bitmap getBitmapByPath(String filePath) {
176 | return getBitmapByPath(filePath, null);
177 | }
178 |
179 | public static Bitmap getBitmapByPath(String filePath,
180 | BitmapFactory.Options opts) {
181 | FileInputStream fis = null;
182 | Bitmap bitmap = null;
183 | try {
184 | File file = new File(filePath);
185 | fis = new FileInputStream(file);
186 | bitmap = BitmapFactory.decodeStream(fis, null, opts);
187 | } catch (FileNotFoundException e) {
188 | e.printStackTrace();
189 | } catch (OutOfMemoryError e) {
190 | e.printStackTrace();
191 | } finally {
192 | try {
193 | fis.close();
194 | } catch (Exception e) {
195 | }
196 | }
197 | return bitmap;
198 | }
199 |
200 | /**
201 | * 获取bitmap
202 | *
203 | * @param file
204 | * @return
205 | */
206 | public static Bitmap getBitmapByFile(File file) {
207 | FileInputStream fis = null;
208 | Bitmap bitmap = null;
209 | try {
210 | fis = new FileInputStream(file);
211 | bitmap = BitmapFactory.decodeStream(fis);
212 | } catch (FileNotFoundException e) {
213 | e.printStackTrace();
214 | } catch (OutOfMemoryError e) {
215 | e.printStackTrace();
216 | } finally {
217 | try {
218 | fis.close();
219 | } catch (Exception e) {
220 | }
221 | }
222 | return bitmap;
223 | }
224 |
225 | /**
226 | * 使用当前时间戳拼接一个唯一的文件名
227 | *
228 | * @return
229 | */
230 | public static String getTempFileName() {
231 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss_SS");
232 | String fileName = format.format(new Timestamp(System
233 | .currentTimeMillis()));
234 | return fileName;
235 | }
236 |
237 | /**
238 | * 获取照相机使用的目录
239 | *
240 | * @return
241 | */
242 | public static String getCamerPath() {
243 | return Environment.getExternalStorageDirectory() + File.separator
244 | + "FounderNews" + File.separator;
245 | }
246 |
247 | /**
248 | * 判断当前Url是否标准的content://样式,如果不是,则返回绝对路径
249 | *
250 | * @return
251 | */
252 | public static String getAbsolutePathFromNoStandardUri(Uri mUri) {
253 | String filePath = null;
254 |
255 | String mUriString = mUri.toString();
256 | mUriString = Uri.decode(mUriString);
257 |
258 | String pre1 = "file://" + SDCARD + File.separator;
259 | String pre2 = "file://" + SDCARD_MNT + File.separator;
260 |
261 | if (mUriString.startsWith(pre1)) {
262 | filePath = Environment.getExternalStorageDirectory().getPath()
263 | + File.separator + mUriString.substring(pre1.length());
264 | } else if (mUriString.startsWith(pre2)) {
265 | filePath = Environment.getExternalStorageDirectory().getPath()
266 | + File.separator + mUriString.substring(pre2.length());
267 | }
268 | return filePath;
269 | }
270 |
271 | /**
272 | * 通过uri获取文件的绝对路径
273 | *
274 | * @param uri
275 | * @return
276 | */
277 | @SuppressWarnings("deprecation")
278 | public static String getAbsoluteImagePath(Activity context, Uri uri) {
279 | String imagePath = "";
280 | String[] proj = { MediaStore.Images.Media.DATA };
281 | Cursor cursor = context.managedQuery(uri, proj, // Which columns to
282 | // return
283 | null, // WHERE clause; which rows to return (all rows)
284 | null, // WHERE clause selection arguments (none)
285 | null); // Order-by clause (ascending by name)
286 |
287 | if (cursor != null) {
288 | int column_index = cursor
289 | .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
290 | if (cursor.getCount() > 0 && cursor.moveToFirst()) {
291 | imagePath = cursor.getString(column_index);
292 | }
293 | }
294 |
295 | return imagePath;
296 | }
297 |
298 | /**
299 | * 获取图片缩略图 只有Android2.1以上版本支持
300 | *
301 | * @param imgName
302 | * @param kind
303 | * MediaStore.Images.Thumbnails.MICRO_KIND
304 | * @return
305 | */
306 | @SuppressWarnings("deprecation")
307 | public static Bitmap loadImgThumbnail(Activity context, String imgName,
308 | int kind) {
309 | Bitmap bitmap = null;
310 |
311 | String[] proj = { MediaStore.Images.Media._ID,
312 | MediaStore.Images.Media.DISPLAY_NAME };
313 |
314 | Cursor cursor = context.managedQuery(
315 | MediaStore.Images.Media.EXTERNAL_CONTENT_URI, proj,
316 | MediaStore.Images.Media.DISPLAY_NAME + "='" + imgName + "'",
317 | null, null);
318 |
319 | if (cursor != null && cursor.getCount() > 0 && cursor.moveToFirst()) {
320 | ContentResolver crThumb = context.getContentResolver();
321 | BitmapFactory.Options options = new BitmapFactory.Options();
322 | options.inSampleSize = 1;
323 | bitmap = MethodsCompat.getThumbnail(crThumb, cursor.getInt(0),
324 | kind, options);
325 | }
326 | return bitmap;
327 | }
328 |
329 | public static Bitmap loadImgThumbnail(String filePath, int w, int h) {
330 | Bitmap bitmap = getBitmapByPath(filePath);
331 | return zoomBitmap(bitmap, w, h,0);
332 | }
333 |
334 | /**
335 | * 获取SD卡中最新图片路径
336 | *
337 | * @return
338 | */
339 | public static String getLatestImage(Activity context) {
340 | String latestImage = null;
341 | String[] items = { MediaStore.Images.Media._ID,
342 | MediaStore.Images.Media.DATA };
343 | Cursor cursor = context.managedQuery(
344 | MediaStore.Images.Media.EXTERNAL_CONTENT_URI, items, null,
345 | null, MediaStore.Images.Media._ID + " desc");
346 |
347 | if (cursor != null && cursor.getCount() > 0) {
348 | cursor.moveToFirst();
349 | for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor
350 | .moveToNext()) {
351 | latestImage = cursor.getString(1);
352 | break;
353 | }
354 | }
355 |
356 | return latestImage;
357 | }
358 |
359 | /**
360 | * 计算缩放图片的宽高
361 | *
362 | * @param img_size
363 | * @param square_size
364 | * @return
365 | */
366 | public static int[] scaleImageSize(int[] img_size, int square_size) {
367 | if (img_size[0] <= square_size && img_size[1] <= square_size)
368 | return img_size;
369 | double ratio = square_size
370 | / (double) Math.max(img_size[0], img_size[1]);
371 | return new int[] { (int) (img_size[0] * ratio),
372 | (int) (img_size[1] * ratio) };
373 | }
374 |
375 | /**
376 | * 创建缩略图
377 | *
378 | * @param context
379 | * @param largeImagePath
380 | * 原始大图路径
381 | * @param thumbfilePath
382 | * 输出缩略图路径
383 | * @param square_size
384 | * 输出图片宽度
385 | * @param quality
386 | * 输出图片质量
387 | * @throws IOException
388 | */
389 | public static void createImageThumbnail(Context context,
390 | String largeImagePath, String thumbfilePath, int square_size,
391 | int quality,int rotate) throws IOException {
392 | BitmapFactory.Options options = new BitmapFactory.Options();
393 | options.inJustDecodeBounds = true;
394 | BitmapFactory.decodeFile(largeImagePath, options);
395 | options.inSampleSize = caculateInSampleSize(options,
396 | square_size, square_size);
397 |
398 | // 使用获得到的InSampleSize再次解析图片
399 | options.inJustDecodeBounds = false;
400 | // 原始图片bitmap
401 | Bitmap cur_bitmap = getBitmapByPath(largeImagePath, options);
402 |
403 | if (cur_bitmap == null)
404 | return;
405 |
406 | // 原始图片的高宽
407 | // int[] cur_img_size = new int[] { cur_bitmap.getWidth(),
408 | // cur_bitmap.getHeight() };
409 | // 计算原始图片缩放后的宽高
410 | // int[] new_img_size = scaleImageSize(cur_img_size, square_size);
411 | // 生成缩放后的bitmap
412 | // Bitmap thb_bitmap = zoomBitmap(cur_bitmap, new_img_size[0],
413 | // new_img_size[1],rotate);
414 | // 生成缩放后的图片文件
415 | saveImageToSD(null, thumbfilePath, cur_bitmap, quality);
416 | }
417 | private static int caculateInSampleSize(BitmapFactory.Options options,
418 | int reqWidth, int reqHeight) {
419 | final int height = options.outHeight;
420 | final int width = options.outWidth;
421 | int inSampleSize = 1;
422 | if (height > reqHeight || width > reqWidth) {
423 | final int halfHeight = height ;
424 | final int halfWidth = width ;
425 | while ((halfHeight / inSampleSize) > reqHeight
426 | && (halfWidth / inSampleSize) > reqWidth) {
427 | inSampleSize *= 2;
428 | }
429 | }
430 | return inSampleSize;
431 | }
432 | /**
433 | * 放大缩小图片
434 | *
435 | * @param bitmap
436 | * @param w
437 | * @param h
438 | * @return
439 | */
440 | public static Bitmap zoomBitmap(Bitmap bitmap, int w, int h,int rotate) {
441 | Bitmap newbmp = null;
442 | if (bitmap != null) {
443 | int width = bitmap.getWidth();
444 | int height = bitmap.getHeight();
445 | Matrix matrix = new Matrix();
446 | float scaleWidht = ((float) w / width);
447 | float scaleHeight = ((float) h / height);
448 | matrix.postScale(scaleWidht, scaleHeight);
449 | matrix.postRotate(rotate);
450 | newbmp = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix,
451 | true);
452 | }
453 | return newbmp;
454 | }
455 |
456 | public static Bitmap scaleBitmap(Bitmap bitmap) {
457 | // 获取这个图片的宽和高
458 | int width = bitmap.getWidth();
459 | int height = bitmap.getHeight();
460 | // 定义预转换成的图片的宽度和高度
461 | int newWidth = 200;
462 | int newHeight = 200;
463 | // 计算缩放率,新尺寸除原始尺寸
464 | float scaleWidth = ((float) newWidth) / width;
465 | float scaleHeight = ((float) newHeight) / height;
466 | // 创建操作图片用的matrix对象
467 | Matrix matrix = new Matrix();
468 | // 缩放图片动作
469 | matrix.postScale(scaleWidth, scaleHeight);
470 | // 旋转图片 动作
471 | // matrix.postRotate(45);
472 | // 创建新的图片
473 | Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height,
474 | matrix, true);
475 | return resizedBitmap;
476 | }
477 |
478 | /**
479 | * (缩放)重绘图片
480 | *
481 | * @param context
482 | * Activity
483 | * @param bitmap
484 | * @return
485 | */
486 | public static Bitmap reDrawBitMap(Activity context, Bitmap bitmap) {
487 | DisplayMetrics dm = new DisplayMetrics();
488 | context.getWindowManager().getDefaultDisplay().getMetrics(dm);
489 | int rHeight = dm.heightPixels;
490 | int rWidth = dm.widthPixels;
491 | // float rHeight=dm.heightPixels/dm.density+0.5f;
492 | // float rWidth=dm.widthPixels/dm.density+0.5f;
493 | // int height=bitmap.getScaledHeight(dm);
494 | // int width = bitmap.getScaledWidth(dm);
495 | int height = bitmap.getHeight();
496 | int width = bitmap.getWidth();
497 | float zoomScale;
498 |
499 | /** 方式3 **/
500 | if (width >= rWidth)
501 | zoomScale = ((float) rWidth) / width;
502 | else
503 | zoomScale = 1.0f;
504 | // 创建操作图片用的matrix对象
505 | Matrix matrix = new Matrix();
506 | // 缩放图片动作
507 | matrix.postScale(zoomScale, zoomScale);
508 | Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
509 | bitmap.getWidth(), bitmap.getHeight(), matrix, true);
510 | return resizedBitmap;
511 | }
512 |
513 | /**
514 | * 将Drawable转化为Bitmap
515 | *
516 | * @param drawable
517 | * @return
518 | */
519 | public static Bitmap drawableToBitmap(Drawable drawable) {
520 | int width = drawable.getIntrinsicWidth();
521 | int height = drawable.getIntrinsicHeight();
522 | Bitmap bitmap = Bitmap.createBitmap(width, height, drawable
523 | .getOpacity() != PixelFormat.OPAQUE ? Config.ARGB_8888
524 | : Config.RGB_565);
525 | Canvas canvas = new Canvas(bitmap);
526 | drawable.setBounds(0, 0, width, height);
527 | drawable.draw(canvas);
528 | return bitmap;
529 |
530 | }
531 |
532 | /**
533 | * 获得圆角图片的方法
534 | *
535 | * @param bitmap
536 | * @param roundPx
537 | * 一般设成14
538 | * @return
539 | */
540 | public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float roundPx) {
541 |
542 | Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
543 | bitmap.getHeight(), Config.ARGB_8888);
544 | Canvas canvas = new Canvas(output);
545 |
546 | final int color = 0xff424242;
547 | final Paint paint = new Paint();
548 | final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
549 | final RectF rectF = new RectF(rect);
550 |
551 | paint.setAntiAlias(true);
552 | canvas.drawARGB(0, 0, 0, 0);
553 | paint.setColor(color);
554 | canvas.drawRoundRect(rectF, roundPx, roundPx, paint);
555 |
556 | paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
557 | canvas.drawBitmap(bitmap, rect, rect, paint);
558 |
559 | return output;
560 | }
561 |
562 | /**
563 | * 获得带倒影的图片方法
564 | *
565 | * @param bitmap
566 | * @return
567 | */
568 | public static Bitmap createReflectionImageWithOrigin(Bitmap bitmap) {
569 | final int reflectionGap = 4;
570 | int width = bitmap.getWidth();
571 | int height = bitmap.getHeight();
572 |
573 | Matrix matrix = new Matrix();
574 | matrix.preScale(1, -1);
575 |
576 | Bitmap reflectionImage = Bitmap.createBitmap(bitmap, 0, height / 2,
577 | width, height / 2, matrix, false);
578 |
579 | Bitmap bitmapWithReflection = Bitmap.createBitmap(width,
580 | (height + height / 2), Config.ARGB_8888);
581 |
582 | Canvas canvas = new Canvas(bitmapWithReflection);
583 | canvas.drawBitmap(bitmap, 0, 0, null);
584 | Paint deafalutPaint = new Paint();
585 | canvas.drawRect(0, height, width, height + reflectionGap, deafalutPaint);
586 |
587 | canvas.drawBitmap(reflectionImage, 0, height + reflectionGap, null);
588 |
589 | Paint paint = new Paint();
590 | LinearGradient shader = new LinearGradient(0, bitmap.getHeight(), 0,
591 | bitmapWithReflection.getHeight() + reflectionGap, 0x70ffffff,
592 | 0x00ffffff, TileMode.CLAMP);
593 | paint.setShader(shader);
594 | // Set the Transfer mode to be porter duff and destination in
595 | paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
596 | // Draw a rectangle using the paint with our linear gradient
597 | canvas.drawRect(0, height, width, bitmapWithReflection.getHeight()
598 | + reflectionGap, paint);
599 |
600 | return bitmapWithReflection;
601 | }
602 |
603 | /**
604 | * 将bitmap转化为drawable
605 | *
606 | * @param bitmap
607 | * @return
608 | */
609 | public static Drawable bitmapToDrawable(Bitmap bitmap) {
610 | Drawable drawable = new BitmapDrawable(bitmap);
611 | return drawable;
612 | }
613 |
614 | /**
615 | * 获取图片类型
616 | *
617 | * @param file
618 | * @return
619 | */
620 | public static String getImageType(File file) {
621 | if (file == null || !file.exists()) {
622 | return null;
623 | }
624 | InputStream in = null;
625 | try {
626 | in = new FileInputStream(file);
627 | String type = getImageType(in);
628 | return type;
629 | } catch (IOException e) {
630 | return null;
631 | } finally {
632 | try {
633 | if (in != null) {
634 | in.close();
635 | }
636 | } catch (IOException e) {
637 | }
638 | }
639 | }
640 |
641 | /**
642 | * 获取图片的类型信息
643 | *
644 | * @param in
645 | * @return
646 | * @see #getImageType(byte[])
647 | */
648 | public static String getImageType(InputStream in) {
649 | if (in == null) {
650 | return null;
651 | }
652 | try {
653 | byte[] bytes = new byte[8];
654 | in.read(bytes);
655 | return getImageType(bytes);
656 | } catch (IOException e) {
657 | return null;
658 | }
659 | }
660 |
661 | /**
662 | * 获取图片的类型信息
663 | *
664 | * @param bytes
665 | * 2~8 byte at beginning of the image file
666 | * @return image mimetype or null if the file is not image
667 | */
668 | public static String getImageType(byte[] bytes) {
669 | if (isJPEG(bytes)) {
670 | return "image/jpeg";
671 | }
672 | if (isGIF(bytes)) {
673 | return "image/gif";
674 | }
675 | if (isPNG(bytes)) {
676 | return "image/png";
677 | }
678 | if (isBMP(bytes)) {
679 | return "application/x-bmp";
680 | }
681 | return null;
682 | }
683 |
684 | private static boolean isJPEG(byte[] b) {
685 | if (b.length < 2) {
686 | return false;
687 | }
688 | return (b[0] == (byte) 0xFF) && (b[1] == (byte) 0xD8);
689 | }
690 |
691 | private static boolean isGIF(byte[] b) {
692 | if (b.length < 6) {
693 | return false;
694 | }
695 | return b[0] == 'G' && b[1] == 'I' && b[2] == 'F' && b[3] == '8'
696 | && (b[4] == '7' || b[4] == '9') && b[5] == 'a';
697 | }
698 |
699 | private static boolean isPNG(byte[] b) {
700 | if (b.length < 8) {
701 | return false;
702 | }
703 | return (b[0] == (byte) 137 && b[1] == (byte) 80 && b[2] == (byte) 78
704 | && b[3] == (byte) 71 && b[4] == (byte) 13 && b[5] == (byte) 10
705 | && b[6] == (byte) 26 && b[7] == (byte) 10);
706 | }
707 |
708 | private static boolean isBMP(byte[] b) {
709 | if (b.length < 2) {
710 | return false;
711 | }
712 | return (b[0] == 0x42) && (b[1] == 0x4d);
713 | }
714 |
715 | /**
716 | * 获取图片路径 2014年8月12日
717 | *
718 | * @param uri
719 | * @return E-mail:mr.huangwenwei@gmail.com
720 | */
721 | public static String getImagePath(Uri uri, Activity context) {
722 |
723 | String[] projection = { MediaColumns.DATA };
724 | Cursor cursor = context.getContentResolver().query(uri, projection,
725 | null, null, null);
726 | if (cursor != null) {
727 | cursor.moveToFirst();
728 | int columIndex = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
729 | String ImagePath = cursor.getString(columIndex);
730 | cursor.close();
731 | return ImagePath;
732 | }
733 |
734 | return uri.toString().replace("file://", "");
735 | }
736 |
737 | static Bitmap bitmap = null;
738 | /**
739 | *2014年8月13日
740 | *@param uri
741 | *@param context
742 | * E-mail:mr.huangwenwei@gmail.com
743 | */
744 | public static Bitmap loadPicasaImageFromGalley(final Uri uri, final Activity context) {
745 |
746 | String[] projection = { MediaColumns.DATA, MediaColumns.DISPLAY_NAME };
747 | Cursor cursor = context.getContentResolver().query(uri, projection,
748 | null, null, null);
749 | if (cursor != null) {
750 | cursor.moveToFirst();
751 |
752 | int columIndex = cursor.getColumnIndex(MediaColumns.DISPLAY_NAME);
753 | if (columIndex != -1) {
754 | new Thread(new Runnable() {
755 |
756 | @Override
757 | public void run() {
758 | try {
759 | bitmap = MediaStore.Images.Media
760 | .getBitmap(context.getContentResolver(),
761 | uri);
762 | } catch (FileNotFoundException e) {
763 | e.printStackTrace();
764 | } catch (IOException e) {
765 | e.printStackTrace();
766 | }
767 |
768 | }
769 | }).start();
770 | }
771 | cursor.close();
772 | return bitmap;
773 | }else
774 | return null;
775 | }
776 | public static File saveBitmap2file(Context context,Bitmap bmp,String filename){
777 | CompressFormat format= CompressFormat.JPEG;
778 | int quality = 100;
779 | OutputStream stream = null;
780 | try {
781 | stream = new FileOutputStream(AppContext.getInstance().getCachePath()+File.separator + filename);
782 | } catch (FileNotFoundException e) {
783 | // TODO Auto-generated catch block
784 | e.printStackTrace();
785 | }
786 |
787 | if( bmp.compress(format, quality, stream)){
788 | return new File(AppContext.getInstance().getCachePath()+File.separator + filename);
789 | }
790 | return null;
791 |
792 | }
793 | public static String getRealFilePath( final Context context, final Uri uri ) {
794 | if ( null == uri ) return null;
795 | final String scheme = uri.getScheme();
796 | String data = null;
797 | if ( scheme == null )
798 | data = uri.getPath();
799 | else if ( ContentResolver.SCHEME_FILE.equals( scheme ) ) {
800 | data = uri.getPath();
801 | } else if ( ContentResolver.SCHEME_CONTENT.equals( scheme ) ) {
802 | Cursor cursor = context.getContentResolver().query( uri, new String[] { MediaStore.Images.ImageColumns.DATA }, null, null, null );
803 | if ( null != cursor ) {
804 | if ( cursor.moveToFirst() ) {
805 | int index = cursor.getColumnIndex( MediaStore.Images.ImageColumns.DATA );
806 | if ( index > -1 ) {
807 | data = cursor.getString( index );
808 | }
809 | }
810 | cursor.close();
811 | }
812 | }
813 | return data;
814 | }
815 | }
816 |
--------------------------------------------------------------------------------