aboutsummaryrefslogtreecommitdiff
path: root/sample/src/main
diff options
context:
space:
mode:
authorDavid Morrissey <davemorrissey@gmail.com>2017-11-02 18:59:25 +0000
committerDavid Morrissey <davemorrissey@gmail.com>2017-11-02 18:59:26 +0000
commit0cae9eb5b2b68ad2bea9586036500925018e8c8b (patch)
tree1361e0dce27fc9a2cdc40594c982032e38ec20ea /sample/src/main
parentc930ef77f57c0619c10893696452b94e75e0dd23 (diff)
downloadsubsampling-scale-image-view-0cae9eb5b2b68ad2bea9586036500925018e8c8b.tar.gz
Updated to current standard project structure
Diffstat (limited to 'sample/src/main')
-rw-r--r--sample/src/main/AndroidManifest.xml28
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/AbstractFragmentsActivity.java98
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/AbstractPagesActivity.java115
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/MainActivity.java95
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/Page.java37
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/animation/AnimationActivity.java87
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/basicfeatures/BasicFeaturesActivity.java52
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/configuration/ConfigurationActivity.java110
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/eventhandling/EventHandlingActivity.java57
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/eventhandlingadvanced/AdvancedEventHandlingActivity.java94
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionActivity.java67
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionCircleFragment.java46
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionFreehandFragment.java46
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionPinFragment.java45
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/CircleView.java72
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/FreehandView.java157
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/PinView.java76
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayActivity.java60
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayLargeFragment.java43
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayRegionFragment.java48
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayRotateFragment.java50
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/VerticalViewPager.java67
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/ViewPagerActivity.java98
-rw-r--r--sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/ViewPagerFragment.java69
-rw-r--r--sample/src/main/res/drawable-hdpi/launcher.pngbin0 -> 3019 bytes
-rw-r--r--sample/src/main/res/drawable-nodpi/button_standout_inactive.xml4
-rw-r--r--sample/src/main/res/drawable-nodpi/button_standout_pressed.xml4
-rw-r--r--sample/src/main/res/drawable-nodpi/button_transparent_pressed.xml4
-rw-r--r--sample/src/main/res/drawable-nodpi/buttonstate_standout.xml10
-rw-r--r--sample/src/main/res/drawable-nodpi/buttonstate_transparent.xml10
-rw-r--r--sample/src/main/res/drawable-nodpi/pushpin_blue.pngbin0 -> 8102 bytes
-rw-r--r--sample/src/main/res/drawable-nodpi/transparent.xml4
-rw-r--r--sample/src/main/res/drawable-xhdpi/daffy.gifbin0 -> 4533 bytes
-rw-r--r--sample/src/main/res/drawable-xhdpi/launcher.pngbin0 -> 4796 bytes
-rw-r--r--sample/src/main/res/drawable-xhdpi/next.pngbin0 -> 1737 bytes
-rw-r--r--sample/src/main/res/drawable-xhdpi/play.pngbin0 -> 1620 bytes
-rw-r--r--sample/src/main/res/drawable-xhdpi/previous.pngbin0 -> 1734 bytes
-rw-r--r--sample/src/main/res/drawable-xhdpi/reset.pngbin0 -> 2335 bytes
-rw-r--r--sample/src/main/res/drawable-xhdpi/rotate.pngbin0 -> 2432 bytes
-rw-r--r--sample/src/main/res/drawable-xxhdpi/launcher.pngbin0 -> 6605 bytes
-rw-r--r--sample/src/main/res/layout/animation_activity.xml24
-rw-r--r--sample/src/main/res/layout/extension_circle_fragment.xml19
-rw-r--r--sample/src/main/res/layout/extension_freehand_fragment.xml25
-rw-r--r--sample/src/main/res/layout/extension_pin_fragment.xml19
-rw-r--r--sample/src/main/res/layout/fragments_activity.xml5
-rw-r--r--sample/src/main/res/layout/imagedisplay_large_fragment.xml19
-rw-r--r--sample/src/main/res/layout/imagedisplay_region_fragment.xml25
-rw-r--r--sample/src/main/res/layout/imagedisplay_rotate_fragment.xml25
-rw-r--r--sample/src/main/res/layout/main.xml75
-rw-r--r--sample/src/main/res/layout/pages_activity.xml18
-rw-r--r--sample/src/main/res/layout/view_pager.xml20
-rw-r--r--sample/src/main/res/layout/view_pager_page.xml5
-rw-r--r--sample/src/main/res/values/colors.xml5
-rw-r--r--sample/src/main/res/values/strings.xml184
-rw-r--r--sample/src/main/res/values/style.xml78
55 files changed, 2299 insertions, 0 deletions
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..db9d4e6
--- /dev/null
+++ b/sample/src/main/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.davemorrissey.labs.subscaleview.sample"
+ android:versionCode="4"
+ android:versionName="3.1.0"
+ android:hardwareAccelerated="true">
+<uses-sdk android:minSdkVersion="17" android:targetSdkVersion="26"/>
+<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove"/>
+<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" tools:node="remove"/>
+<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:node="remove"/>
+<application android:label="@string/app.name" android:theme="@style/sampleTheme" android:icon="@drawable/launcher" android:allowBackup="false">
+ <activity android:name=".MainActivity" android:label="Scale View Demo">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="android.intent.category.LAUNCHER"/>
+ </intent-filter>
+ </activity>
+ <activity android:name=".basicfeatures.BasicFeaturesActivity"/>
+ <activity android:name=".imagedisplay.ImageDisplayActivity"/>
+ <activity android:name=".eventhandling.EventHandlingActivity"/>
+ <activity android:name=".eventhandlingadvanced.AdvancedEventHandlingActivity"/>
+ <activity android:name=".viewpager.ViewPagerActivity"/>
+ <activity android:name=".animation.AnimationActivity"/>
+ <activity android:name=".extension.ExtensionActivity"/>
+ <activity android:name=".configuration.ConfigurationActivity"/>
+</application>
+</manifest>
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/AbstractFragmentsActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/AbstractFragmentsActivity.java
new file mode 100644
index 0000000..1bbe522
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/AbstractFragmentsActivity.java
@@ -0,0 +1,98 @@
+/*
+Copyright 2017 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample;
+
+import android.app.ActionBar;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentActivity;
+import android.view.MenuItem;
+
+import java.util.List;
+
+public abstract class AbstractFragmentsActivity extends FragmentActivity {
+
+ private static final String BUNDLE_PAGE = "page";
+
+ private int page;
+
+ private final int title;
+ private final int layout;
+ private final List<Page> notes;
+
+ protected abstract void onPageChanged(int page);
+
+ protected AbstractFragmentsActivity(int title, int layout, List<Page> notes) {
+ this.title = title;
+ this.layout = layout;
+ this.notes = notes;
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(layout);
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setTitle(getString(title));
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+ if (savedInstanceState != null && savedInstanceState.containsKey(BUNDLE_PAGE)) {
+ page = savedInstanceState.getInt(BUNDLE_PAGE);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ updateNotes();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(BUNDLE_PAGE, page);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ finish();
+ return true;
+ }
+
+ public void next() {
+ page++;
+ updateNotes();
+ }
+
+ public void previous() {
+ page--;
+ updateNotes();
+ }
+
+ private void updateNotes() {
+ if (page > notes.size() - 1) {
+ return;
+ }
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setSubtitle(notes.get(page).getSubtitle());
+ }
+ onPageChanged(page);
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/AbstractPagesActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/AbstractPagesActivity.java
new file mode 100644
index 0000000..de0711f
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/AbstractPagesActivity.java
@@ -0,0 +1,115 @@
+/*
+Copyright 2017 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample;
+
+import android.app.ActionBar;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.FragmentActivity;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import java.util.List;
+
+public abstract class AbstractPagesActivity extends FragmentActivity {
+
+ private static final String BUNDLE_PAGE = "page";
+
+ private int page;
+
+ private final int title;
+ private final int layout;
+ private final List<Page> notes;
+
+ protected AbstractPagesActivity(int title, int layout, List<Page> notes) {
+ this.title = title;
+ this.layout = layout;
+ this.notes = notes;
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(layout);
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setTitle(getString(title));
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ }
+ findViewById(R.id.next).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { next(); }
+ });
+ findViewById(R.id.previous).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { previous(); }
+ });
+ if (savedInstanceState != null && savedInstanceState.containsKey(BUNDLE_PAGE)) {
+ page = savedInstanceState.getInt(BUNDLE_PAGE);
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ updateNotes();
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putInt(BUNDLE_PAGE, page);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ finish();
+ return true;
+ }
+
+ private void next() {
+ page++;
+ updateNotes();
+ }
+
+ private void previous() {
+ page--;
+ updateNotes();
+ }
+
+ private void updateNotes() {
+ if (page > notes.size() - 1) {
+ return;
+ }
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setSubtitle(notes.get(page).getSubtitle());
+ }
+ ((TextView)findViewById(R.id.note)).setText(notes.get(page).getText());
+ findViewById(R.id.next).setVisibility(page >= notes.size() - 1 ? View.INVISIBLE : View.VISIBLE);
+ findViewById(R.id.previous).setVisibility(page <= 0 ? View.INVISIBLE : View.VISIBLE);
+ onPageChanged(page);
+ }
+
+ protected final int getPage() {
+ return page;
+ }
+
+ protected void onPageChanged(int page) {
+
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/MainActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/MainActivity.java
new file mode 100644
index 0000000..f49bf8f
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/MainActivity.java
@@ -0,0 +1,95 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample;
+
+import android.app.ActionBar;
+import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+import com.davemorrissey.labs.subscaleview.sample.animation.AnimationActivity;
+import com.davemorrissey.labs.subscaleview.sample.basicfeatures.BasicFeaturesActivity;
+import com.davemorrissey.labs.subscaleview.sample.configuration.ConfigurationActivity;
+import com.davemorrissey.labs.subscaleview.sample.eventhandling.EventHandlingActivity;
+import com.davemorrissey.labs.subscaleview.sample.eventhandlingadvanced.AdvancedEventHandlingActivity;
+import com.davemorrissey.labs.subscaleview.sample.extension.ExtensionActivity;
+import com.davemorrissey.labs.subscaleview.sample.imagedisplay.ImageDisplayActivity;
+import com.davemorrissey.labs.subscaleview.sample.viewpager.ViewPagerActivity;
+
+public class MainActivity extends Activity implements View.OnClickListener {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ actionBar.setTitle(R.string.main_title);
+ }
+ setContentView(R.layout.main);
+ findViewById(id.basicFeatures).setOnClickListener(this);
+ findViewById(id.imageDisplay).setOnClickListener(this);
+ findViewById(id.eventHandling).setOnClickListener(this);
+ findViewById(id.advancedEventHandling).setOnClickListener(this);
+ findViewById(id.viewPagerGalleries).setOnClickListener(this);
+ findViewById(id.animation).setOnClickListener(this);
+ findViewById(id.extension).setOnClickListener(this);
+ findViewById(id.configuration).setOnClickListener(this);
+ findViewById(id.github).setOnClickListener(this);
+ findViewById(id.self).setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case id.basicFeatures: startActivity(BasicFeaturesActivity.class); break;
+ case id.imageDisplay: startActivity(ImageDisplayActivity.class); break;
+ case id.eventHandling: startActivity(EventHandlingActivity.class); break;
+ case id.advancedEventHandling: startActivity(AdvancedEventHandlingActivity.class); break;
+ case id.viewPagerGalleries: startActivity(ViewPagerActivity.class); break;
+ case id.animation: startActivity(AnimationActivity.class); break;
+ case id.extension: startActivity(ExtensionActivity.class); break;
+ case id.configuration: startActivity(ConfigurationActivity.class); break;
+ case id.github: openGitHub(); break;
+ case id.self: openSelf(); break;
+ }
+ }
+
+ private void startActivity(Class<? extends Activity> activity) {
+ Intent intent = new Intent(this, activity);
+ startActivity(intent);
+ }
+
+ private void openGitHub() {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setData(Uri.parse("https://github.com/davemorrissey/subsampling-scale-image-view"));
+ startActivity(i);
+ }
+
+ private void openSelf() {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ i.setData(Uri.parse("http://www.davemorrissey.com"));
+ startActivity(i);
+ }
+
+ @Override
+ public void onBackPressed() {
+ moveTaskToBack(true);
+ }
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/Page.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/Page.java
new file mode 100644
index 0000000..f489f6e
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/Page.java
@@ -0,0 +1,37 @@
+/*
+Copyright 2017 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample;
+
+public class Page {
+
+ private final int text;
+
+ private final int subtitle;
+
+ public Page(int subtitle, int text) {
+ this.subtitle = subtitle;
+ this.text = text;
+ }
+
+ public int getText() {
+ return text;
+ }
+
+ public int getSubtitle() {
+ return subtitle;
+ }
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/animation/AnimationActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/animation/AnimationActivity.java
new file mode 100644
index 0000000..008691d
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/animation/AnimationActivity.java
@@ -0,0 +1,87 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.animation;
+
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.View;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.AnimationBuilder;
+import com.davemorrissey.labs.subscaleview.sample.AbstractPagesActivity;
+import com.davemorrissey.labs.subscaleview.sample.Page;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+import com.davemorrissey.labs.subscaleview.sample.extension.views.PinView;
+
+import java.util.Arrays;
+import java.util.Random;
+
+import static com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView.*;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.*;
+import static com.davemorrissey.labs.subscaleview.sample.R.layout.*;
+
+public class AnimationActivity extends AbstractPagesActivity {
+
+ private PinView view;
+
+ public AnimationActivity() {
+ super(animation_title, animation_activity, Arrays.asList(
+ new Page(animation_p1_subtitle, animation_p1_text),
+ new Page(animation_p2_subtitle, animation_p2_text),
+ new Page(animation_p3_subtitle, animation_p3_text),
+ new Page(animation_p4_subtitle, animation_p4_text)
+ ));
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ findViewById(id.play).setOnClickListener(new OnClickListener() {
+ @Override public void onClick(View v) { AnimationActivity.this.play(); }
+ });
+ view = findViewById(id.imageView);
+ view.setImage(ImageSource.asset("squirrel.jpg"));
+ }
+
+ @Override
+ protected void onPageChanged(int page) {
+ if (page == 2) {
+ view.setPanLimit(PAN_LIMIT_CENTER);
+ } else {
+ view.setPanLimit(PAN_LIMIT_INSIDE);
+ }
+ }
+
+ private void play() {
+ Random random = new Random();
+ if (view.isReady()) {
+ float maxScale = view.getMaxScale();
+ float minScale = view.getMinScale();
+ float scale = (random.nextFloat() * (maxScale - minScale)) + minScale;
+ PointF center = new PointF(random.nextInt(view.getSWidth()), random.nextInt(view.getSHeight()));
+ view.setPin(center);
+ AnimationBuilder animationBuilder = view.animateScaleAndCenter(scale, center);
+ if (getPage() == 3) {
+ animationBuilder.withDuration(2000).withEasing(EASE_OUT_QUAD).withInterruptible(false).start();
+ } else {
+ animationBuilder.withDuration(750).start();
+ }
+ }
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/basicfeatures/BasicFeaturesActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/basicfeatures/BasicFeaturesActivity.java
new file mode 100644
index 0000000..a89619a
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/basicfeatures/BasicFeaturesActivity.java
@@ -0,0 +1,52 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.basicfeatures;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.davemorrissey.labs.subscaleview.sample.AbstractPagesActivity;
+import com.davemorrissey.labs.subscaleview.sample.Page;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+
+import java.util.Arrays;
+
+import static com.davemorrissey.labs.subscaleview.sample.R.string.*;
+import static com.davemorrissey.labs.subscaleview.sample.R.layout.*;
+
+public class BasicFeaturesActivity extends AbstractPagesActivity {
+
+ public BasicFeaturesActivity() {
+ super(basic_title, pages_activity, Arrays.asList(
+ new Page(basic_p1_subtitle, basic_p1_text),
+ new Page(basic_p2_subtitle, basic_p2_text),
+ new Page(basic_p3_subtitle, basic_p3_text),
+ new Page(basic_p4_subtitle, basic_p4_text),
+ new Page(basic_p5_subtitle, basic_p5_text)
+ ));
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SubsamplingScaleImageView view = findViewById(id.imageView);
+ view.setImage(ImageSource.asset("pony.jpg"));
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/configuration/ConfigurationActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/configuration/ConfigurationActivity.java
new file mode 100644
index 0000000..39c4b24
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/configuration/ConfigurationActivity.java
@@ -0,0 +1,110 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.configuration;
+
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.davemorrissey.labs.subscaleview.sample.AbstractPagesActivity;
+import com.davemorrissey.labs.subscaleview.sample.Page;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+
+import java.util.Arrays;
+
+import static com.davemorrissey.labs.subscaleview.sample.R.string.*;
+import static com.davemorrissey.labs.subscaleview.sample.R.layout.*;
+
+public class ConfigurationActivity extends AbstractPagesActivity {
+
+ private SubsamplingScaleImageView view;
+
+ public ConfigurationActivity() {
+ super(configuration_title, pages_activity, Arrays.asList(
+ new Page(configuration_p1_subtitle, configuration_p1_text),
+ new Page(configuration_p2_subtitle, configuration_p2_text),
+ new Page(configuration_p3_subtitle, configuration_p3_text),
+ new Page(configuration_p4_subtitle, configuration_p4_text),
+ new Page(configuration_p5_subtitle, configuration_p5_text),
+ new Page(configuration_p6_subtitle, configuration_p6_text),
+ new Page(configuration_p7_subtitle, configuration_p7_text),
+ new Page(configuration_p8_subtitle, configuration_p8_text),
+ new Page(configuration_p9_subtitle, configuration_p9_text),
+ new Page(configuration_p10_subtitle, configuration_p10_text)
+ ));
+ }
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ view = findViewById(id.imageView);
+ view.setImage(ImageSource.asset("eagle.jpg"));
+ }
+
+ @Override
+ protected void onPageChanged(int page) {
+ if (page == 0) {
+ view.setMinimumDpi(50);
+ } else {
+ view.setMaxScale(2F);
+ }
+ if (page == 1) {
+ view.setMinimumTileDpi(50);
+ } else {
+ view.setMinimumTileDpi(500);
+ }
+ if (page == 4) {
+ view.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER);
+ } else if (page == 5) {
+ view.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_CENTER_IMMEDIATE);
+ } else {
+ view.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED);
+ }
+ if (page == 6) {
+ view.setDoubleTapZoomDpi(240);
+ } else {
+ view.setDoubleTapZoomScale(1F);
+ }
+ if (page == 7) {
+ view.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_CENTER);
+ } else if (page == 8) {
+ view.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_OUTSIDE);
+ } else {
+ view.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE);
+ }
+ if (page == 9) {
+ view.setDebug(true);
+ } else {
+ view.setDebug(false);
+ }
+ if (page == 2) {
+ view.setScaleAndCenter(0f, new PointF(2456, 1632));
+ view.setPanEnabled(false);
+ } else {
+ view.setPanEnabled(true);
+ }
+ if (page == 3) {
+ view.setScaleAndCenter(1f, new PointF(2456, 1632));
+ view.setZoomEnabled(false);
+ } else {
+ view.setZoomEnabled(true);
+ }
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/eventhandling/EventHandlingActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/eventhandling/EventHandlingActivity.java
new file mode 100644
index 0000000..bd5613a
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/eventhandling/EventHandlingActivity.java
@@ -0,0 +1,57 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.eventhandling;
+
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Toast;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.davemorrissey.labs.subscaleview.sample.AbstractPagesActivity;
+import com.davemorrissey.labs.subscaleview.sample.Page;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+
+import java.util.Arrays;
+
+import static com.davemorrissey.labs.subscaleview.sample.R.layout.*;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.*;
+
+public class EventHandlingActivity extends AbstractPagesActivity {
+
+ public EventHandlingActivity() {
+ super(event_title, pages_activity, Arrays.asList(
+ new Page(event_p1_subtitle, event_p1_text),
+ new Page(event_p2_subtitle, event_p2_text),
+ new Page(event_p3_subtitle, event_p3_text)
+ ));
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ SubsamplingScaleImageView imageView = findViewById(id.imageView);
+ imageView.setImage(ImageSource.asset("pony.jpg"));
+ imageView.setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { Toast.makeText(v.getContext(), "Clicked", Toast.LENGTH_SHORT).show(); }
+ });
+ imageView.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override public boolean onLongClick(View v) { Toast.makeText(v.getContext(), "Long clicked", Toast.LENGTH_SHORT).show(); return true; }
+ });
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/eventhandlingadvanced/AdvancedEventHandlingActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/eventhandlingadvanced/AdvancedEventHandlingActivity.java
new file mode 100644
index 0000000..e2c34fd
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/eventhandlingadvanced/AdvancedEventHandlingActivity.java
@@ -0,0 +1,94 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.eventhandlingadvanced;
+
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.Toast;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.davemorrissey.labs.subscaleview.sample.AbstractPagesActivity;
+import com.davemorrissey.labs.subscaleview.sample.Page;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+
+import java.util.Arrays;
+
+import static com.davemorrissey.labs.subscaleview.sample.R.string.*;
+import static com.davemorrissey.labs.subscaleview.sample.R.layout.*;
+
+public class AdvancedEventHandlingActivity extends AbstractPagesActivity {
+
+ public AdvancedEventHandlingActivity() {
+ super(advancedevent_title, pages_activity, Arrays.asList(
+ new Page(advancedevent_p1_subtitle, advancedevent_p1_text),
+ new Page(advancedevent_p2_subtitle, advancedevent_p2_text),
+ new Page(advancedevent_p3_subtitle, advancedevent_p3_text),
+ new Page(advancedevent_p4_subtitle, advancedevent_p4_text),
+ new Page(advancedevent_p5_subtitle, advancedevent_p5_text)
+ ));
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final SubsamplingScaleImageView imageView = findViewById(id.imageView);
+ final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
+ @Override
+ public boolean onSingleTapConfirmed(MotionEvent e) {
+ if (imageView.isReady()) {
+ PointF sCoord = imageView.viewToSourceCoord(e.getX(), e.getY());
+ Toast.makeText(getApplicationContext(), "Single tap: " + ((int)sCoord.x) + ", " + ((int)sCoord.y), Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(getApplicationContext(), "Single tap: Image not ready", Toast.LENGTH_SHORT).show();
+ }
+ return true;
+ }
+ @Override
+ public void onLongPress(MotionEvent e) {
+ if (imageView.isReady()) {
+ PointF sCoord = imageView.viewToSourceCoord(e.getX(), e.getY());
+ Toast.makeText(getApplicationContext(), "Long press: " + ((int)sCoord.x) + ", " + ((int)sCoord.y), Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(getApplicationContext(), "Long press: Image not ready", Toast.LENGTH_SHORT).show();
+ }
+ }
+ @Override
+ public boolean onDoubleTap(MotionEvent e) {
+ if (imageView.isReady()) {
+ PointF sCoord = imageView.viewToSourceCoord(e.getX(), e.getY());
+ Toast.makeText(getApplicationContext(), "Double tap: " + ((int)sCoord.x) + ", " + ((int)sCoord.y), Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(getApplicationContext(), "Double tap: Image not ready", Toast.LENGTH_SHORT).show();
+ }
+ return true;
+ }
+ });
+
+ imageView.setImage(ImageSource.asset("squirrel.jpg"));
+ imageView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ return gestureDetector.onTouchEvent(motionEvent);
+ }
+ });
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionActivity.java
new file mode 100644
index 0000000..1b143d7
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionActivity.java
@@ -0,0 +1,67 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.extension;
+
+import android.support.v4.app.Fragment;
+import android.util.Log;
+
+import com.davemorrissey.labs.subscaleview.sample.AbstractFragmentsActivity;
+import com.davemorrissey.labs.subscaleview.sample.Page;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+import com.davemorrissey.labs.subscaleview.sample.imagedisplay.ImageDisplayActivity;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.davemorrissey.labs.subscaleview.sample.R.layout.fragments_activity;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.extension_p1_subtitle;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.extension_p1_text;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.extension_p2_subtitle;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.extension_p2_text;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.extension_p3_subtitle;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.extension_p3_text;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.extension_title;
+
+public class ExtensionActivity extends AbstractFragmentsActivity {
+
+ private static final List<Class<? extends Fragment>> FRAGMENTS = Arrays.asList(
+ ExtensionPinFragment.class,
+ ExtensionCircleFragment.class,
+ ExtensionFreehandFragment.class
+ );
+
+ public ExtensionActivity() {
+ super(extension_title, fragments_activity, Arrays.asList(
+ new Page(extension_p1_subtitle, extension_p1_text),
+ new Page(extension_p2_subtitle, extension_p2_text),
+ new Page(extension_p3_subtitle, extension_p3_text)
+ ));
+ }
+
+ @Override
+ protected void onPageChanged(int page) {
+ try {
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(id.frame, FRAGMENTS.get(page).newInstance())
+ .commit();
+ } catch (Exception e) {
+ Log.e(ImageDisplayActivity.class.getName(), "Failed to load fragment", e);
+ }
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionCircleFragment.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionCircleFragment.java
new file mode 100644
index 0000000..3cb3866
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionCircleFragment.java
@@ -0,0 +1,46 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.extension;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+import com.davemorrissey.labs.subscaleview.sample.R.layout;
+
+public class ExtensionCircleFragment extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View rootView = inflater.inflate(layout.extension_circle_fragment, container, false);
+ rootView.findViewById(id.next).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { ((ExtensionActivity) ExtensionCircleFragment.this.getActivity()).next(); }
+ });
+ rootView.findViewById(id.previous).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { ((ExtensionActivity) ExtensionCircleFragment.this.getActivity()).previous(); }
+ });
+ SubsamplingScaleImageView imageView = rootView.findViewById(id.imageView);
+ imageView.setImage(ImageSource.asset("squirrel.jpg"));
+ return rootView;
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionFreehandFragment.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionFreehandFragment.java
new file mode 100644
index 0000000..e77f882
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionFreehandFragment.java
@@ -0,0 +1,46 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.extension;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+import com.davemorrissey.labs.subscaleview.sample.R.layout;
+import com.davemorrissey.labs.subscaleview.sample.extension.views.FreehandView;
+
+public class ExtensionFreehandFragment extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View rootView = inflater.inflate(layout.extension_freehand_fragment, container, false);
+ rootView.findViewById(id.previous).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { ((ExtensionActivity) ExtensionFreehandFragment.this.getActivity()).previous(); }
+ });
+ final FreehandView imageView = rootView.findViewById(id.imageView);
+ imageView.setImage(ImageSource.asset("squirrel.jpg"));
+ rootView.findViewById(id.reset).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { imageView.reset(); }
+ });
+ return rootView;
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionPinFragment.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionPinFragment.java
new file mode 100644
index 0000000..d8e4e71
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/ExtensionPinFragment.java
@@ -0,0 +1,45 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.extension;
+
+import android.graphics.PointF;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+import com.davemorrissey.labs.subscaleview.sample.R.layout;
+import com.davemorrissey.labs.subscaleview.sample.extension.views.PinView;
+
+public class ExtensionPinFragment extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View rootView = inflater.inflate(layout.extension_pin_fragment, container, false);
+ rootView.findViewById(id.next).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { ((ExtensionActivity) ExtensionPinFragment.this.getActivity()).next(); }
+ });
+ PinView imageView = rootView.findViewById(id.imageView);
+ imageView.setImage(ImageSource.asset("squirrel.jpg"));
+ imageView.setPin(new PointF(1718f, 581f));
+ return rootView;
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/CircleView.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/CircleView.java
new file mode 100644
index 0000000..9a7a6aa
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/CircleView.java
@@ -0,0 +1,72 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.extension.views;
+
+import android.content.Context;
+import android.graphics.*;
+import android.graphics.Paint.Cap;
+import android.graphics.Paint.Style;
+import android.util.AttributeSet;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+
+public class CircleView extends SubsamplingScaleImageView {
+
+ private int strokeWidth;
+
+ private final PointF sCenter = new PointF();
+ private final PointF vCenter = new PointF();
+ private final Paint paint = new Paint();
+
+ public CircleView(Context context) {
+ this(context, null);
+ }
+
+ public CircleView(Context context, AttributeSet attr) {
+ super(context, attr);
+ initialise();
+ }
+
+ private void initialise() {
+ float density = getResources().getDisplayMetrics().densityDpi;
+ strokeWidth = (int)(density/60f);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ // Don't draw pin before image is ready so it doesn't move around during setup.
+ if (!isReady()) {
+ return;
+ }
+
+ sCenter.set(getSWidth()/2, getSHeight()/2);
+ sourceToViewCoord(sCenter, vCenter);
+ float radius = (getScale() * getSWidth()) * 0.25f;
+
+ paint.setAntiAlias(true);
+ paint.setStyle(Style.STROKE);
+ paint.setStrokeCap(Cap.ROUND);
+ paint.setStrokeWidth(strokeWidth * 2);
+ paint.setColor(Color.BLACK);
+ canvas.drawCircle(vCenter.x, vCenter.y, radius, paint);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setColor(Color.argb(255, 51, 181, 229));
+ canvas.drawCircle(vCenter.x, vCenter.y, radius, paint);
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/FreehandView.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/FreehandView.java
new file mode 100644
index 0000000..6d49aca
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/FreehandView.java
@@ -0,0 +1,157 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.extension.views;
+
+import android.content.Context;
+import android.graphics.*;
+import android.graphics.Paint.Cap;
+import android.graphics.Paint.Style;
+import android.support.annotation.NonNull;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnTouchListener;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FreehandView extends SubsamplingScaleImageView implements OnTouchListener {
+
+ private final Paint paint = new Paint();
+ private final Path vPath = new Path();
+ private final PointF vPoint = new PointF();
+ private PointF vPrev = new PointF();
+ private PointF vPrevious;
+ private PointF vStart;
+ private boolean drawing = false;
+
+ private int strokeWidth;
+
+ private List<PointF> sPoints;
+
+ public FreehandView(Context context, AttributeSet attr) {
+ super(context, attr);
+ initialise();
+ }
+
+ public FreehandView(Context context) {
+ this(context, null);
+ }
+
+ private void initialise() {
+ setOnTouchListener(this);
+ float density = getResources().getDisplayMetrics().densityDpi;
+ strokeWidth = (int)(density/60f);
+ }
+
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ return false;
+ }
+
+ @Override
+ public boolean onTouchEvent(@NonNull MotionEvent event) {
+ if (sPoints != null && !drawing) {
+ return super.onTouchEvent(event);
+ }
+ boolean consumed = false;
+ int touchCount = event.getPointerCount();
+ switch (event.getActionMasked()) {
+ case MotionEvent.ACTION_DOWN:
+ if (event.getActionIndex() == 0) {
+ vStart = new PointF(event.getX(), event.getY());
+ vPrevious = new PointF(event.getX(), event.getY());
+ } else {
+ vStart = null;
+ vPrevious = null;
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ PointF sCurrentF = viewToSourceCoord(event.getX(), event.getY());
+ PointF sCurrent = new PointF(sCurrentF.x, sCurrentF.y);
+ PointF sStart = vStart == null ? null : new PointF(viewToSourceCoord(vStart).x, viewToSourceCoord(vStart).y);
+
+ if (touchCount == 1 && vStart != null) {
+ float vDX = Math.abs(event.getX() - vPrevious.x);
+ float vDY = Math.abs(event.getY() - vPrevious.y);
+ if (vDX >= strokeWidth * 5 || vDY >= strokeWidth * 5) {
+ if (sPoints == null) {
+ sPoints = new ArrayList<>();
+ sPoints.add(sStart);
+ }
+ sPoints.add(sCurrent);
+ vPrevious.x = event.getX();
+ vPrevious.y = event.getY();
+ drawing = true;
+ }
+ consumed = true;
+ invalidate();
+ } else if (touchCount == 1) {
+ // Consume all one touch drags to prevent odd panning effects handled by the superclass.
+ consumed = true;
+ }
+ break;
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_POINTER_UP:
+ invalidate();
+ drawing = false;
+ vPrevious = null;
+ vStart = null;
+ }
+ // Use parent to handle pinch and two-finger pan.
+ return consumed || super.onTouchEvent(event);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ // Don't draw anything before image is ready.
+ if (!isReady()) {
+ return;
+ }
+
+ paint.setAntiAlias(true);
+
+ if (sPoints != null && sPoints.size() >= 2) {
+ vPath.reset();
+ sourceToViewCoord(sPoints.get(0).x, sPoints.get(0).y, vPrev);
+ vPath.moveTo(vPrev.x, vPrev.y);
+ for (int i = 1; i < sPoints.size(); i++) {
+ sourceToViewCoord(sPoints.get(i).x, sPoints.get(i).y, vPoint);
+ vPath.quadTo(vPrev.x, vPrev.y, (vPoint.x + vPrev.x) / 2, (vPoint.y + vPrev.y) / 2);
+ vPrev = vPoint;
+ }
+ paint.setStyle(Style.STROKE);
+ paint.setStrokeCap(Cap.ROUND);
+ paint.setStrokeWidth(strokeWidth * 2);
+ paint.setColor(Color.BLACK);
+ canvas.drawPath(vPath, paint);
+ paint.setStrokeWidth(strokeWidth);
+ paint.setColor(Color.argb(255, 51, 181, 229));
+ canvas.drawPath(vPath, paint);
+ }
+
+ }
+
+ public void reset() {
+ this.sPoints = null;
+ invalidate();
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/PinView.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/PinView.java
new file mode 100644
index 0000000..fda8f73
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/extension/views/PinView.java
@@ -0,0 +1,76 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.extension.views;
+
+import android.content.Context;
+import android.graphics.*;
+import android.util.AttributeSet;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.davemorrissey.labs.subscaleview.sample.R.drawable;
+
+
+public class PinView extends SubsamplingScaleImageView {
+
+ private final Paint paint = new Paint();
+ private final PointF vPin = new PointF();
+ private PointF sPin;
+ private Bitmap pin;
+
+ public PinView(Context context) {
+ this(context, null);
+ }
+
+ public PinView(Context context, AttributeSet attr) {
+ super(context, attr);
+ initialise();
+ }
+
+ public void setPin(PointF sPin) {
+ this.sPin = sPin;
+ initialise();
+ invalidate();
+ }
+
+ private void initialise() {
+ float density = getResources().getDisplayMetrics().densityDpi;
+ pin = BitmapFactory.decodeResource(this.getResources(), drawable.pushpin_blue);
+ float w = (density/420f) * pin.getWidth();
+ float h = (density/420f) * pin.getHeight();
+ pin = Bitmap.createScaledBitmap(pin, (int)w, (int)h, true);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ // Don't draw pin before image is ready so it doesn't move around during setup.
+ if (!isReady()) {
+ return;
+ }
+
+ paint.setAntiAlias(true);
+
+ if (sPin != null && pin != null) {
+ sourceToViewCoord(sPin, vPin);
+ float vX = vPin.x - (pin.getWidth()/2);
+ float vY = vPin.y - pin.getHeight();
+ canvas.drawBitmap(pin, vX, vY, paint);
+ }
+
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayActivity.java
new file mode 100644
index 0000000..7d0df3b
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayActivity.java
@@ -0,0 +1,60 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.imagedisplay;
+
+import android.support.v4.app.Fragment;
+import android.util.Log;
+
+import com.davemorrissey.labs.subscaleview.sample.AbstractFragmentsActivity;
+import com.davemorrissey.labs.subscaleview.sample.Page;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static com.davemorrissey.labs.subscaleview.sample.R.string.*;
+import static com.davemorrissey.labs.subscaleview.sample.R.layout.*;
+
+public class ImageDisplayActivity extends AbstractFragmentsActivity {
+
+ private static final List<Class<? extends Fragment>> FRAGMENTS = Arrays.asList(
+ ImageDisplayLargeFragment.class,
+ ImageDisplayRotateFragment.class,
+ ImageDisplayRegionFragment.class
+ );
+
+ public ImageDisplayActivity() {
+ super(display_title, fragments_activity, Arrays.asList(
+ new Page(display_p1_subtitle, display_p1_text),
+ new Page(display_p2_subtitle, display_p2_text),
+ new Page(display_p3_subtitle, display_p3_text)
+ ));
+ }
+
+ @Override
+ protected void onPageChanged(int page) {
+ try {
+ getSupportFragmentManager()
+ .beginTransaction()
+ .replace(id.frame, FRAGMENTS.get(page).newInstance())
+ .commit();
+ } catch (Exception e) {
+ Log.e(ImageDisplayActivity.class.getName(), "Failed to load fragment", e);
+ }
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayLargeFragment.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayLargeFragment.java
new file mode 100644
index 0000000..7e8542f
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayLargeFragment.java
@@ -0,0 +1,43 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.imagedisplay;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+import com.davemorrissey.labs.subscaleview.sample.R.layout;
+
+public class ImageDisplayLargeFragment extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View rootView = inflater.inflate(layout.imagedisplay_large_fragment, container, false);
+ rootView.findViewById(id.next).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { ((ImageDisplayActivity) ImageDisplayLargeFragment.this.getActivity()).next(); }
+ });
+ SubsamplingScaleImageView imageView = rootView.findViewById(id.imageView);
+ imageView.setImage(ImageSource.asset("card.png"));
+ return rootView;
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayRegionFragment.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayRegionFragment.java
new file mode 100644
index 0000000..517948f
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayRegionFragment.java
@@ -0,0 +1,48 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.imagedisplay;
+
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+import com.davemorrissey.labs.subscaleview.sample.R.layout;
+
+public class ImageDisplayRegionFragment extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View rootView = inflater.inflate(layout.imagedisplay_region_fragment, container, false);
+ final SubsamplingScaleImageView imageView = rootView.findViewById(id.imageView);
+ imageView.setOrientation(SubsamplingScaleImageView.ORIENTATION_90);
+ imageView.setImage(ImageSource.asset("card.png").region(new Rect(0, 0, 3778, 2834)));
+ rootView.findViewById(id.previous).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { ((ImageDisplayActivity) ImageDisplayRegionFragment.this.getActivity()).previous(); }
+ });
+ rootView.findViewById(id.rotate).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { imageView.setOrientation((imageView.getOrientation() + 90) % 360); }
+ });
+ return rootView;
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayRotateFragment.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayRotateFragment.java
new file mode 100644
index 0000000..1ec199a
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/imagedisplay/ImageDisplayRotateFragment.java
@@ -0,0 +1,50 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.imagedisplay;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+import com.davemorrissey.labs.subscaleview.sample.R.layout;
+
+public class ImageDisplayRotateFragment extends Fragment {
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View rootView = inflater.inflate(layout.imagedisplay_rotate_fragment, container, false);
+ final SubsamplingScaleImageView imageView = rootView.findViewById(id.imageView);
+ imageView.setImage(ImageSource.asset("eagle.jpg"));
+ imageView.setOrientation(90);
+ rootView.findViewById(id.previous).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { ((ImageDisplayActivity) ImageDisplayRotateFragment.this.getActivity()).previous(); }
+ });
+ rootView.findViewById(id.next).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { ((ImageDisplayActivity) ImageDisplayRotateFragment.this.getActivity()).next(); }
+ });
+ rootView.findViewById(id.rotate).setOnClickListener(new View.OnClickListener() {
+ @Override public void onClick(View v) { imageView.setOrientation((imageView.getOrientation() + 90) % 360); }
+ });
+ return rootView;
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/VerticalViewPager.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/VerticalViewPager.java
new file mode 100644
index 0000000..86d2e85
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/VerticalViewPager.java
@@ -0,0 +1,67 @@
+package com.davemorrissey.labs.subscaleview.sample.viewpager;
+
+import android.content.Context;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+
+/**
+ * From http://stackoverflow.com/a/22797619/2719186
+ */
+public class VerticalViewPager extends ViewPager {
+
+ public VerticalViewPager(Context context) {
+ super(context);
+ init();
+ }
+
+ public VerticalViewPager(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ private void init() {
+ setPageTransformer(true, new VerticalPageTransformer());
+ setOverScrollMode(OVER_SCROLL_NEVER);
+ }
+
+ private class VerticalPageTransformer implements ViewPager.PageTransformer {
+
+ @Override
+ public void transformPage(View view, float position) {
+ if (position < -1) {
+ view.setAlpha(0);
+ } else if (position <= 1) {
+ view.setAlpha(1);
+ view.setTranslationX(view.getWidth() * -position);
+ float yPosition = position * view.getHeight();
+ view.setTranslationY(yPosition);
+ } else {
+ view.setAlpha(0);
+ }
+ }
+ }
+
+ private MotionEvent swapXY(MotionEvent ev) {
+ float width = getWidth();
+ float height = getHeight();
+ float newX = (ev.getY() / height) * width;
+ float newY = (ev.getX() / width) * height;
+ ev.setLocation(newX, newY);
+ return ev;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev){
+ boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
+ swapXY(ev);
+ return intercepted;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ return super.onTouchEvent(swapXY(ev));
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/ViewPagerActivity.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/ViewPagerActivity.java
new file mode 100644
index 0000000..ba7fb7f
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/ViewPagerActivity.java
@@ -0,0 +1,98 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.viewpager;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.app.FragmentStatePagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.View;
+
+import com.davemorrissey.labs.subscaleview.sample.AbstractPagesActivity;
+import com.davemorrissey.labs.subscaleview.sample.Page;
+import com.davemorrissey.labs.subscaleview.sample.R;
+
+import java.util.Arrays;
+
+import static com.davemorrissey.labs.subscaleview.sample.R.layout.view_pager;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.pager_p1_subtitle;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.pager_p1_text;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.pager_p2_subtitle;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.pager_p2_text;
+import static com.davemorrissey.labs.subscaleview.sample.R.string.pager_title;
+
+public class ViewPagerActivity extends AbstractPagesActivity {
+
+ private static final String[] IMAGES = { "eagle.jpg", "pony.jpg" };
+
+ public ViewPagerActivity() {
+ super(pager_title, view_pager, Arrays.asList(
+ new Page(pager_p1_subtitle, pager_p1_text),
+ new Page(pager_p2_subtitle, pager_p2_text)
+ ));
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ViewPager horizontalPager = findViewById(R.id.horizontal_pager);
+ horizontalPager.setAdapter(new ScreenSlidePagerAdapter(getSupportFragmentManager()));
+ ViewPager verticalPager = findViewById(R.id.vertical_pager);
+ verticalPager.setAdapter(new ScreenSlidePagerAdapter(getSupportFragmentManager()));
+ }
+
+ @Override
+ public void onBackPressed() {
+ ViewPager viewPager = findViewById(getPage() == 0 ? R.id.horizontal_pager : R.id.vertical_pager);
+ if (viewPager.getCurrentItem() == 0) {
+ super.onBackPressed();
+ } else {
+ viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
+ }
+ }
+
+ @Override
+ protected void onPageChanged(int page) {
+ if (getPage() == 0) {
+ findViewById(R.id.horizontal_pager).setVisibility(View.VISIBLE);
+ findViewById(R.id.vertical_pager).setVisibility(View.GONE);
+ } else {
+ findViewById(R.id.horizontal_pager).setVisibility(View.GONE);
+ findViewById(R.id.vertical_pager).setVisibility(View.VISIBLE);
+ }
+ }
+
+ private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
+ ScreenSlidePagerAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ ViewPagerFragment fragment = new ViewPagerFragment();
+ fragment.setAsset(IMAGES[position]);
+ return fragment;
+ }
+
+ @Override
+ public int getCount() {
+ return IMAGES.length;
+ }
+ }
+
+}
diff --git a/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/ViewPagerFragment.java b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/ViewPagerFragment.java
new file mode 100644
index 0000000..442c84b
--- /dev/null
+++ b/sample/src/main/java/com/davemorrissey/labs/subscaleview/sample/viewpager/ViewPagerFragment.java
@@ -0,0 +1,69 @@
+/*
+Copyright 2014 David Morrissey
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package com.davemorrissey.labs.subscaleview.sample.viewpager;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.davemorrissey.labs.subscaleview.ImageSource;
+import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
+import com.davemorrissey.labs.subscaleview.sample.R.id;
+import com.davemorrissey.labs.subscaleview.sample.R.layout;
+
+public class ViewPagerFragment extends Fragment {
+
+ private static final String BUNDLE_ASSET = "asset";
+
+ private String asset;
+
+ public ViewPagerFragment() {
+ }
+
+ public void setAsset(String asset) {
+ this.asset = asset;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View rootView = inflater.inflate(layout.view_pager_page, container, false);
+
+ if (savedInstanceState != null) {
+ if (asset == null && savedInstanceState.containsKey(BUNDLE_ASSET)) {
+ asset = savedInstanceState.getString(BUNDLE_ASSET);
+ }
+ }
+ if (asset != null) {
+ SubsamplingScaleImageView imageView = rootView.findViewById(id.imageView);
+ imageView.setImage(ImageSource.asset(asset));
+ }
+
+ return rootView;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ View rootView = getView();
+ if (rootView != null) {
+ outState.putString(BUNDLE_ASSET, asset);
+ }
+ }
+
+}
diff --git a/sample/src/main/res/drawable-hdpi/launcher.png b/sample/src/main/res/drawable-hdpi/launcher.png
new file mode 100644
index 0000000..2ba1cba
--- /dev/null
+++ b/sample/src/main/res/drawable-hdpi/launcher.png
Binary files differ
diff --git a/sample/src/main/res/drawable-nodpi/button_standout_inactive.xml b/sample/src/main/res/drawable-nodpi/button_standout_inactive.xml
new file mode 100644
index 0000000..dfcefb4
--- /dev/null
+++ b/sample/src/main/res/drawable-nodpi/button_standout_inactive.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <solid android:color="#333333" />
+</shape>
diff --git a/sample/src/main/res/drawable-nodpi/button_standout_pressed.xml b/sample/src/main/res/drawable-nodpi/button_standout_pressed.xml
new file mode 100644
index 0000000..857646a
--- /dev/null
+++ b/sample/src/main/res/drawable-nodpi/button_standout_pressed.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <solid android:color="#0099CC" />
+</shape>
diff --git a/sample/src/main/res/drawable-nodpi/button_transparent_pressed.xml b/sample/src/main/res/drawable-nodpi/button_transparent_pressed.xml
new file mode 100644
index 0000000..e2ed965
--- /dev/null
+++ b/sample/src/main/res/drawable-nodpi/button_transparent_pressed.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <solid android:color="#770099cc" />
+</shape>
diff --git a/sample/src/main/res/drawable-nodpi/buttonstate_standout.xml b/sample/src/main/res/drawable-nodpi/buttonstate_standout.xml
new file mode 100644
index 0000000..71cfcd3
--- /dev/null
+++ b/sample/src/main/res/drawable-nodpi/buttonstate_standout.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:state_pressed="false"
+ android:drawable="@drawable/button_standout_pressed" />
+ <item android:state_focused="true" android:state_pressed="true"
+ android:drawable="@drawable/button_standout_pressed" />
+ <item android:state_focused="false" android:state_pressed="true"
+ android:drawable="@drawable/button_standout_pressed" />
+ <item android:drawable="@drawable/button_standout_inactive"/>
+</selector>
diff --git a/sample/src/main/res/drawable-nodpi/buttonstate_transparent.xml b/sample/src/main/res/drawable-nodpi/buttonstate_transparent.xml
new file mode 100644
index 0000000..8ca5594
--- /dev/null
+++ b/sample/src/main/res/drawable-nodpi/buttonstate_transparent.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_focused="true" android:state_pressed="false"
+ android:drawable="@drawable/button_transparent_pressed" />
+ <item android:state_focused="true" android:state_pressed="true"
+ android:drawable="@drawable/button_transparent_pressed" />
+ <item android:state_focused="false" android:state_pressed="true"
+ android:drawable="@drawable/button_transparent_pressed" />
+ <item android:drawable="@drawable/transparent"/>
+</selector>
diff --git a/sample/src/main/res/drawable-nodpi/pushpin_blue.png b/sample/src/main/res/drawable-nodpi/pushpin_blue.png
new file mode 100644
index 0000000..bb6d1ff
--- /dev/null
+++ b/sample/src/main/res/drawable-nodpi/pushpin_blue.png
Binary files differ
diff --git a/sample/src/main/res/drawable-nodpi/transparent.xml b/sample/src/main/res/drawable-nodpi/transparent.xml
new file mode 100644
index 0000000..f4f33d9
--- /dev/null
+++ b/sample/src/main/res/drawable-nodpi/transparent.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
+ <solid android:color="#00000000" />
+</shape>
diff --git a/sample/src/main/res/drawable-xhdpi/daffy.gif b/sample/src/main/res/drawable-xhdpi/daffy.gif
new file mode 100644
index 0000000..7fab6be
--- /dev/null
+++ b/sample/src/main/res/drawable-xhdpi/daffy.gif
Binary files differ
diff --git a/sample/src/main/res/drawable-xhdpi/launcher.png b/sample/src/main/res/drawable-xhdpi/launcher.png
new file mode 100644
index 0000000..fdfae89
--- /dev/null
+++ b/sample/src/main/res/drawable-xhdpi/launcher.png
Binary files differ
diff --git a/sample/src/main/res/drawable-xhdpi/next.png b/sample/src/main/res/drawable-xhdpi/next.png
new file mode 100644
index 0000000..7dc45c0
--- /dev/null
+++ b/sample/src/main/res/drawable-xhdpi/next.png
Binary files differ
diff --git a/sample/src/main/res/drawable-xhdpi/play.png b/sample/src/main/res/drawable-xhdpi/play.png
new file mode 100644
index 0000000..5112499
--- /dev/null
+++ b/sample/src/main/res/drawable-xhdpi/play.png
Binary files differ
diff --git a/sample/src/main/res/drawable-xhdpi/previous.png b/sample/src/main/res/drawable-xhdpi/previous.png
new file mode 100644
index 0000000..e97e910
--- /dev/null
+++ b/sample/src/main/res/drawable-xhdpi/previous.png
Binary files differ
diff --git a/sample/src/main/res/drawable-xhdpi/reset.png b/sample/src/main/res/drawable-xhdpi/reset.png
new file mode 100644
index 0000000..e1082da
--- /dev/null
+++ b/sample/src/main/res/drawable-xhdpi/reset.png
Binary files differ
diff --git a/sample/src/main/res/drawable-xhdpi/rotate.png b/sample/src/main/res/drawable-xhdpi/rotate.png
new file mode 100644
index 0000000..1ba064f
--- /dev/null
+++ b/sample/src/main/res/drawable-xhdpi/rotate.png
Binary files differ
diff --git a/sample/src/main/res/drawable-xxhdpi/launcher.png b/sample/src/main/res/drawable-xxhdpi/launcher.png
new file mode 100644
index 0000000..87f0e25
--- /dev/null
+++ b/sample/src/main/res/drawable-xxhdpi/launcher.png
Binary files differ
diff --git a/sample/src/main/res/layout/animation_activity.xml b/sample/src/main/res/layout/animation_activity.xml
new file mode 100644
index 0000000..5416a88
--- /dev/null
+++ b/sample/src/main/res/layout/animation_activity.xml
@@ -0,0 +1,24 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <RelativeLayout style="@style/footer" android:id="@+id/footer">
+
+ <ImageView style="@style/previousButton" android:id="@+id/previous" android:contentDescription="@string/button.previous"/>
+
+ <ImageView style="@style/nextButton" android:id="@+id/next" android:contentDescription="@string/button.next"/>
+
+ <ImageView style="@style/footerButton"
+ android:id="@+id/play"
+ android:layout_toStartOf="@id/next"
+ android:src="@drawable/play"
+ android:contentDescription="@string/button.animate"/>
+
+ <TextView style="@style/footerNote"
+ android:id="@+id/note"
+ android:layout_toStartOf="@id/play"
+ android:layout_toEndOf="@id/previous"/>
+
+ </RelativeLayout>
+
+ <com.davemorrissey.labs.subscaleview.sample.extension.views.PinView style="@style/mainPanel" android:id="@+id/imageView"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/layout/extension_circle_fragment.xml b/sample/src/main/res/layout/extension_circle_fragment.xml
new file mode 100644
index 0000000..b1bcd76
--- /dev/null
+++ b/sample/src/main/res/layout/extension_circle_fragment.xml
@@ -0,0 +1,19 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <RelativeLayout style="@style/footer" android:id="@+id/footer">
+
+ <ImageView style="@style/previousButton" android:id="@+id/previous" android:contentDescription="@string/button.previous"/>
+
+ <ImageView style="@style/nextButton" android:id="@+id/next" android:contentDescription="@string/button.next"/>
+
+ <TextView style="@style/footerNote"
+ android:id="@+id/note"
+ android:text="@string/extension.p2.text"
+ android:layout_toStartOf="@id/next"
+ android:layout_toEndOf="@id/previous"/>
+
+ </RelativeLayout>
+
+ <com.davemorrissey.labs.subscaleview.sample.extension.views.CircleView style="@style/mainPanel" android:id="@+id/imageView"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/layout/extension_freehand_fragment.xml b/sample/src/main/res/layout/extension_freehand_fragment.xml
new file mode 100644
index 0000000..006aa0f
--- /dev/null
+++ b/sample/src/main/res/layout/extension_freehand_fragment.xml
@@ -0,0 +1,25 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <RelativeLayout style="@style/footer" android:id="@+id/footer">
+
+ <ImageView style="@style/previousButton" android:id="@+id/previous" android:contentDescription="@string/button.previous"/>
+
+ <ImageView style="@style/nextButton" android:id="@+id/next" android:contentDescription="@string/button.next" android:visibility="invisible"/>
+
+ <ImageView style="@style/footerButton"
+ android:id="@+id/reset"
+ android:layout_toStartOf="@id/next"
+ android:src="@drawable/reset"
+ android:contentDescription="@string/button.reset"/>
+
+ <TextView style="@style/footerNote"
+ android:id="@+id/note"
+ android:text="@string/extension.p3.text"
+ android:layout_toStartOf="@id/reset"
+ android:layout_toEndOf="@id/previous"/>
+
+ </RelativeLayout>
+
+ <com.davemorrissey.labs.subscaleview.sample.extension.views.FreehandView style="@style/mainPanel" android:id="@+id/imageView"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/layout/extension_pin_fragment.xml b/sample/src/main/res/layout/extension_pin_fragment.xml
new file mode 100644
index 0000000..fd67b84
--- /dev/null
+++ b/sample/src/main/res/layout/extension_pin_fragment.xml
@@ -0,0 +1,19 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <RelativeLayout style="@style/footer" android:id="@+id/footer">
+
+ <ImageView style="@style/previousButton" android:id="@+id/previous" android:contentDescription="@string/button.previous" android:visibility="invisible"/>
+
+ <ImageView style="@style/nextButton" android:id="@+id/next" android:contentDescription="@string/button.next"/>
+
+ <TextView style="@style/footerNote"
+ android:id="@+id/note"
+ android:text="@string/extension.p1.text"
+ android:layout_toStartOf="@id/next"
+ android:layout_toEndOf="@id/previous"/>
+
+ </RelativeLayout>
+
+ <com.davemorrissey.labs.subscaleview.sample.extension.views.PinView style="@style/mainPanel" android:id="@+id/imageView"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/layout/fragments_activity.xml b/sample/src/main/res/layout/fragments_activity.xml
new file mode 100644
index 0000000..5624f75
--- /dev/null
+++ b/sample/src/main/res/layout/fragments_activity.xml
@@ -0,0 +1,5 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <FrameLayout android:id="@+id/frame" style="@style/fill"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/layout/imagedisplay_large_fragment.xml b/sample/src/main/res/layout/imagedisplay_large_fragment.xml
new file mode 100644
index 0000000..442fc67
--- /dev/null
+++ b/sample/src/main/res/layout/imagedisplay_large_fragment.xml
@@ -0,0 +1,19 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <RelativeLayout style="@style/footer" android:id="@+id/footer">
+
+ <ImageView style="@style/previousButton" android:id="@+id/previous" android:contentDescription="@string/button.previous" android:visibility="invisible"/>
+
+ <ImageView style="@style/nextButton" android:id="@+id/next" android:contentDescription="@string/button.next"/>
+
+ <TextView style="@style/footerNote"
+ android:id="@+id/note"
+ android:text="@string/display.p1.text"
+ android:layout_toStartOf="@id/next"
+ android:layout_toEndOf="@id/previous"/>
+
+ </RelativeLayout>
+
+ <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView style="@style/mainPanel" android:id="@+id/imageView"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/layout/imagedisplay_region_fragment.xml b/sample/src/main/res/layout/imagedisplay_region_fragment.xml
new file mode 100644
index 0000000..6c8b3d2
--- /dev/null
+++ b/sample/src/main/res/layout/imagedisplay_region_fragment.xml
@@ -0,0 +1,25 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <RelativeLayout style="@style/footer" android:id="@+id/footer">
+
+ <ImageView style="@style/previousButton" android:id="@+id/previous" android:contentDescription="@string/button.previous"/>
+
+ <ImageView style="@style/nextButton" android:id="@+id/next" android:contentDescription="@string/button.next" android:visibility="invisible"/>
+
+ <ImageView style="@style/footerButton"
+ android:id="@+id/rotate"
+ android:layout_toStartOf="@id/next"
+ android:src="@drawable/rotate"
+ android:contentDescription="@string/button.rotate"/>
+
+ <TextView style="@style/footerNote"
+ android:id="@+id/note"
+ android:text="@string/display.p3.text"
+ android:layout_toStartOf="@id/rotate"
+ android:layout_toEndOf="@id/previous"/>
+
+ </RelativeLayout>
+
+ <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView style="@style/mainPanel" android:id="@+id/imageView"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/layout/imagedisplay_rotate_fragment.xml b/sample/src/main/res/layout/imagedisplay_rotate_fragment.xml
new file mode 100644
index 0000000..9dbf50a
--- /dev/null
+++ b/sample/src/main/res/layout/imagedisplay_rotate_fragment.xml
@@ -0,0 +1,25 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <RelativeLayout style="@style/footer" android:id="@+id/footer">
+
+ <ImageView style="@style/previousButton" android:id="@+id/previous" android:contentDescription="@string/button.previous"/>
+
+ <ImageView style="@style/nextButton" android:id="@+id/next" android:contentDescription="@string/button.next"/>
+
+ <ImageView style="@style/footerButton"
+ android:id="@+id/rotate"
+ android:layout_toStartOf="@id/next"
+ android:src="@drawable/rotate"
+ android:contentDescription="@string/button.rotate"/>
+
+ <TextView style="@style/footerNote"
+ android:id="@+id/note"
+ android:text="@string/display.p2.text"
+ android:layout_toStartOf="@id/rotate"
+ android:layout_toEndOf="@id/previous"/>
+
+ </RelativeLayout>
+
+ <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView style="@style/mainPanel" android:id="@+id/imageView"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/layout/main.xml b/sample/src/main/res/layout/main.xml
new file mode 100644
index 0000000..05146e9
--- /dev/null
+++ b/sample/src/main/res/layout/main.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <LinearLayout android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:layout_width="300dp"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="10dp"
+ android:orientation="vertical">
+
+ <View style="@style/indexDivider"/>
+ <TextView style="@style/indexLink" android:id="@+id/basicFeatures" android:text="@string/basic.link"/>
+ <View style="@style/indexDivider"/>
+ <TextView style="@style/indexLink" android:id="@+id/imageDisplay" android:text="@string/display.link"/>
+ <View style="@style/indexDivider"/>
+ <TextView style="@style/indexLink" android:id="@+id/eventHandling" android:text="@string/event.link"/>
+ <View style="@style/indexDivider"/>
+ <TextView style="@style/indexLink" android:id="@+id/advancedEventHandling" android:text="@string/advancedevent.link"/>
+ <View style="@style/indexDivider"/>
+ <TextView style="@style/indexLink" android:id="@+id/viewPagerGalleries" android:text="@string/pager.link"/>
+ <View style="@style/indexDivider"/>
+ <TextView style="@style/indexLink" android:id="@+id/animation" android:text="@string/animation.link"/>
+ <View style="@style/indexDivider"/>
+ <TextView style="@style/indexLink" android:id="@+id/extension" android:text="@string/extension.link"/>
+ <View style="@style/indexDivider"/>
+ <TextView style="@style/indexLink" android:id="@+id/configuration" android:text="@string/configuration.link"/>
+ <View style="@style/indexDivider"/>
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/self"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:background="@drawable/buttonstate_transparent"
+ android:padding="10dp"
+ android:orientation="vertical">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:src="@drawable/daffy"
+ android:contentDescription="@string/main.avatar"/>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:gravity="center_horizontal"
+ android:textSize="13sp"
+ android:textColor="#777777"
+ android:text="@string/main.attribution"/>
+
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/github"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:layout_gravity="center_horizontal"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp"
+ android:textSize="16sp"
+ android:text="@string/main.viewongithub"/>
+
+ </LinearLayout>
+</ScrollView>
diff --git a/sample/src/main/res/layout/pages_activity.xml b/sample/src/main/res/layout/pages_activity.xml
new file mode 100644
index 0000000..46014bb
--- /dev/null
+++ b/sample/src/main/res/layout/pages_activity.xml
@@ -0,0 +1,18 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <RelativeLayout style="@style/footer" android:id="@+id/footer">
+
+ <ImageView style="@style/previousButton" android:id="@+id/previous" android:contentDescription="@string/button.previous"/>
+
+ <ImageView style="@style/nextButton" android:id="@+id/next" android:contentDescription="@string/button.next"/>
+
+ <TextView style="@style/footerNote"
+ android:id="@+id/note"
+ android:layout_toStartOf="@id/next"
+ android:layout_toEndOf="@id/previous"/>
+
+ </RelativeLayout>
+
+ <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView style="@style/mainPanel" android:id="@+id/imageView"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/layout/view_pager.xml b/sample/src/main/res/layout/view_pager.xml
new file mode 100644
index 0000000..c6c7bfc
--- /dev/null
+++ b/sample/src/main/res/layout/view_pager.xml
@@ -0,0 +1,20 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <RelativeLayout style="@style/footer" android:id="@+id/footer">
+
+ <ImageView style="@style/previousButton" android:id="@+id/previous" android:contentDescription="@string/button.previous"/>
+
+ <ImageView style="@style/nextButton" android:id="@+id/next" android:contentDescription="@string/button.next"/>
+
+ <TextView style="@style/footerNote"
+ android:id="@+id/note"
+ android:layout_toStartOf="@id/next"
+ android:layout_toEndOf="@id/previous"/>
+
+ </RelativeLayout>
+
+ <android.support.v4.view.ViewPager style="@style/mainPanel" android:id="@+id/horizontal_pager" android:visibility="gone" />
+
+ <com.davemorrissey.labs.subscaleview.sample.viewpager.VerticalViewPager style="@style/mainPanel" android:id="@+id/vertical_pager" android:visibility="gone"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/layout/view_pager_page.xml b/sample/src/main/res/layout/view_pager_page.xml
new file mode 100644
index 0000000..0f1ede4
--- /dev/null
+++ b/sample/src/main/res/layout/view_pager_page.xml
@@ -0,0 +1,5 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/fill">
+
+ <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView style="@style/fill" android:id="@+id/imageView"/>
+
+</RelativeLayout>
diff --git a/sample/src/main/res/values/colors.xml b/sample/src/main/res/values/colors.xml
new file mode 100644
index 0000000..2f29f49
--- /dev/null
+++ b/sample/src/main/res/values/colors.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="background">#111111</color>
+ <color name="actionBarBackground">#282828</color>
+</resources>
diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml
new file mode 100644
index 0000000..3c5a1f4
--- /dev/null
+++ b/sample/src/main/res/values/strings.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="app.name">Scale Image View Demo</string>
+
+ <string name="main.title">Subsampling Scale Image View</string>
+
+ <string name="main.attribution">by Dave Morrissey</string>
+ <string name="main.avatar">Avatar</string>
+ <string name="main.viewongithub">View on GitHub</string>
+
+ <string name="button.animate">Animate</string>
+ <string name="button.next">Next</string>
+ <string name="button.previous">Previous</string>
+ <string name="button.rotate">Rotate</string>
+ <string name="button.reset">Reset</string>
+
+ <string name="basic.link">Basic features</string>
+ <string name="basic.title">Basic features</string>
+ <string name="basic.p1.subtitle">Pinch to zoom</string>
+ <string name="basic.p1.text">
+ Use a two finger pinch to zoom in and out. The zoom is centred on the pinch gesture, and you can pan at the same time.
+ </string>
+ <string name="basic.p2.subtitle">Quick scale</string>
+ <string name="basic.p2.text">
+ Double tap and swipe up or down to zoom in or out. The zoom is centred where you tapped.
+ </string>
+ <string name="basic.p3.subtitle">Drag</string>
+ <string name="basic.p3.text">Use one finger to drag the image around.</string>
+ <string name="basic.p4.subtitle">Fling</string>
+ <string name="basic.p4.text">
+ If you drag quickly and let go, fling momentum keeps the image moving.
+ </string>
+ <string name="basic.p5.subtitle">Double tap</string>
+ <string name="basic.p5.text">
+ Double tap the image to zoom in to that spot. Double tap again to zoom out.
+ </string>
+
+ <string name="display.link">Image display</string>
+ <string name="display.title">Image display</string>
+ <string name="display.p1.subtitle">Large images</string>
+ <string name="display.p1.text">
+ This image is 7,557 x 5,669 pixels. On most devices it will be subsampled, and higher quality tiles are loaded as you zoom in.
+ </string>
+ <string name="display.p2.subtitle">Rotation</string>
+ <string name="display.p2.text">
+ This image has been rotated 90 degrees. Tap the button to rotate it. EXIF rotation is supported for external files.
+ </string>
+ <string name="display.p3.subtitle">Display region</string>
+ <string name="display.p3.text">Set the region to display instead of the whole image.</string>
+
+ <string name="event.link">Event handling</string>
+ <string name="event.title">Event handling</string>
+ <string name="event.p1.subtitle">Simple events</string>
+ <string name="event.p1.text">
+ Touch handling by the image view doesn\'t prevent normal events from working.
+ </string>
+ <string name="event.p2.subtitle">OnClickListener</string>
+ <string name="event.p2.text">
+ This view has an OnClickListener. Tap once to activate the click.
+ </string>
+ <string name="event.p3.subtitle">OnLongClickListener</string>
+ <string name="event.p3.text">
+ This view has an OnLongClickListener. Press and hold to activate it.
+ </string>
+
+ <string name="advancedevent.link">Advanced event handling</string>
+ <string name="advancedevent.title">Advanced event handling</string>
+ <string name="advancedevent.p1.subtitle">Overriding gestures</string>
+ <string name="advancedevent.p1.text">Some gestures can be overridden with your own
+ GestureDetector without affecting the image view. This allows you to get the coordinates of
+ the event.
+ </string>
+ <string name="advancedevent.p2.subtitle">onSingleTapConfirmed</string>
+ <string name="advancedevent.p2.text">onSingleTapConfirmed has been overridden. Tap the image to
+ see coordinates.
+ </string>
+ <string name="advancedevent.p3.subtitle">onDoubleTap</string>
+ <string name="advancedevent.p3.text">onDoubleTap has been overridden. Tap the image to see
+ coordinates. This overrides the default zoom in behaviour.
+ </string>
+ <string name="advancedevent.p4.subtitle">onLongPress</string>
+ <string name="advancedevent.p4.text">onLongPress has been overridden. Press and hold the image
+ to see coordinates.
+ </string>
+ <string name="advancedevent.p5.subtitle">Other events</string>
+ <string name="advancedevent.p5.text">You can override any event you want, but customising swipe,
+ fling and zoom gestures will stop the view working normally.
+ </string>
+
+
+ <string name="pager.link">View pager galleries</string>
+ <string name="pager.title">View pager gallery</string>
+ <string name="pager.p1.subtitle">Horizontal</string>
+ <string name="pager.p1.text">
+ This gallery has two images in a ViewPager. Swipe to move to the
+ next image. If you\'re zoomed in on an image, you need to pan to the right of it, then swipe
+ again to activate the pager.
+ </string>
+ <string name="pager.p2.subtitle">Vertical</string>
+ <string name="pager.p2.text">
+ Vertical view pagers are also supported. Swipe up to move to the
+ next image. If you\'re zoomed in on an image, you need to pan to the bottom of it, then
+ swipe again to activate the pager.
+ </string>
+
+ <string name="animation.link">Animation</string>
+ <string name="animation.title">Animation</string>
+ <string name="animation.p1.subtitle">A demo</string>
+ <string name="animation.p1.text">
+ Tap the play button. The image will scale and zoom to a random point, shown by a marker.
+ </string>
+ <string name="animation.p2.subtitle">Limited pan</string>
+ <string name="animation.p2.text">
+ If the target point is near the edge of the image, it will be moved as near to the center as possible.
+ </string>
+ <string name="animation.p3.subtitle">Unlimited pan</string>
+ <string name="animation.p3.text">
+ With unlimited or center-limited pan, the target point can always be animated to the center.
+ </string>
+ <string name="animation.p4.subtitle">Customisation</string>
+ <string name="animation.p4.text">
+ Duration and easing are configurable. You can also make animations non-interruptible.
+ </string>
+
+ <string name="extension.link">Extension</string>
+ <string name="extension.title">Extension</string>
+ <string name="extension.p1.subtitle">Location pin</string>
+ <string name="extension.p1.text">
+ This view class extends the image view, and adds a pin anchored to a point on the image.
+ </string>
+ <string name="extension.p2.subtitle">Overlaid circle</string>
+ <string name="extension.p2.text">
+ A slightly more advanced example, this shows a circle that will
+ move and scale with the image. (Due to a limitation in Android, this circle may disappear
+ when it\'s larger than 2048px.)
+ </string>
+ <string name="extension.p3.subtitle">Freehand drawing</string>
+ <string name="extension.p3.text">
+ This subclass adds event detection. Draw a freehand line; it
+ will move with the image. (Due to a limitation in Android, your drawing may disappear when
+ it\'s larger than 2048px.)
+ </string>
+
+ <string name="configuration.link">Configuration</string>
+ <string name="configuration.title">Configuration</string>
+ <string name="configuration.p1.subtitle">Maximum scale</string>
+ <string name="configuration.p1.text">
+ The maximum scale has been set to 50dpi. You can zoom in until the image is very pixellated.
+ </string>
+ <string name="configuration.p2.subtitle">Minimum tile DPI</string>
+ <string name="configuration.p2.text">
+ The minimum tile DPI has been set to 50dpi, to reduce
+ memory usage. The next layer of tiles will not be loaded until the image is very pixellated.
+ </string>
+ <string name="configuration.p3.subtitle">Pan disabled</string>
+ <string name="configuration.p3.text">
+ Dragging has been disabled. You can only zoom in to the centre point.
+ </string>
+ <string name="configuration.p4.subtitle">Zoom disabled</string>
+ <string name="configuration.p4.text">
+ Zooming has been disabled. You can drag the image around.
+ </string>
+ <string name="configuration.p5.subtitle">Double tap style</string>
+ <string name="configuration.p5.text">
+ On double tap, the tapped point is now zoomed to the center of the screen instead of remaining in the same place.
+ </string>
+ <string name="configuration.p6.subtitle">Double tap style</string>
+ <string name="configuration.p6.text">On double tap, the zoom now happens immediately.</string>
+ <string name="configuration.p7.subtitle">Double tap scale</string>
+ <string name="configuration.p7.text">The double tap zoom scale has been set to 240dpi.</string>
+ <string name="configuration.p8.subtitle">Pan limit center</string>
+ <string name="configuration.p8.text">
+ The pan limit has been changed to PAN_LIMIT_CENTER. Panning stops when a corner reaches the centre of the screen.
+ </string>
+ <string name="configuration.p9.subtitle">Pan limit outside</string>
+ <string name="configuration.p9.text">
+ The pan limit has been changed to PAN_LIMIT_OUTSIDE. Panning stops when the image is just off screen.
+ </string>
+ <string name="configuration.p10.subtitle">Debug</string>
+ <string name="configuration.p10.text">
+ Debug has been enabled. This shows the tile boundaries and sizes.
+ </string>
+
+</resources> \ No newline at end of file
diff --git a/sample/src/main/res/values/style.xml b/sample/src/main/res/values/style.xml
new file mode 100644
index 0000000..023db6e
--- /dev/null
+++ b/sample/src/main/res/values/style.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <style name="sampleTheme" parent="@android:style/Theme.Holo">
+ <item name="android:actionBarStyle">@style/sampleActionBar</item>
+ <item name="android:windowBackground">@color/background</item>
+ </style>
+
+ <style name="sampleActionBar" parent="@android:style/Widget.Holo.ActionBar">
+ <item name="android:background">@color/actionBarBackground</item>
+ </style>
+
+ <style name="indexDivider">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">1px</item>
+ <item name="android:background">#333333</item>
+ </style>
+
+ <style name="indexLink">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:background">@drawable/buttonstate_transparent</item>
+ <item name="android:gravity">center_horizontal</item>
+ <item name="android:padding">10dp</item>
+ <item name="android:textSize">18sp</item>
+ </style>
+
+ <style name="fill">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">match_parent</item>
+ </style>
+
+ <style name="mainPanel">
+ <item name="android:layout_alignParentTop">true</item>
+ <item name="android:layout_above">@+id/footer</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">match_parent</item>
+ </style>
+
+ <style name="footer">
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_alignParentBottom">true</item>
+ <item name="android:background">#333</item>
+ </style>
+
+ <style name="footerNote">
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">match_parent</item>
+ <item name="android:layout_centerVertical">true</item>
+ <item name="android:padding">10dp</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textColor">#FFFFFF</item>
+ </style>
+
+ <style name="footerButton">
+ <item name="android:layout_width">wrap_content</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_centerVertical">true</item>
+ <item name="android:background">@drawable/buttonstate_transparent</item>
+ <item name="android:paddingLeft">8dp</item>
+ <item name="android:paddingRight">8dp</item>
+ <item name="android:paddingTop">18dp</item>
+ <item name="android:paddingBottom">18dp</item>
+ <item name="android:src">@drawable/previous</item>
+ </style>
+
+ <style name="previousButton" parent="@style/footerButton">
+ <item name="android:layout_alignParentStart">true</item>
+ <item name="android:src">@drawable/previous</item>
+ </style>
+
+ <style name="nextButton" parent="@style/footerButton">
+ <item name="android:layout_alignParentEnd">true</item>
+ <item name="android:src">@drawable/next</item>
+ </style>
+
+</resources>