├── .gitignore ├── README.md ├── example ├── AndroidManifest.xml ├── TouchGallery.iml ├── assets │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ └── 5.jpg ├── lint.xml ├── project.properties ├── res │ ├── drawable │ │ └── icon.png │ ├── layout │ │ ├── activity_main.xml │ │ └── main.xml │ ├── menu │ │ └── activity_main.xml │ └── values │ │ └── strings.xml └── src │ └── ru │ └── truba │ └── touchgallery │ ├── GalleryFileActivity.java │ ├── GalleryUrlActivity.java │ └── MainActivity.java └── library ├── AndroidManifest.xml ├── README.md ├── ant.properties ├── build.xml ├── libs └── android-support-v4.jar ├── pom.xml ├── proguard-project.txt ├── project.properties ├── res ├── drawable-hdpi │ ├── ic_launcher.png │ └── no_photo.png ├── drawable-ldpi │ ├── ic_launcher.png │ └── no_photo.png ├── drawable-mdpi │ ├── ic_launcher.png │ └── no_photo.png ├── drawable-xhdpi │ ├── ic_launcher.png │ └── no_photo.png ├── layout │ └── main.xml └── values │ └── strings.xml └── src └── ru └── truba └── touchgallery ├── GalleryWidget ├── BasePagerAdapter.java ├── FilePagerAdapter.java ├── GalleryViewPager.java ├── InfinityFilePagerAdapter.java ├── InfinityUrlAdapter.java └── UrlPagerAdapter.java └── TouchView ├── EclairMotionEvent.java ├── FileTouchImageView.java ├── InputStreamWrapper.java ├── TouchImageView.java ├── UrlTouchImageView.java └── WrapMotionEvent.java /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## IntelliJ IDEA 34 | ################# 35 | 36 | *.iml 37 | 38 | ################# 39 | ## Visual Studio 40 | ################# 41 | 42 | ## Ignore Visual Studio temporary files, build results, and 43 | ## files generated by popular Visual Studio add-ons. 44 | 45 | # User-specific files 46 | *.suo 47 | *.user 48 | *.sln.docstates 49 | 50 | # Build results 51 | [Dd]ebug/ 52 | [Rr]elease/ 53 | *_i.c 54 | *_p.c 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.vspscc 69 | .builds 70 | *.dotCover 71 | 72 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 73 | #packages/ 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opensdf 80 | *.sdf 81 | 82 | # Visual Studio profiler 83 | *.psess 84 | *.vsp 85 | 86 | # ReSharper is a .NET coding add-in 87 | _ReSharper* 88 | 89 | # Installshield output folder 90 | [Ee]xpress 91 | 92 | # DocProject is a documentation generator add-in 93 | DocProject/buildhelp/ 94 | DocProject/Help/*.HxT 95 | DocProject/Help/*.HxC 96 | DocProject/Help/*.hhc 97 | DocProject/Help/*.hhk 98 | DocProject/Help/*.hhp 99 | DocProject/Help/Html2 100 | DocProject/Help/html 101 | 102 | # Click-Once directory 103 | publish 104 | 105 | # Others 106 | [Bb]in 107 | [Oo]bj 108 | sql 109 | TestResults 110 | *.Cache 111 | ClientBin 112 | stylecop.* 113 | ~$* 114 | *.dbmdl 115 | Generated_Code #added for RIA/Silverlight projects 116 | 117 | # Backup & report files from converting an old project file to a newer 118 | # Visual Studio version. Backup files are not needed, because we have git ;-) 119 | _UpgradeReport_Files/ 120 | Backup*/ 121 | UpgradeLog*.XML 122 | 123 | 124 | 125 | ############ 126 | ## Windows 127 | ############ 128 | 129 | # Windows image file caches 130 | Thumbs.db 131 | 132 | # Folder config file 133 | Desktop.ini 134 | 135 | 136 | ############# 137 | ## Python 138 | ############# 139 | 140 | *.py[co] 141 | 142 | # Packages 143 | *.egg 144 | *.egg-info 145 | dist 146 | build 147 | eggs 148 | parts 149 | bin 150 | var 151 | sdist 152 | develop-eggs 153 | .installed.cfg 154 | 155 | # Installer logs 156 | pip-log.txt 157 | 158 | # Unit test / coverage reports 159 | .coverage 160 | .tox 161 | 162 | #Translations 163 | *.mo 164 | 165 | #Mr Developer 166 | .mr.developer.cfg 167 | 168 | # Mac crap 169 | .DS_Store 170 | 171 | #inteliji idea 172 | .idea 173 | 174 | #android 175 | gen 176 | out 177 | 178 | #project 179 | example/src/ru/truba/touchgallery/GalleryWidget 180 | example/src/ru/truba/touchgallery/TouchView 181 | 182 | bin/ 183 | gen/ 184 | target/ 185 | 186 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Attention please! 2 | =================== 3 | This library is not supported anymore. Please, check out nice living forks! 4 | Thanks for attention. 5 | 6 | 7 | AndroidTouchGallery 8 | =================== 9 | 10 | Android widget for gallery, using viewpager. Allow pinch zoom and drag for images by url. 11 | Widget allows use it in Android > 2.0! 12 | 13 | 14 | How to use 15 | =================== 16 | 1. Make import library folder into your IDE. 17 | 2. Make sure, that AndroidTouchGallery has included in your project as library. Check project properties, and make sure checkbox "Is library" is checked. 18 | 3. Include GalleryViewPager in your layout xml or programmatically. 19 | ``` 20 | 25 | ``` 26 | 27 | 4. Provide one of library adapters: UrlPagerAdapter or FilePagerAdapter 28 | For example (an Activity code): 29 | ```java 30 | setContentView(R.layout.main); 31 | String[] urls = { 32 | "http://cs407831.userapi.com/v407831207/18f6/jBaVZFDhXRA.jpg", 33 | "http://cs407831.userapi.com/v4078f31207/18fe/4Tz8av5Hlvo.jpg", //special url with error 34 | "http://cs407831.userapi.com/v407831207/1906/oxoP6URjFtA.jpg", 35 | "http://cs407831.userapi.com/v407831207/190e/2Sz9A774hUc.jpg", 36 | "http://cs407831.userapi.com/v407831207/1916/Ua52RjnKqjk.jpg", 37 | "http://cs407831.userapi.com/v407831207/191e/QEQE83Ok0lQ.jpg" 38 | }; 39 | List items = new ArrayList(); 40 | Collections.addAll(items, urls); 41 | UrlPagerAdapter pagerAdapter = new UrlPagerAdapter(this, items); 42 | GalleryViewPager mViewPager = (GalleryViewPager)findViewById(R.id.viewer); 43 | mViewPager.setOffscreenPageLimit(3); 44 | mViewPager.setAdapter(pagerAdapter); 45 | ``` 46 | 47 | 5. You can always check example if you miss something. 48 | 49 | License 50 | =================== 51 | Copyright (c) 2012-2013 Roman Truba 52 | 53 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 54 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 55 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 56 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 57 | 58 | The above copyright notice and this permission notice shall be included in all copies or substantial 59 | portions of the Software. 60 | 61 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 62 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 63 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 64 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 65 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 66 | -------------------------------------------------------------------------------- /example/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 17 | 20 | 21 | 24 | 25 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /example/TouchGallery.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /example/assets/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/example/assets/1.jpg -------------------------------------------------------------------------------- /example/assets/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/example/assets/2.jpg -------------------------------------------------------------------------------- /example/assets/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/example/assets/3.jpg -------------------------------------------------------------------------------- /example/assets/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/example/assets/4.jpg -------------------------------------------------------------------------------- /example/assets/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/example/assets/5.jpg -------------------------------------------------------------------------------- /example/lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /example/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by IntelliJ IDEA 2 | # Project target. 3 | target=android-17 4 | android.library.reference.1=../library 5 | -------------------------------------------------------------------------------- /example/res/drawable/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/example/res/drawable/icon.png -------------------------------------------------------------------------------- /example/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /example/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 11 | -------------------------------------------------------------------------------- /example/res/menu/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /example/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Touch Gallery 5 | Hello world! 6 | Settings 7 | Main Activity 8 | 9 | -------------------------------------------------------------------------------- /example/src/ru/truba/touchgallery/GalleryFileActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 Roman Truba 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery; 19 | 20 | import android.app.Activity; 21 | import android.os.Bundle; 22 | import android.widget.Toast; 23 | import ru.truba.touchgallery.GalleryWidget.FilePagerAdapter; 24 | import ru.truba.touchgallery.GalleryWidget.GalleryViewPager; 25 | import ru.truba.touchgallery.GalleryWidget.BasePagerAdapter.OnItemChangeListener; 26 | 27 | import java.io.File; 28 | import java.io.FileOutputStream; 29 | import java.io.IOException; 30 | import java.io.InputStream; 31 | import java.io.OutputStream; 32 | import java.util.ArrayList; 33 | import java.util.List; 34 | 35 | public class GalleryFileActivity extends Activity { 36 | 37 | private GalleryViewPager mViewPager; 38 | public void onCreate(Bundle savedInstanceState) { 39 | super.onCreate(savedInstanceState); 40 | setContentView(R.layout.main); 41 | 42 | String[] urls = null; 43 | List items = new ArrayList(); 44 | try { 45 | urls = getAssets().list(""); 46 | 47 | for (String filename : urls) 48 | { 49 | if (filename.matches(".+\\.jpg")) 50 | { 51 | String path = getFilesDir() + "/" + filename; 52 | copy(getAssets().open(filename), new File(path) ); 53 | items.add(path); 54 | } 55 | } 56 | } catch (IOException e) { 57 | e.printStackTrace(); 58 | } 59 | 60 | FilePagerAdapter pagerAdapter = new FilePagerAdapter(this, items); 61 | pagerAdapter.setOnItemChangeListener(new OnItemChangeListener() 62 | { 63 | @Override 64 | public void onItemChange(int currentPosition) 65 | { 66 | Toast.makeText(GalleryFileActivity.this, "Current item is " + currentPosition, Toast.LENGTH_SHORT).show(); 67 | } 68 | }); 69 | 70 | mViewPager = (GalleryViewPager)findViewById(R.id.viewer); 71 | mViewPager.setOffscreenPageLimit(3); 72 | mViewPager.setAdapter(pagerAdapter); 73 | } 74 | public void copy(InputStream in, File dst) throws IOException { 75 | 76 | OutputStream out = new FileOutputStream(dst); 77 | 78 | // Transfer bytes from in to out 79 | byte[] buf = new byte[1024]; 80 | int len; 81 | while ((len = in.read(buf)) > 0) { 82 | out.write(buf, 0, len); 83 | } 84 | in.close(); 85 | out.close(); 86 | } 87 | } -------------------------------------------------------------------------------- /example/src/ru/truba/touchgallery/GalleryUrlActivity.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 Roman Truba 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery; 19 | 20 | import android.app.Activity; 21 | import android.os.Bundle; 22 | import android.widget.Toast; 23 | import ru.truba.touchgallery.GalleryWidget.BasePagerAdapter.OnItemChangeListener; 24 | import ru.truba.touchgallery.GalleryWidget.GalleryViewPager; 25 | import ru.truba.touchgallery.GalleryWidget.UrlPagerAdapter; 26 | 27 | import java.util.ArrayList; 28 | import java.util.Collections; 29 | import java.util.List; 30 | 31 | public class GalleryUrlActivity extends Activity { 32 | 33 | private GalleryViewPager mViewPager; 34 | public void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | setContentView(R.layout.main); 37 | String[] urls = { 38 | "http://cs407831.userapi.com/v407831207/18f6/jBaVZFDhXRA.jpg", 39 | "http://cs407831.userapi.com/v4078f31207/18fe/4Tz8av5Hlvo.jpg", 40 | "http://cs407831.userapi.com/v407831207/1906/oxoP6URjFtA.jpg", 41 | "http://cs407831.userapi.com/v407831207/190e/2Sz9A774hUc.jpg", 42 | "http://cs407831.userapi.com/v407831207/1916/Ua52RjnKqjk.jpg", 43 | "http://cs407831.userapi.com/v407831207/191e/QEQE83Ok0lQ.jpg" 44 | }; 45 | List items = new ArrayList(); 46 | Collections.addAll(items, urls); 47 | 48 | UrlPagerAdapter pagerAdapter = new UrlPagerAdapter(this, items); 49 | pagerAdapter.setOnItemChangeListener(new OnItemChangeListener() 50 | { 51 | @Override 52 | public void onItemChange(int currentPosition) 53 | { 54 | Toast.makeText(GalleryUrlActivity.this, "Current item is " + currentPosition, Toast.LENGTH_SHORT).show(); 55 | } 56 | }); 57 | 58 | mViewPager = (GalleryViewPager)findViewById(R.id.viewer); 59 | mViewPager.setOffscreenPageLimit(3); 60 | mViewPager.setAdapter(pagerAdapter); 61 | 62 | } 63 | 64 | } -------------------------------------------------------------------------------- /example/src/ru/truba/touchgallery/MainActivity.java: -------------------------------------------------------------------------------- 1 | package ru.truba.touchgallery; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | 8 | import android.os.Bundle; 9 | import android.app.ListActivity; 10 | import android.content.Intent; 11 | import android.view.View; 12 | import android.widget.ListAdapter; 13 | import android.widget.ListView; 14 | import android.widget.SimpleAdapter; 15 | 16 | public class MainActivity extends ListActivity { 17 | 18 | public static final String TITLE = "title"; 19 | public static final String SUBTITLE = "subtitle"; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | // setContentView(R.layout.activity_main); 25 | 26 | setListAdapter(createAdapter()); 27 | } 28 | 29 | protected Map createElement(String title, String subtitle) 30 | { 31 | Map result = new HashMap(); 32 | result.put(TITLE, title); 33 | result.put(SUBTITLE, subtitle); 34 | return result; 35 | } 36 | public List> getData() 37 | { 38 | List> result = new ArrayList>(); 39 | result.add(createElement("Web load", "In this example, you provide list of URLs to display in gallery")); 40 | result.add(createElement("Local load", "In this example, you provide list of files to display in gallery")); 41 | return result; 42 | } 43 | public ListAdapter createAdapter() 44 | { 45 | SimpleAdapter adapter = new SimpleAdapter(this, getData(), 46 | android.R.layout.simple_list_item_2, 47 | new String[]{TITLE, SUBTITLE}, 48 | new int[]{android.R.id.text1, android.R.id.text2}); 49 | return adapter; 50 | } 51 | 52 | @Override 53 | protected void onListItemClick(ListView l, View v, int position, long id) { 54 | Intent i = null; 55 | switch (position) 56 | { 57 | case 0: 58 | i = new Intent(this, GalleryUrlActivity.class); 59 | break; 60 | case 1: 61 | i = new Intent(this, GalleryFileActivity.class); 62 | break; 63 | } 64 | startActivity(i); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /library/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /library/README.md: -------------------------------------------------------------------------------- 1 | AndroidTouchGallery 2 | =================== 3 | 4 | Android widget for gallery, using viewpager. Allow pinch zoom and drag for images by url. 5 | Widget allows use it in Android > 2.0! 6 | 7 | 8 | How to use 9 | =================== 10 | 1. Download and install "Android support" package. Look here for some instructions: http://android-developers.blogspot.com/2011/08/horizontal-view-swiping-with-viewpager.html 11 | 2. Add files to your project and then use it in layout or programmatically 12 | 3. You can see example for better understanding -------------------------------------------------------------------------------- /library/ant.properties: -------------------------------------------------------------------------------- 1 | # This file is used to override default values used by the Ant build system. 2 | # 3 | # This file must be checked into Version Control Systems, as it is 4 | # integral to the build system of your project. 5 | 6 | # This file is only used by the Ant script. 7 | 8 | # You can use this to override default values such as 9 | # 'source.dir' for the location of your java source folder and 10 | # 'out.dir' for the location of your output folder. 11 | 12 | # You can also use it define how the release builds are signed by declaring 13 | # the following properties: 14 | # 'key.store' for the location of your keystore and 15 | # 'key.alias' for the name of the key to use. 16 | # The password will be asked during the build when you use the 'release' target. 17 | 18 | -------------------------------------------------------------------------------- /library/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 9 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 | 49 | 50 | 51 | 52 | 56 | 57 | 69 | 70 | 71 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /library/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/library/libs/android-support-v4.jar -------------------------------------------------------------------------------- /library/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 4.0.0 9 | AndroidTouchGallery 10 | ru.truba.AndroidTouchGallery 11 | touchgallery 12 | 1.1 13 | apklib 14 | 15 | 16 | https://github.com/goblindegook/AndroidTouchGallery 17 | 18 | 19 | 20 | 4.1.1.4 21 | 22 | 23 | 24 | 25 | com.google.android 26 | support-v4 27 | r7 28 | 29 | 30 | com.google.android 31 | android 32 | ${platform.version} 33 | provided 34 | 35 | 36 | 37 | 38 | src 39 | 40 | 41 | com.jayway.maven.plugins.android.generation2 42 | android-maven-plugin 43 | 3.5.0 44 | 45 | ${project.basedir}/AndroidManifest.xml 46 | 47 | 17 48 | 49 | true 50 | 51 | true 52 | 53 | 54 | 55 | maven-compiler-plugin 56 | 2.5.1 57 | 58 | 1.6 59 | 1.6 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /library/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /library/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | android.library=true 14 | # Project target. 15 | target=android-17 16 | -------------------------------------------------------------------------------- /library/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/library/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /library/res/drawable-hdpi/no_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/library/res/drawable-hdpi/no_photo.png -------------------------------------------------------------------------------- /library/res/drawable-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/library/res/drawable-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /library/res/drawable-ldpi/no_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/library/res/drawable-ldpi/no_photo.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/library/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/no_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/library/res/drawable-mdpi/no_photo.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/library/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/no_photo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RomanTruba/AndroidTouchGallery/f9d88cc56acf1e1e8a52130d4aa6340267b1b632/library/res/drawable-xhdpi/no_photo.png -------------------------------------------------------------------------------- /library/res/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /library/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ACTIVITY_ENTRY_NAME 4 | 5 | -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/GalleryWidget/BasePagerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 Roman Truba 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery.GalleryWidget; 19 | 20 | import android.content.Context; 21 | import android.os.Parcelable; 22 | import android.support.v4.view.PagerAdapter; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | 26 | import java.util.List; 27 | 28 | /** 29 | Class wraps URLs to adapter, then it instantiates UrlTouchImageView objects to paging up through them. 30 | */ 31 | public class BasePagerAdapter extends PagerAdapter { 32 | 33 | protected final List mResources; 34 | protected final Context mContext; 35 | protected int mCurrentPosition = -1; 36 | protected OnItemChangeListener mOnItemChangeListener; 37 | 38 | public BasePagerAdapter() 39 | { 40 | mResources = null; 41 | mContext = null; 42 | } 43 | 44 | public BasePagerAdapter(Context context, List resources) 45 | { 46 | this.mResources = resources; 47 | this.mContext = context; 48 | } 49 | 50 | @Override 51 | public void setPrimaryItem(ViewGroup container, final int position, Object object) { 52 | super.setPrimaryItem(container, position, object); 53 | if (mCurrentPosition == position) return; 54 | GalleryViewPager galleryContainer = ((GalleryViewPager)container); 55 | if (galleryContainer.mCurrentView != null) { 56 | galleryContainer.mCurrentView.resetScale(); 57 | } 58 | mCurrentPosition = position; 59 | if (mOnItemChangeListener != null) mOnItemChangeListener.onItemChange(mCurrentPosition); 60 | } 61 | 62 | @Override 63 | public void destroyItem(ViewGroup collection, int position, Object view){ 64 | collection.removeView((View) view); 65 | } 66 | 67 | @Override 68 | public int getCount() 69 | { 70 | return mResources.size(); 71 | } 72 | 73 | @Override 74 | public boolean isViewFromObject(View view, Object object){ 75 | return view.equals(object); 76 | } 77 | 78 | @Override 79 | public void finishUpdate(ViewGroup arg0){ 80 | } 81 | 82 | @Override 83 | public void restoreState(Parcelable arg0, ClassLoader arg1){ 84 | } 85 | 86 | @Override 87 | public Parcelable saveState(){ 88 | return null; 89 | } 90 | 91 | @Override 92 | public void startUpdate(ViewGroup arg0) { } 93 | 94 | public int getCurrentPosition() { return mCurrentPosition; } 95 | 96 | public void setOnItemChangeListener(OnItemChangeListener listener) { mOnItemChangeListener = listener; } 97 | 98 | public static interface OnItemChangeListener 99 | { 100 | public void onItemChange(int currentPosition); 101 | } 102 | }; -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/GalleryWidget/FilePagerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Roman Truba 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery.GalleryWidget; 19 | 20 | import java.util.List; 21 | 22 | import android.content.Context; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import ru.truba.touchgallery.TouchView.FileTouchImageView; 26 | 27 | /** 28 | Class wraps file paths to adapter, then it instantiates {@link ru.truba.touchgallery.TouchView.FileTouchImageView} objects to paging up through them. 29 | */ 30 | public class FilePagerAdapter extends BasePagerAdapter { 31 | 32 | 33 | public FilePagerAdapter(Context context, List resources) 34 | { 35 | super(context, resources); 36 | } 37 | 38 | @Override 39 | public void setPrimaryItem(ViewGroup container, int position, Object object) { 40 | super.setPrimaryItem(container, position, object); 41 | ((GalleryViewPager)container).mCurrentView = ((FileTouchImageView)object).getImageView(); 42 | } 43 | 44 | @Override 45 | public Object instantiateItem(ViewGroup collection, int position){ 46 | final FileTouchImageView iv = new FileTouchImageView(mContext); 47 | iv.setUrl(mResources.get(position)); 48 | iv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 49 | 50 | collection.addView(iv, 0); 51 | return iv; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/GalleryWidget/GalleryViewPager.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 Roman Truba 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery.GalleryWidget; 19 | 20 | import android.annotation.TargetApi; 21 | import android.content.Context; 22 | import android.graphics.PointF; 23 | import android.os.Build; 24 | import android.support.v4.view.ViewPager; 25 | import android.util.AttributeSet; 26 | import android.view.MotionEvent; 27 | import android.view.View; 28 | 29 | import ru.truba.touchgallery.TouchView.TouchImageView; 30 | 31 | /** 32 | This class implements method to help TouchImageView fling, draggin and scaling. 33 | */ 34 | public class GalleryViewPager extends ViewPager { 35 | 36 | PointF last; 37 | public TouchImageView mCurrentView; 38 | 39 | /** 40 | * @Fabio add OnItemClickListener interface 41 | */ 42 | protected OnItemClickListener mOnItemClickListener; 43 | 44 | public GalleryViewPager(Context context) { 45 | super(context); 46 | } 47 | public GalleryViewPager(Context context, AttributeSet attrs) { 48 | super(context, attrs); 49 | } 50 | 51 | @TargetApi(Build.VERSION_CODES.ECLAIR) 52 | private float[] handleMotionEvent(MotionEvent event) { 53 | switch (event.getAction() & MotionEvent.ACTION_MASK) { 54 | case MotionEvent.ACTION_DOWN: 55 | last = new PointF(event.getX(0), event.getY(0)); 56 | break; 57 | case MotionEvent.ACTION_MOVE: 58 | case MotionEvent.ACTION_UP: 59 | PointF curr = new PointF(event.getX(0), event.getY(0)); 60 | return new float[]{curr.x - last.x, curr.y - last.y}; 61 | 62 | } 63 | return null; 64 | } 65 | @Override 66 | public boolean onTouchEvent(MotionEvent event) { 67 | 68 | if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) { 69 | //super.onInterceptTouchEvent(event); 70 | 71 | float endX = event.getX(); 72 | float endY = event.getY(); 73 | if(isAClick(startX, endX, startY, endY)) { 74 | if(mOnItemClickListener != null) { 75 | mOnItemClickListener.onItemClicked(mCurrentView, getCurrentItem()); 76 | } 77 | //launchFullPhotoActivity(imageUrls);// WE HAVE A CLICK!! 78 | } else { 79 | super.onTouchEvent(event); 80 | } 81 | } 82 | 83 | if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) { 84 | startX = event.getX(); 85 | startY = event.getY(); 86 | } 87 | 88 | /*if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) 89 | { 90 | super.onTouchEvent(event); 91 | }*/ 92 | 93 | float [] difference = handleMotionEvent(event); 94 | 95 | if (mCurrentView.pagerCanScroll()) { 96 | return super.onTouchEvent(event); 97 | } 98 | else { 99 | if (difference != null && mCurrentView.onRightSide && difference[0] < 0) //move right 100 | { 101 | return super.onTouchEvent(event); 102 | } 103 | if (difference != null && mCurrentView.onLeftSide && difference[0] > 0) //move left 104 | { 105 | return super.onTouchEvent(event); 106 | } 107 | if (difference == null && ( mCurrentView.onLeftSide || mCurrentView.onRightSide)) 108 | { 109 | return super.onTouchEvent(event); 110 | } 111 | } 112 | 113 | return false; 114 | } 115 | 116 | private float startX; 117 | private float startY; 118 | 119 | @Override 120 | public boolean onInterceptTouchEvent(MotionEvent event) { 121 | if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) { 122 | //super.onInterceptTouchEvent(event); 123 | 124 | float endX = event.getX(); 125 | float endY = event.getY(); 126 | if(isAClick(startX, endX, startY, endY)) { 127 | if(mOnItemClickListener != null) { 128 | mOnItemClickListener.onItemClicked(mCurrentView, getCurrentItem()); 129 | } 130 | } else { 131 | super.onInterceptTouchEvent(event); 132 | } 133 | } 134 | 135 | if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) { 136 | startX = event.getX(); 137 | startY = event.getY(); 138 | } 139 | 140 | 141 | float [] difference = handleMotionEvent(event); 142 | 143 | if (mCurrentView.pagerCanScroll()) { 144 | return super.onInterceptTouchEvent(event); 145 | } 146 | else { 147 | if (difference != null && mCurrentView.onRightSide && difference[0] < 0) //move right 148 | { 149 | return super.onInterceptTouchEvent(event); 150 | } 151 | if (difference != null && mCurrentView.onLeftSide && difference[0] > 0) //move left 152 | { 153 | return super.onInterceptTouchEvent(event); 154 | } 155 | if (difference == null && ( mCurrentView.onLeftSide || mCurrentView.onRightSide)) 156 | { 157 | return super.onInterceptTouchEvent(event); 158 | } 159 | } 160 | return false; 161 | } 162 | 163 | private boolean isAClick(float startX, float endX, float startY, float endY) { 164 | float differenceX = Math.abs(startX - endX); 165 | float differenceY = Math.abs(startY - endY); 166 | if (differenceX > CLICK_ACTION_THRESHHOLD/* =5 */ || differenceY > CLICK_ACTION_THRESHHOLD) { 167 | return false; 168 | } 169 | return true; 170 | } 171 | 172 | public static interface OnItemClickListener { 173 | public void onItemClicked(View view, int position); 174 | } 175 | 176 | private final static int CLICK_ACTION_THRESHHOLD = 5; 177 | public void setOnItemClickListener(OnItemClickListener listener) { mOnItemClickListener = listener; } 178 | }; -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/GalleryWidget/InfinityFilePagerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Roman Truba 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery.GalleryWidget; 19 | 20 | import android.content.Context; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | import android.widget.ImageView; 24 | 25 | import java.util.List; 26 | 27 | import ru.truba.touchgallery.TouchView.FileTouchImageView; 28 | 29 | /** 30 | Class wraps file paths to adapter, then it instantiates {@link ru.truba.touchgallery.TouchView.FileTouchImageView} objects to paging up through them. 31 | */ 32 | public class InfinityFilePagerAdapter extends BasePagerAdapter { 33 | 34 | private int TOTAL_PAGES = -1; 35 | private int MIN_LOOPS = 1000; 36 | // You can choose a bigger number for LOOPS, but you know, nobody will fling 37 | // more than 1000 times just in order to test your "infinite" ViewPager :D 38 | public int FIRST_PAGE = 1; 39 | 40 | private ImageView.ScaleType mScaleType = null; 41 | 42 | public InfinityFilePagerAdapter(Context context, List resources) { 43 | super(context, resources); 44 | TOTAL_PAGES = resources.size(); 45 | FIRST_PAGE = TOTAL_PAGES * MIN_LOOPS / 2; 46 | } 47 | 48 | @Override 49 | public void setPrimaryItem(ViewGroup container, int position, Object object) { 50 | super.setPrimaryItem(container, position, object); 51 | ((GalleryViewPager)container).mCurrentView = ((FileTouchImageView)object).getImageView(); 52 | } 53 | 54 | @Override 55 | public Object instantiateItem(ViewGroup collection, int position){ 56 | final FileTouchImageView iv = new FileTouchImageView(mContext); 57 | 58 | position = position % TOTAL_PAGES; 59 | 60 | iv.setUrl(mResources.get(position)); 61 | iv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 62 | 63 | if(mScaleType != null) 64 | iv.setScaleType(mScaleType); 65 | collection.addView(iv, 0); 66 | return iv; 67 | } 68 | 69 | /** 70 | * Set Scaletype for ImageView 71 | * @param scaletype 72 | */ 73 | public void setScaleTypeForImageView(ImageView.ScaleType scaletype) { 74 | mScaleType = scaletype; 75 | } 76 | 77 | @Override 78 | public int getCount() { 79 | return TOTAL_PAGES * MIN_LOOPS; 80 | } 81 | 82 | }; -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/GalleryWidget/InfinityUrlAdapter.java: -------------------------------------------------------------------------------- 1 | package ru.truba.touchgallery.GalleryWidget; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.ViewGroup; 6 | import android.widget.ImageView; 7 | 8 | import java.util.List; 9 | 10 | import ru.truba.touchgallery.TouchView.UrlTouchImageView; 11 | 12 | /** 13 | * Created by fabio on 28/05/14. 14 | */ 15 | public class InfinityUrlAdapter extends BasePagerAdapter { 16 | 17 | private int TOTAL_PAGES = -1; 18 | private int MIN_LOOPS = 1000; 19 | // You can choose a bigger number for LOOPS, but you know, nobody will fling 20 | // more than 1000 times just in order to test your "infinite" ViewPager :D 21 | public int FIRST_PAGE = 1; 22 | private ImageView.ScaleType mScaleType = null; 23 | 24 | public InfinityUrlAdapter(Context context, List resources) { 25 | super(context, resources); 26 | TOTAL_PAGES = resources.size(); 27 | FIRST_PAGE = TOTAL_PAGES * MIN_LOOPS / 2; 28 | } 29 | 30 | 31 | @Override 32 | public void setPrimaryItem(ViewGroup container, int position, Object object) { 33 | super.setPrimaryItem(container, FIRST_PAGE/*position*/, object); 34 | ((GalleryViewPager)container).mCurrentView = ((UrlTouchImageView)object).getImageView(); 35 | } 36 | 37 | @Override 38 | public Object instantiateItem(ViewGroup collection, int position) { 39 | 40 | position = position % TOTAL_PAGES; 41 | final UrlTouchImageView iv = new UrlTouchImageView(mContext); 42 | iv.setUrl(mResources.get(position)); 43 | iv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 44 | if(mScaleType != null) 45 | iv.setScaleType(mScaleType); 46 | collection.addView(iv, 0); 47 | return iv; 48 | } 49 | 50 | /** 51 | * Set Scaletype for ImageView 52 | * @param scaletype 53 | */ 54 | public void setScaleTypeForImageView(ImageView.ScaleType scaletype) { 55 | mScaleType = scaletype; 56 | } 57 | 58 | @Override 59 | public int getCount() { 60 | return TOTAL_PAGES * MIN_LOOPS; 61 | } 62 | }; -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/GalleryWidget/UrlPagerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Roman Truba 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery.GalleryWidget; 19 | 20 | import java.util.List; 21 | 22 | import android.content.Context; 23 | import android.view.View; 24 | import android.view.ViewGroup; 25 | import ru.truba.touchgallery.TouchView.UrlTouchImageView; 26 | 27 | 28 | /** 29 | Class wraps URLs to adapter, then it instantiates {@link ru.truba.touchgallery.TouchView.UrlTouchImageView} objects to paging up through them. 30 | */ 31 | public class UrlPagerAdapter extends BasePagerAdapter { 32 | 33 | public UrlPagerAdapter(Context context, List resources) 34 | { 35 | super(context, resources); 36 | } 37 | 38 | @Override 39 | public void setPrimaryItem(ViewGroup container, int position, Object object) { 40 | super.setPrimaryItem(container, position, object); 41 | ((GalleryViewPager)container).mCurrentView = ((UrlTouchImageView)object).getImageView(); 42 | } 43 | 44 | @Override 45 | public Object instantiateItem(ViewGroup collection, final int position){ 46 | final UrlTouchImageView iv = new UrlTouchImageView(mContext); 47 | iv.setUrl(mResources.get(position)); 48 | iv.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 49 | 50 | collection.addView(iv, 0); 51 | return iv; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/TouchView/EclairMotionEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 Robert Foss 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery.TouchView; 19 | 20 | import android.view.MotionEvent; 21 | 22 | public class EclairMotionEvent extends WrapMotionEvent { 23 | 24 | protected EclairMotionEvent(MotionEvent event) { 25 | super(event); 26 | } 27 | 28 | public float getX(int pointerIndex) { 29 | return event.getX(pointerIndex); 30 | } 31 | 32 | public float getY(int pointerIndex) { 33 | return event.getY(pointerIndex); 34 | } 35 | 36 | public int getPointerCount() { 37 | return event.getPointerCount(); 38 | } 39 | 40 | public int getPointerId(int pointerIndex) { 41 | return event.getPointerId(pointerIndex); 42 | } 43 | } -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/TouchView/FileTouchImageView.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 Roman Truba 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery.TouchView; 19 | 20 | import android.content.Context; 21 | import android.graphics.Bitmap; 22 | import android.graphics.BitmapFactory; 23 | import android.util.AttributeSet; 24 | import java.io.File; 25 | import java.io.FileInputStream; 26 | 27 | import ru.truba.touchgallery.TouchView.InputStreamWrapper.InputStreamProgressListener; 28 | 29 | public class FileTouchImageView extends UrlTouchImageView 30 | { 31 | 32 | public FileTouchImageView(Context ctx) 33 | { 34 | super(ctx); 35 | 36 | } 37 | public FileTouchImageView(Context ctx, AttributeSet attrs) 38 | { 39 | super(ctx, attrs); 40 | } 41 | 42 | public void setUrl(String imagePath) 43 | { 44 | new ImageLoadTask().execute(imagePath); 45 | } 46 | //No caching load 47 | public class ImageLoadTask extends UrlTouchImageView.ImageLoadTask 48 | { 49 | @Override 50 | protected Bitmap doInBackground(String... strings) { 51 | String path = strings[0]; 52 | Bitmap bm = null; 53 | try { 54 | File file = new File(path); 55 | FileInputStream fis = new FileInputStream(file); 56 | InputStreamWrapper bis = new InputStreamWrapper(fis, 8192, file.length()); 57 | bis.setProgressListener(new InputStreamProgressListener() 58 | { 59 | @Override 60 | public void onProgress(float progressValue, long bytesLoaded, 61 | long bytesTotal) 62 | { 63 | publishProgress((int)(progressValue * 100)); 64 | } 65 | }); 66 | bm = BitmapFactory.decodeStream(bis); 67 | bis.close(); 68 | } catch (Exception e) { 69 | e.printStackTrace(); 70 | } 71 | return bm; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/TouchView/InputStreamWrapper.java: -------------------------------------------------------------------------------- 1 | package ru.truba.touchgallery.TouchView; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | 7 | public class InputStreamWrapper extends BufferedInputStream 8 | { 9 | protected long mContentLen, mBytesLoaded; 10 | protected InputStreamProgressListener mProgressListener; 11 | public InputStreamWrapper(InputStream in, int size, long contentLen) 12 | { 13 | super(in, size); 14 | mContentLen = contentLen; 15 | mBytesLoaded = 0; 16 | } 17 | 18 | @Override 19 | public synchronized int read(byte[] buffer, int offset, int byteCount) 20 | throws IOException 21 | { 22 | mBytesLoaded += byteCount; 23 | if (mProgressListener != null) 24 | { 25 | mProgressListener.onProgress(mBytesLoaded * 1.0f / mContentLen, mBytesLoaded, mContentLen); 26 | } 27 | return super.read(buffer, offset, byteCount); 28 | } 29 | 30 | public void setProgressListener(InputStreamProgressListener listener) 31 | { 32 | mProgressListener = listener; 33 | } 34 | 35 | public static interface InputStreamProgressListener 36 | { 37 | public void onProgress(float progressValue, long bytesLoaded, long bytesTotal); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/TouchView/TouchImageView.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 Robert Foss, Roman Truba 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery.TouchView; 19 | 20 | import java.lang.ref.WeakReference; 21 | import java.util.Timer; 22 | import java.util.TimerTask; 23 | 24 | import android.annotation.SuppressLint; 25 | import android.content.Context; 26 | import android.graphics.Bitmap; 27 | import android.graphics.Canvas; 28 | import android.graphics.Matrix; 29 | import android.graphics.PointF; 30 | import android.os.Build; 31 | import android.os.Handler; 32 | import android.os.Message; 33 | import android.util.AttributeSet; 34 | import android.util.FloatMath; 35 | import android.view.MotionEvent; 36 | import android.view.ScaleGestureDetector; 37 | import android.view.View; 38 | import android.widget.ImageView; 39 | 40 | @SuppressLint("NewApi") 41 | public class TouchImageView extends ImageView { 42 | 43 | private int positionForTouchImageView = -1; 44 | 45 | // private static final String TAG = "Touch"; 46 | // These matrices will be used to move and zoom image 47 | Matrix matrix = new Matrix(); 48 | Matrix savedMatrix = new Matrix(); 49 | 50 | static final long DOUBLE_PRESS_INTERVAL = 600; 51 | static final float FRICTION = 0.9f; 52 | 53 | // We can be in one of these 4 states 54 | static final int NONE = 0; 55 | static final int DRAG = 1; 56 | static final int ZOOM = 2; 57 | static final int CLICK = 10; 58 | int mode = NONE; 59 | 60 | float redundantXSpace, redundantYSpace; 61 | float right, bottom, origWidth, origHeight, bmWidth, bmHeight; 62 | float width, height; 63 | PointF last = new PointF(); 64 | PointF mid = new PointF(); 65 | PointF start = new PointF(); 66 | float[] m; 67 | float matrixX, matrixY; 68 | 69 | float saveScale = 1f; 70 | float minScale = 1f; 71 | float maxScale = 3f; 72 | float oldDist = 1f; 73 | 74 | PointF lastDelta = new PointF(0, 0); 75 | float velocity = 0; 76 | 77 | long lastPressTime = 0, lastDragTime = 0; 78 | boolean allowInert = false; 79 | 80 | private Context mContext; 81 | private Timer mClickTimer; 82 | private OnClickListener mOnClickListener; 83 | private Object mScaleDetector; 84 | private Handler mTimerHandler = null; 85 | 86 | // Scale mode on DoubleTap 87 | private boolean zoomToOriginalSize = false; 88 | 89 | public boolean isZoomToOriginalSize() { 90 | return this.zoomToOriginalSize; 91 | } 92 | 93 | public void setZoomToOriginalSize(boolean zoomToOriginalSize) { 94 | this.zoomToOriginalSize = zoomToOriginalSize; 95 | } 96 | 97 | public boolean onLeftSide = false, onTopSide = false, onRightSide = false, onBottomSide = false; 98 | 99 | public TouchImageView(Context context) { 100 | super(context); 101 | super.setClickable(true); 102 | this.mContext = context; 103 | 104 | init(); 105 | } 106 | public TouchImageView(Context context, AttributeSet attrs) 107 | { 108 | super(context, attrs); 109 | super.setClickable(true); 110 | this.mContext = context; 111 | 112 | init(); 113 | } 114 | 115 | protected void init() 116 | { 117 | mTimerHandler = new TimeHandler(this); 118 | matrix.setTranslate(1f, 1f); 119 | m = new float[9]; 120 | setImageMatrix(matrix); 121 | setScaleType(ScaleType.MATRIX); 122 | if (Build.VERSION.SDK_INT >= 8) 123 | { 124 | mScaleDetector = new ScaleGestureDetector(mContext, new ScaleListener()); 125 | } 126 | setOnTouchListener(new OnTouchListener() { 127 | @Override 128 | public boolean onTouch(View v, MotionEvent rawEvent) { 129 | WrapMotionEvent event = WrapMotionEvent.wrap(rawEvent); 130 | if (mScaleDetector != null) 131 | { 132 | ((ScaleGestureDetector)mScaleDetector).onTouchEvent(rawEvent); 133 | } 134 | fillMatrixXY(); 135 | PointF curr = new PointF(event.getX(), event.getY()); 136 | 137 | switch (event.getAction() & MotionEvent.ACTION_MASK) { 138 | case MotionEvent.ACTION_DOWN: 139 | allowInert = false; 140 | savedMatrix.set(matrix); 141 | last.set(event.getX(), event.getY()); 142 | start.set(last); 143 | mode = DRAG; 144 | 145 | break; 146 | case MotionEvent.ACTION_POINTER_DOWN: 147 | oldDist = spacing(event); 148 | //Log.d(TAG, "oldDist=" + oldDist); 149 | if (oldDist > 10f) { 150 | savedMatrix.set(matrix); 151 | midPoint(mid, event); 152 | mode = ZOOM; 153 | //Log.d(TAG, "mode=ZOOM"); 154 | } 155 | break; 156 | case MotionEvent.ACTION_UP: 157 | allowInert = true; 158 | mode = NONE; 159 | int xDiff = (int) Math.abs(event.getX() - start.x); 160 | int yDiff = (int) Math.abs(event.getY() - start.y); 161 | 162 | if (xDiff < CLICK && yDiff < CLICK) { 163 | 164 | 165 | //Perform scale on double click 166 | long pressTime = System.currentTimeMillis(); 167 | if (pressTime - lastPressTime <= DOUBLE_PRESS_INTERVAL) { 168 | if (mClickTimer != null) mClickTimer.cancel(); 169 | if (saveScale == 1) 170 | { 171 | final float targetScale = maxScale / saveScale; 172 | matrix.postScale(targetScale, targetScale, start.x, start.y); 173 | saveScale = maxScale; 174 | } 175 | else 176 | { 177 | matrix.postScale(minScale / saveScale, minScale / saveScale, width / 2, height / 2); 178 | saveScale = minScale; 179 | } 180 | calcPadding(); 181 | checkAndSetTranslate(0, 0); 182 | lastPressTime = 0; 183 | } 184 | else { 185 | lastPressTime = pressTime; 186 | mClickTimer = new Timer(); 187 | mClickTimer.schedule(new Task(), 300); 188 | } 189 | if (saveScale == minScale) { 190 | scaleMatrixToBounds(); 191 | } 192 | } 193 | 194 | break; 195 | 196 | case MotionEvent.ACTION_POINTER_UP: 197 | mode = NONE; 198 | velocity = 0; 199 | savedMatrix.set(matrix); 200 | oldDist = spacing(event); 201 | //Log.d(TAG, "mode=NONE"); 202 | break; 203 | 204 | case MotionEvent.ACTION_MOVE: 205 | allowInert = false; 206 | if (mode == DRAG) { 207 | float deltaX = curr.x - last.x; 208 | float deltaY = curr.y - last.y; 209 | 210 | long dragTime = System.currentTimeMillis(); 211 | 212 | velocity = (float)distanceBetween(curr, last) / (dragTime - lastDragTime) * FRICTION; 213 | lastDragTime = dragTime; 214 | 215 | checkAndSetTranslate(deltaX, deltaY); 216 | lastDelta.set(deltaX, deltaY); 217 | last.set(curr.x, curr.y); 218 | } 219 | else if (mScaleDetector == null && mode == ZOOM) { 220 | float newDist = spacing(event); 221 | if (rawEvent.getPointerCount() < 2) break; 222 | //There is one serious trouble: when you scaling with two fingers, then pick up first finger of gesture, ACTION_MOVE being called. 223 | //Magic number 50 for this case 224 | if (10 > Math.abs(oldDist - newDist) || Math.abs(oldDist - newDist) > 50) break; 225 | float mScaleFactor = newDist / oldDist; 226 | oldDist = newDist; 227 | 228 | float origScale = saveScale; 229 | saveScale *= mScaleFactor; 230 | if (saveScale > maxScale) { 231 | saveScale = maxScale; 232 | mScaleFactor = maxScale / origScale; 233 | } else if (saveScale < minScale) { 234 | saveScale = minScale; 235 | mScaleFactor = minScale / origScale; 236 | } 237 | 238 | calcPadding(); 239 | if (origWidth * saveScale <= width || origHeight * saveScale <= height) { 240 | matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2); 241 | if (mScaleFactor < 1) { 242 | fillMatrixXY(); 243 | if (mScaleFactor < 1) { 244 | scaleMatrixToBounds(); 245 | } 246 | } 247 | } else { 248 | PointF mid = midPointF(event); 249 | matrix.postScale(mScaleFactor, mScaleFactor, mid.x, mid.y); 250 | fillMatrixXY(); 251 | if (mScaleFactor < 1) { 252 | if (matrixX < -right) 253 | matrix.postTranslate(-(matrixX + right), 0); 254 | else if (matrixX > 0) 255 | matrix.postTranslate(-matrixX, 0); 256 | if (matrixY < -bottom) 257 | matrix.postTranslate(0, -(matrixY + bottom)); 258 | else if (matrixY > 0) 259 | matrix.postTranslate(0, -matrixY); 260 | } 261 | } 262 | checkSiding(); 263 | } 264 | break; 265 | } 266 | 267 | setImageMatrix(matrix); 268 | invalidate(); 269 | return false; 270 | } 271 | }); 272 | } 273 | public void resetScale() 274 | { 275 | fillMatrixXY(); 276 | matrix.postScale(minScale / saveScale, minScale / saveScale, width / 2, height / 2); 277 | saveScale = minScale; 278 | 279 | calcPadding(); 280 | checkAndSetTranslate(0, 0); 281 | 282 | scaleMatrixToBounds(); 283 | 284 | setImageMatrix(matrix); 285 | invalidate(); 286 | } 287 | public boolean pagerCanScroll() 288 | { 289 | if (mode != NONE) return false; 290 | return saveScale == minScale; 291 | } 292 | 293 | @Override 294 | protected void onDraw(Canvas canvas) { 295 | super.onDraw(canvas); 296 | if (!allowInert) return; 297 | final float deltaX = lastDelta.x * velocity, deltaY = lastDelta.y * velocity; 298 | if (deltaX > width || deltaY > height) 299 | { 300 | return; 301 | } 302 | velocity *= FRICTION; 303 | if (Math.abs(deltaX) < 0.1 && Math.abs(deltaY) < 0.1) return; 304 | checkAndSetTranslate(deltaX, deltaY); 305 | setImageMatrix(matrix); 306 | } 307 | 308 | private void checkAndSetTranslate(float deltaX, float deltaY) 309 | { 310 | float scaleWidth = Math.round(origWidth * saveScale); 311 | float scaleHeight = Math.round(origHeight * saveScale); 312 | fillMatrixXY(); 313 | if (scaleWidth < width) { 314 | deltaX = 0; 315 | if (matrixY + deltaY > 0) 316 | deltaY = -matrixY; 317 | else if (matrixY + deltaY < -bottom) 318 | deltaY = -(matrixY + bottom); 319 | } else if (scaleHeight < height) { 320 | deltaY = 0; 321 | if (matrixX + deltaX > 0) 322 | deltaX = -matrixX; 323 | else if (matrixX + deltaX < -right) 324 | deltaX = -(matrixX + right); 325 | } 326 | else { 327 | if (matrixX + deltaX > 0) 328 | deltaX = -matrixX; 329 | else if (matrixX + deltaX < -right) 330 | deltaX = -(matrixX + right); 331 | 332 | if (matrixY + deltaY > 0) 333 | deltaY = -matrixY; 334 | else if (matrixY + deltaY < -bottom) 335 | deltaY = -(matrixY + bottom); 336 | } 337 | matrix.postTranslate(deltaX, deltaY); 338 | checkSiding(); 339 | } 340 | private void checkSiding() 341 | { 342 | fillMatrixXY(); 343 | //Log.d(TAG, "x: " + matrixX + " y: " + matrixY + " left: " + right / 2 + " top:" + bottom / 2); 344 | float scaleWidth = Math.round(origWidth * saveScale); 345 | float scaleHeight = Math.round(origHeight * saveScale); 346 | onLeftSide = onRightSide = onTopSide = onBottomSide = false; 347 | if (-matrixX < 10.0f ) onLeftSide = true; 348 | //Log.d("GalleryViewPager", String.format("ScaleW: %f; W: %f, MatrixX: %f", scaleWidth, width, matrixX)); 349 | if ((scaleWidth >= width && (matrixX + scaleWidth - width) < 10) || 350 | (scaleWidth <= width && -matrixX + scaleWidth <= width)) onRightSide = true; 351 | if (-matrixY < 10.0f) onTopSide = true; 352 | if (Math.abs(-matrixY + height - scaleHeight) < 10.0f) onBottomSide = true; 353 | } 354 | private void calcPadding() 355 | { 356 | right = width * saveScale - width - (2 * redundantXSpace * saveScale); 357 | bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); 358 | } 359 | private void fillMatrixXY() 360 | { 361 | matrix.getValues(m); 362 | matrixX = m[Matrix.MTRANS_X]; 363 | matrixY = m[Matrix.MTRANS_Y]; 364 | } 365 | private void scaleMatrixToBounds() 366 | { 367 | if (Math.abs(matrixX + right / 2) > 0.5f) 368 | matrix.postTranslate(-(matrixX + right / 2), 0); 369 | if (Math.abs(matrixY + bottom / 2) > 0.5f) 370 | matrix.postTranslate(0, -(matrixY + bottom / 2)); 371 | } 372 | @Override 373 | public void setImageBitmap(Bitmap bm) { 374 | super.setImageBitmap(bm); 375 | bmWidth = bm.getWidth(); 376 | bmHeight = bm.getHeight(); 377 | } 378 | @Override 379 | protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) 380 | { 381 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 382 | width = MeasureSpec.getSize(widthMeasureSpec); 383 | height = MeasureSpec.getSize(heightMeasureSpec); 384 | //Fit to screen. 385 | float scale; 386 | float scaleX = width / bmWidth; 387 | float scaleY = height / bmHeight; 388 | scale = Math.min(scaleX, scaleY); 389 | matrix.setScale(scale, scale); 390 | //minScale = scale; 391 | setImageMatrix(matrix); 392 | saveScale = 1f; 393 | 394 | // Center the image 395 | redundantYSpace = height - (scale * bmHeight) ; 396 | redundantXSpace = width - (scale * bmWidth); 397 | redundantYSpace /= (float)2; 398 | redundantXSpace /= (float)2; 399 | 400 | matrix.postTranslate(redundantXSpace, redundantYSpace); 401 | 402 | origWidth = width - 2 * redundantXSpace; 403 | origHeight = height - 2 * redundantYSpace; 404 | calcPadding(); 405 | setImageMatrix(matrix); 406 | } 407 | 408 | private double distanceBetween(PointF left, PointF right) 409 | { 410 | return Math.sqrt(Math.pow(left.x - right.x, 2) + Math.pow(left.y - right.y, 2)); 411 | } 412 | /** Determine the space between the first two fingers */ 413 | private float spacing(WrapMotionEvent event) { 414 | // ... 415 | float x = event.getX(0) - event.getX(1); 416 | float y = event.getY(0) - event.getY(1); 417 | return FloatMath.sqrt(x * x + y * y); 418 | } 419 | 420 | /** Calculate the mid point of the first two fingers */ 421 | private void midPoint(PointF point, WrapMotionEvent event) { 422 | // ... 423 | float x = event.getX(0) + event.getX(1); 424 | float y = event.getY(0) + event.getY(1); 425 | point.set(x / 2, y / 2); 426 | } 427 | private PointF midPointF(WrapMotionEvent event) { 428 | // ... 429 | float x = event.getX(0) + event.getX(1); 430 | float y = event.getY(0) + event.getY(1); 431 | return new PointF(x / 2, y / 2); 432 | } 433 | 434 | @Override 435 | public void setOnClickListener(OnClickListener l) { 436 | mOnClickListener = l; 437 | } 438 | 439 | 440 | private class Task extends TimerTask { 441 | public void run() { 442 | mTimerHandler.sendEmptyMessage(0); 443 | } 444 | } 445 | 446 | private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 447 | @Override 448 | public boolean onScaleBegin(ScaleGestureDetector detector) { 449 | mode = ZOOM; 450 | return true; 451 | } 452 | 453 | @Override 454 | public boolean onScale(ScaleGestureDetector detector) { 455 | float mScaleFactor = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05); 456 | float origScale = saveScale; 457 | saveScale *= mScaleFactor; 458 | if (saveScale > maxScale) { 459 | saveScale = maxScale; 460 | mScaleFactor = maxScale / origScale; 461 | } else if (saveScale < minScale) { 462 | saveScale = minScale; 463 | mScaleFactor = minScale / origScale; 464 | } 465 | right = width * saveScale - width - (2 * redundantXSpace * saveScale); 466 | bottom = height * saveScale - height - (2 * redundantYSpace * saveScale); 467 | if (origWidth * saveScale <= width || origHeight * saveScale <= height) { 468 | matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2); 469 | if (mScaleFactor < 1) { 470 | matrix.getValues(m); 471 | float x = m[Matrix.MTRANS_X]; 472 | float y = m[Matrix.MTRANS_Y]; 473 | if (mScaleFactor < 1) { 474 | if (Math.round(origWidth * saveScale) < width) { 475 | if (y < -bottom) 476 | matrix.postTranslate(0, -(y + bottom)); 477 | else if (y > 0) 478 | matrix.postTranslate(0, -y); 479 | } else { 480 | if (x < -right) 481 | matrix.postTranslate(-(x + right), 0); 482 | else if (x > 0) 483 | matrix.postTranslate(-x, 0); 484 | } 485 | } 486 | } 487 | } else { 488 | matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY()); 489 | matrix.getValues(m); 490 | float x = m[Matrix.MTRANS_X]; 491 | float y = m[Matrix.MTRANS_Y]; 492 | if (mScaleFactor < 1) { 493 | if (x < -right) 494 | matrix.postTranslate(-(x + right), 0); 495 | else if (x > 0) 496 | matrix.postTranslate(-x, 0); 497 | if (y < -bottom) 498 | matrix.postTranslate(0, -(y + bottom)); 499 | else if (y > 0) 500 | matrix.postTranslate(0, -y); 501 | } 502 | } 503 | return true; 504 | 505 | } 506 | } 507 | static class TimeHandler extends Handler { 508 | private final WeakReference mService; 509 | 510 | TimeHandler(TouchImageView view) { 511 | mService = new WeakReference(view); 512 | 513 | } 514 | @Override 515 | public void handleMessage(Message msg) 516 | { 517 | mService.get().performClick(); 518 | if (mService.get().mOnClickListener != null) mService.get().mOnClickListener.onClick(mService.get()); 519 | } 520 | } 521 | }; -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/TouchView/UrlTouchImageView.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 Roman Truba 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery.TouchView; 19 | 20 | import android.content.Context; 21 | import android.graphics.Bitmap; 22 | import android.graphics.BitmapFactory; 23 | import android.os.AsyncTask; 24 | import android.util.AttributeSet; 25 | import android.widget.ImageView.ScaleType; 26 | import android.widget.ProgressBar; 27 | import android.widget.RelativeLayout; 28 | 29 | import java.io.InputStream; 30 | import java.net.URL; 31 | import java.net.URLConnection; 32 | 33 | import ru.truba.touchgallery.R; 34 | import ru.truba.touchgallery.TouchView.InputStreamWrapper.InputStreamProgressListener; 35 | 36 | public class UrlTouchImageView extends RelativeLayout { 37 | protected ProgressBar mProgressBar; 38 | protected TouchImageView mImageView; 39 | 40 | protected Context mContext; 41 | 42 | public UrlTouchImageView(Context ctx) 43 | { 44 | super(ctx); 45 | mContext = ctx; 46 | init(); 47 | 48 | } 49 | public UrlTouchImageView(Context ctx, AttributeSet attrs) 50 | { 51 | super(ctx, attrs); 52 | mContext = ctx; 53 | init(); 54 | } 55 | public TouchImageView getImageView() { return mImageView; } 56 | 57 | @SuppressWarnings("deprecation") 58 | protected void init() { 59 | mImageView = new TouchImageView(mContext); 60 | LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT); 61 | mImageView.setLayoutParams(params); 62 | this.addView(mImageView); 63 | mImageView.setVisibility(GONE); 64 | 65 | mProgressBar = new ProgressBar(mContext, null, android.R.attr.progressBarStyleHorizontal); 66 | params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); 67 | params.addRule(RelativeLayout.CENTER_VERTICAL); 68 | params.setMargins(30, 0, 30, 0); 69 | mProgressBar.setLayoutParams(params); 70 | mProgressBar.setIndeterminate(false); 71 | mProgressBar.setMax(100); 72 | this.addView(mProgressBar); 73 | } 74 | 75 | public void setUrl(String imageUrl) 76 | { 77 | new ImageLoadTask().execute(imageUrl); 78 | } 79 | 80 | public void setScaleType(ScaleType scaleType) { 81 | mImageView.setScaleType(scaleType); 82 | } 83 | 84 | //No caching load 85 | public class ImageLoadTask extends AsyncTask 86 | { 87 | @Override 88 | protected Bitmap doInBackground(String... strings) { 89 | String url = strings[0]; 90 | Bitmap bm = null; 91 | try { 92 | URL aURL = new URL(url); 93 | URLConnection conn = aURL.openConnection(); 94 | conn.connect(); 95 | InputStream is = conn.getInputStream(); 96 | int totalLen = conn.getContentLength(); 97 | InputStreamWrapper bis = new InputStreamWrapper(is, 8192, totalLen); 98 | bis.setProgressListener(new InputStreamProgressListener() 99 | { 100 | @Override 101 | public void onProgress(float progressValue, long bytesLoaded, 102 | long bytesTotal) 103 | { 104 | publishProgress((int)(progressValue * 100)); 105 | } 106 | }); 107 | bm = BitmapFactory.decodeStream(bis); 108 | bis.close(); 109 | is.close(); 110 | } catch (Exception e) { 111 | e.printStackTrace(); 112 | } 113 | return bm; 114 | } 115 | 116 | @Override 117 | protected void onPostExecute(Bitmap bitmap) { 118 | if (bitmap == null) 119 | { 120 | mImageView.setScaleType(ScaleType.CENTER); 121 | bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.no_photo); 122 | mImageView.setImageBitmap(bitmap); 123 | } 124 | else 125 | { 126 | mImageView.setScaleType(ScaleType.MATRIX); 127 | mImageView.setImageBitmap(bitmap); 128 | } 129 | mImageView.setVisibility(VISIBLE); 130 | mProgressBar.setVisibility(GONE); 131 | } 132 | 133 | @Override 134 | protected void onProgressUpdate(Integer... values) 135 | { 136 | mProgressBar.setProgress(values[0]); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /library/src/ru/truba/touchgallery/TouchView/WrapMotionEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 Robert Foss 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to 7 | permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial 10 | portions of the Software. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 13 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 15 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH 16 | THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | */ 18 | package ru.truba.touchgallery.TouchView; 19 | 20 | import android.view.MotionEvent; 21 | 22 | public class WrapMotionEvent { 23 | protected MotionEvent event; 24 | 25 | 26 | 27 | 28 | protected WrapMotionEvent(MotionEvent event) { 29 | this.event = event; 30 | } 31 | 32 | static public WrapMotionEvent wrap(MotionEvent event) { 33 | try { 34 | return new EclairMotionEvent(event); 35 | } catch (VerifyError e) { 36 | return new WrapMotionEvent(event); 37 | } 38 | } 39 | 40 | 41 | 42 | public int getAction() { 43 | return event.getAction(); 44 | } 45 | 46 | public float getX() { 47 | return event.getX(); 48 | } 49 | 50 | public float getX(int pointerIndex) { 51 | verifyPointerIndex(pointerIndex); 52 | return getX(); 53 | } 54 | 55 | public float getY() { 56 | return event.getY(); 57 | } 58 | 59 | public float getY(int pointerIndex) { 60 | verifyPointerIndex(pointerIndex); 61 | return getY(); 62 | } 63 | 64 | public int getPointerCount() { 65 | return 1; 66 | } 67 | 68 | public int getPointerId(int pointerIndex) { 69 | verifyPointerIndex(pointerIndex); 70 | return 0; 71 | } 72 | 73 | private void verifyPointerIndex(int pointerIndex) { 74 | if (pointerIndex > 0) { 75 | throw new IllegalArgumentException( 76 | "Invalid pointer index for Donut/Cupcake"); 77 | } 78 | } 79 | 80 | } --------------------------------------------------------------------------------