add gesture library
|
|
@ -10,6 +10,7 @@
|
|||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/PdfView" />
|
||||
<option value="$PROJECT_DIR$/gestureimageview" />
|
||||
<option value="$PROJECT_DIR$/pdfviewsample" />
|
||||
</set>
|
||||
</option>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/Android-Pdf-Viewer-Library.iml" filepath="$PROJECT_DIR$/Android-Pdf-Viewer-Library.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/PdfView/PdfView.iml" filepath="$PROJECT_DIR$/PdfView/PdfView.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/gestureimageview/gestureimageview.iml" filepath="$PROJECT_DIR$/gestureimageview/gestureimageview.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/pdfviewsample/pdfviewsample.iml" filepath="$PROJECT_DIR$/pdfviewsample/pdfviewsample.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
|
|
|
|||
1480
.idea/workspace.xml
|
|
@ -8,7 +8,7 @@
|
|||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
|
||||
|
|
|
|||
|
|
@ -80,5 +80,6 @@
|
|||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 21 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="gestureimageview" exported="" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -1,18 +1,21 @@
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "23.0.2"
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "23.0.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 4
|
||||
targetSdkVersion 4
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 4
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':gestureimageview')
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="4"
|
||||
android:minSdkVersion="14"
|
||||
android:targetSdkVersion="4" />
|
||||
|
||||
<application />
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="4"
|
||||
android:minSdkVersion="14"
|
||||
android:targetSdkVersion="4" />
|
||||
|
||||
<application />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.polites.android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="7"
|
||||
android:targetSdkVersion="7" />
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.polites.android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="7"
|
||||
android:targetSdkVersion="7" />
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merger version="3"><dataSet config="unspecified"><source path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/build/intermediates/exploded-aar/Android-Pdf-Viewer-Library/gestureimageview/unspecified/res"/></dataSet><dataSet config="main"><source path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res"><file name="slide_in" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/anim/slide_in.xml" qualifiers="" type="anim"/><file name="slide_out" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/anim/slide_out.xml" qualifiers="" type="anim"/><file name="back01" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable/back01.png" qualifiers="" type="drawable"/><file name="back02" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable/back02.png" qualifiers="" type="drawable"/><file name="doc" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable/doc.png" qualifiers="" type="drawable"/><file name="folder" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable/folder.png" qualifiers="" type="drawable"/><file name="icon" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable/icon.png" qualifiers="" type="drawable"/><file name="left_arrow" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable/left_arrow.png" qualifiers="" type="drawable"/><file name="pdf" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable/pdf.png" qualifiers="" type="drawable"/><file name="right_arrow" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable/right_arrow.png" qualifiers="" type="drawable"/><file name="zoom_in" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable/zoom_in.png" qualifiers="" type="drawable"/><file name="zoom_out" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable/zoom_out.png" qualifiers="" type="drawable"/><file name="icon" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable-hdpi/icon.png" qualifiers="hdpi" type="drawable"/><file name="icon" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable-ldpi/icon.png" qualifiers="ldpi" type="drawable"/><file name="icon" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/drawable-mdpi/icon.png" qualifiers="mdpi" type="drawable"/><file name="dialog_pagenumber" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/dialog_pagenumber.xml" qualifiers="" type="layout"/><file name="graphics_view" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/graphics_view.xml" qualifiers="" type="layout"/><file name="main" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/main.xml" qualifiers="" type="layout"/><file name="navigation_overlay" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/navigation_overlay.xml" qualifiers="" type="layout"/><file name="pdf_file_password" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/pdf_file_password.xml" qualifiers="" type="layout"/><file name="scroll_layout" path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/scroll_layout.xml" qualifiers="" type="layout"/><file path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/values/color.xml" qualifiers=""><drawable name="violet">#9370DB</drawable><drawable name="white">#FFFFFFFF</drawable><drawable name="black">#000000</drawable><drawable name="blue">#000000FF</drawable></file><file path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/values/strings.xml" qualifiers=""><string name="hello">Hello World, PdfViewerActivity!</string><string name="app_name">PdfViewer</string></file></source><source path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/build/generated/res/rs/release"/><source path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/build/generated/res/resValues/release"/></dataSet><dataSet config="release"><source path="/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/release/res"/></dataSet><mergedItems/></merger>
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 Romain Guy
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="200"
|
||||
android:fromYDelta="100%"
|
||||
android:toYDelta="0%" />
|
||||
<alpha
|
||||
android:duration="200"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0" />
|
||||
</set>
|
||||
<!-- From: file:/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/anim/slide_in.xml -->
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2008 Romain Guy
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="200"
|
||||
android:fromYDelta="0%"
|
||||
android:toYDelta="100%" />
|
||||
<alpha
|
||||
android:duration="200"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0" />
|
||||
</set>
|
||||
<!-- From: file:/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/anim/slide_out.xml -->
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 942 B |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 536 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 526 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1006 B |
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2008 The Android Open Source Project
|
||||
|
||||
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.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/username_view"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_marginLeft="20dip"
|
||||
android:layout_marginRight="20dip"
|
||||
android:text="Page number:"
|
||||
android:inputType="number"
|
||||
android:gravity="left"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/pagenum_edit"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_marginLeft="20dip"
|
||||
android:layout_marginRight="20dip"
|
||||
android:scrollHorizontally="true"
|
||||
android:autoText="false"
|
||||
android:capitalize="none"
|
||||
android:inputType="phone"
|
||||
android:gravity="fill_horizontal"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||
|
||||
</LinearLayout>
|
||||
<!-- From: file:/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/dialog_pagenumber.xml -->
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<ImageView android:id="@+id/pdf_image"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:padding="5px"/>
|
||||
|
||||
</LinearLayout>
|
||||
<!-- From: file:/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/graphics_view.xml -->
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
>
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/hello"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<!-- From: file:/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/main.xml -->
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
android:paddingLeft="10dip"
|
||||
android:paddingTop="5dip"
|
||||
android:paddingRight="10dip"
|
||||
android:paddingBottom="4dip"
|
||||
|
||||
android:background="#99000000" >
|
||||
|
||||
<ImageButton android:id="@+id/zoom_out"
|
||||
android:text="Zoom Out"
|
||||
android:src="@drawable/zoom_out"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="10" />
|
||||
|
||||
<ImageButton android:id="@+id/zoom_in"
|
||||
android:text="Zoom In"
|
||||
android:src="@drawable/zoom_in"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="10" />
|
||||
|
||||
<TextView android:id="@+id/navigation_page_position_label"
|
||||
android:text="1/1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="60"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<ImageButton android:id="@+id/navigation_previous"
|
||||
android:text="Previous"
|
||||
android:src="@drawable/left_arrow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="10" />
|
||||
|
||||
<ImageButton android:id="@+id/navigation_next"
|
||||
android:text="Next"
|
||||
android:src="@drawable/right_arrow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="10" />
|
||||
|
||||
</LinearLayout>
|
||||
<!-- From: file:/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/navigation_overlay.xml -->
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (c) 2009 Ferenc Hechler - ferenc_hechler@users.sourceforge.net
|
||||
|
||||
This file is part of the Android PDF Viewer
|
||||
|
||||
The Android PDF Viewer is free software;
|
||||
you can redistribute it and/or modify it under the terms of the GNU
|
||||
General Public License as published by the Free Software Foundation;
|
||||
either version 2 of the License, or (at your option) any later version.
|
||||
|
||||
The Android PDF Viewer is distributed
|
||||
in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Android PDF Viewer
|
||||
if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- filename -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content" android:layout_height="wrap_content"
|
||||
android:layout_weight="0"
|
||||
android:paddingBottom="0dip"
|
||||
android:text="Password protected PDF-File:"/>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etPassword"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="60px"
|
||||
android:text=""
|
||||
android:layout_weight="10"
|
||||
android:hint="please enter password for PDF">
|
||||
<requestFocus />
|
||||
</EditText>
|
||||
|
||||
<!-- Buttons 'OK' + 'Exit' -->
|
||||
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="horizontal" >
|
||||
<Button android:id="@+id/btExit" android:layout_width="120px" android:layout_height="40px" android:text="Exit"></Button>
|
||||
<Button android:id="@+id/btOK" android:layout_width="120px" android:layout_height="40px" android:text="OK"></Button>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- From: file:/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/pdf_file_password.xml -->
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (c) 2009 Ferenc Hechler - ferenc_hechler@users.sourceforge.net
|
||||
|
||||
This file is part of the Android PDF Viewer
|
||||
|
||||
The Android PDF Viewer is free software;
|
||||
you can redistribute it and/or modify it under the terms of the GNU
|
||||
General Public License as published by the Free Software Foundation;
|
||||
either version 2 of the License, or (at your option) any later version.
|
||||
|
||||
The Android PDF Viewer is distributed
|
||||
in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with the Android PDF Viewer
|
||||
if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
-->
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
</ScrollView>
|
||||
<!-- From: file:/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/layout/scroll_layout.xml -->
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- From: file:/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/values/color.xml -->
|
||||
<eat-comment/>
|
||||
<drawable name="black">#000000</drawable>
|
||||
<drawable name="blue">#000000FF</drawable>
|
||||
<drawable name="violet">#9370DB</drawable>
|
||||
<drawable name="white">#FFFFFFFF</drawable>
|
||||
<!-- From: file:/Users/winney/git/Android-Pdf-Viewer-Library/PdfView/src/main/res/values/strings.xml -->
|
||||
<eat-comment/>
|
||||
<string name="app_name">PdfViewer</string>
|
||||
<string name="hello">Hello World, PdfViewerActivity!</string>
|
||||
</resources>
|
||||
|
|
@ -6,11 +6,14 @@ import android.graphics.Color;
|
|||
import android.graphics.RectF;
|
||||
import android.os.Handler;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.polites.android.GestureImageView;
|
||||
import com.sun.pdfview.PDFFile;
|
||||
import com.sun.pdfview.PDFImage;
|
||||
import com.sun.pdfview.PDFPage;
|
||||
|
|
@ -35,7 +38,7 @@ public class PdfView extends FullScrollView {
|
|||
private static final float ZOOM_INCREMENT = 1.5f;
|
||||
|
||||
private Bitmap mBi;
|
||||
private ImageView mImageView;
|
||||
private GestureImageView mImageView;
|
||||
private Handler uiHandler;
|
||||
ImageButton bZoomOut;
|
||||
ImageButton bZoomIn;
|
||||
|
|
@ -59,11 +62,12 @@ public class PdfView extends FullScrollView {
|
|||
PDFPaint.s_doAntiAlias = true;
|
||||
uiHandler = new Handler();
|
||||
LayoutParams matchLp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
|
||||
mImageView = new ImageView(context);
|
||||
mImageView = new GestureImageView(context);
|
||||
|
||||
setPageBitmap(null);
|
||||
updateImage();
|
||||
addView(mImageView, matchLp);
|
||||
setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
|
||||
setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
|
||||
setBackgroundColor(Color.LTGRAY);
|
||||
setHorizontalScrollBarEnabled(true);
|
||||
setHorizontalFadingEdgeEnabled(true);
|
||||
|
|
@ -79,6 +83,21 @@ public class PdfView extends FullScrollView {
|
|||
this.mPdfFile = mPdfFile;
|
||||
}
|
||||
|
||||
private int getDeviceWidth() {
|
||||
DisplayMetrics metric = new DisplayMetrics();
|
||||
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
|
||||
wm.getDefaultDisplay().getMetrics(metric);
|
||||
return metric.widthPixels; // 屏幕宽度(像素)
|
||||
|
||||
}
|
||||
|
||||
private int getDeviceHeight() {
|
||||
DisplayMetrics metric = new DisplayMetrics();
|
||||
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
|
||||
wm.getDefaultDisplay().getMetrics(metric);
|
||||
return metric.heightPixels; // 屏幕高度(像素)
|
||||
}
|
||||
|
||||
public void showPage(int page, float zoom) throws Exception {
|
||||
try {
|
||||
// free memory from previous page
|
||||
|
|
@ -90,6 +109,13 @@ public class PdfView extends FullScrollView {
|
|||
}
|
||||
float width = mPdfPage.getWidth();
|
||||
float height = mPdfPage.getHeight();
|
||||
if (getLayoutParams().height == ViewGroup.LayoutParams.MATCH_PARENT) {
|
||||
height *= getDeviceWidth() / width;
|
||||
}
|
||||
if (getLayoutParams().width == LayoutParams.MATCH_PARENT) {
|
||||
width = getDeviceWidth();
|
||||
}
|
||||
|
||||
RectF clip = null;
|
||||
Bitmap bi = mPdfPage.getImage((int) (width * zoom), (int) (height * zoom), clip, true, true);
|
||||
setPageBitmap(bi);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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 net.sf.andpdf.utils;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.util.FloatMath;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class MathUtils {
|
||||
|
||||
public static float distance(MotionEvent event) {
|
||||
float x = event.getX(0) - event.getX(1);
|
||||
float y = event.getY(0) - event.getY(1);
|
||||
return FloatMath.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
public static float distance(PointF p1, PointF p2) {
|
||||
float x = p1.x - p2.x;
|
||||
float y = p1.y - p2.y;
|
||||
return FloatMath.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
public static float distance(float x1, float y1, float x2, float y2) {
|
||||
float x = x1 - x2;
|
||||
float y = y1 - y2;
|
||||
return FloatMath.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
public static void midpoint(MotionEvent event, PointF point) {
|
||||
float x1 = event.getX(0);
|
||||
float y1 = event.getY(0);
|
||||
float x2 = event.getX(1);
|
||||
float y2 = event.getY(1);
|
||||
midpoint(x1, y1, x2, y2, point);
|
||||
}
|
||||
|
||||
public static void midpoint(float x1, float y1, float x2, float y2, PointF point) {
|
||||
point.x = (x1 + x2) / 2.0f;
|
||||
point.y = (y1 + y2) / 2.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates p1 around p2 by angle degrees.
|
||||
*
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @param angle
|
||||
*/
|
||||
public void rotate(PointF p1, PointF p2, float angle) {
|
||||
float px = p1.x;
|
||||
float py = p1.y;
|
||||
float ox = p2.x;
|
||||
float oy = p2.y;
|
||||
p1.x = (FloatMath.cos(angle) * (px - ox) - FloatMath.sin(angle) * (py - oy) + ox);
|
||||
p1.y = (FloatMath.sin(angle) * (px - ox) + FloatMath.cos(angle) * (py - oy) + oy);
|
||||
}
|
||||
|
||||
public static float angle(PointF p1, PointF p2) {
|
||||
return angle(p1.x, p1.y, p2.x, p2.y);
|
||||
}
|
||||
|
||||
public static float angle(float x1, float y1, float x2, float y2) {
|
||||
return (float) Math.atan2(y2 - y1, x2 - x1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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 net.sf.andpdf.utils;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.util.FloatMath;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class VectorF {
|
||||
|
||||
public float angle;
|
||||
public float length;
|
||||
|
||||
public final PointF start = new PointF();
|
||||
public final PointF end = new PointF();
|
||||
|
||||
public void calculateEndPoint() {
|
||||
end.x = FloatMath.cos(angle) * length + start.x;
|
||||
end.y = FloatMath.sin(angle) * length + start.y;
|
||||
}
|
||||
|
||||
public void setStart(PointF p) {
|
||||
this.start.x = p.x;
|
||||
this.start.y = p.y;
|
||||
}
|
||||
|
||||
public void setEnd(PointF p) {
|
||||
this.end.x = p.x;
|
||||
this.end.y = p.y;
|
||||
}
|
||||
|
||||
public void set(MotionEvent event) {
|
||||
this.start.x = event.getX(0);
|
||||
this.start.y = event.getY(0);
|
||||
this.end.x = event.getX(1);
|
||||
this.end.y = event.getY(1);
|
||||
}
|
||||
|
||||
public float calculateLength() {
|
||||
length = MathUtils.distance(start, end);
|
||||
return length;
|
||||
}
|
||||
|
||||
public float calculateAngle() {
|
||||
angle = MathUtils.angle(start, end);
|
||||
return angle;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
jar="/Users/winney/git/Android-Pdf-Viewer-Library/pdfviewsample/build/intermediates/exploded-aar/Android-Pdf-Viewer-Library/PdfView/unspecified/jars/classes.jar"
|
||||
jumboMode="false"
|
||||
revision="23.0.2"
|
||||
sha1="933be2f099767838f02cd4a28fc5ac4c219b327f">
|
||||
sha1="e7d6dd07e1cac71ea7611e16c5dcd8b3cba978dc">
|
||||
<dex dex="/Users/winney/git/Android-Pdf-Viewer-Library/pdfviewsample/build/intermediates/pre-dexed/debug/classes-dbc371ee905b36ce5cd278976d41c35b063e55b0.jar" />
|
||||
</item>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 19
|
||||
buildToolsVersion "19.1.0"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 7
|
||||
targetSdkVersion 7
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Automatically generated file. DO NOT MODIFY
|
||||
*/
|
||||
package com.polites.android;
|
||||
|
||||
public final class BuildConfig {
|
||||
public static final boolean DEBUG = false;
|
||||
public static final String APPLICATION_ID = "com.polites.android";
|
||||
public static final String BUILD_TYPE = "release";
|
||||
public static final String FLAVOR = "";
|
||||
public static final int VERSION_CODE = 1;
|
||||
public static final String VERSION_NAME = "";
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.polites.android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="7"
|
||||
android:targetSdkVersion="7" />
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.polites.android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk
|
||||
android:minSdkVersion="7"
|
||||
android:targetSdkVersion="7" />
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merger version="3"><dataSet config="main"><source path="/Users/winney/git/Android-Pdf-Viewer-Library/gestureimageview/src/main/assets"/></dataSet><dataSet config="release"><source path="/Users/winney/git/Android-Pdf-Viewer-Library/gestureimageview/src/release/assets"/></dataSet></merger>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merger version="3"><dataSet config="main"><source path="/Users/winney/git/Android-Pdf-Viewer-Library/gestureimageview/src/main/res"/><source path="/Users/winney/git/Android-Pdf-Viewer-Library/gestureimageview/build/generated/res/rs/release"/><source path="/Users/winney/git/Android-Pdf-Viewer-Library/gestureimageview/build/generated/res/resValues/release"/></dataSet><dataSet config="release"><source path="/Users/winney/git/Android-Pdf-Viewer-Library/gestureimageview/src/release/res"/></dataSet><mergedItems/></merger>
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
Manifest-Version: 1.0
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module external.linked.project.id=":gestureimageview" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="Android-Pdf-Viewer-Library" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="android-gradle" name="Android-Gradle">
|
||||
<configuration>
|
||||
<option name="GRADLE_PROJECT_PATH" value=":gestureimageview" />
|
||||
</configuration>
|
||||
</facet>
|
||||
<facet type="android" name="Android">
|
||||
<configuration>
|
||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
||||
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
|
||||
<afterSyncTasks>
|
||||
<task>generateDebugAndroidTestSources</task>
|
||||
<task>generateDebugSources</task>
|
||||
</afterSyncTasks>
|
||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="" />
|
||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
||||
<option name="LIBRARY_PROJECT" value="true" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Android API 19 Platform" jdkType="Android SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.polites.android"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="7" />
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
/**
|
||||
* @author Jason Polites
|
||||
*
|
||||
*/
|
||||
public interface Animation {
|
||||
|
||||
/**
|
||||
* Transforms the view.
|
||||
* @param view
|
||||
* @param diffTime
|
||||
* @return true if this animation should remain active. False otherwise.
|
||||
*/
|
||||
public boolean update(GestureImageView view, long time);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jason Polites
|
||||
*
|
||||
*/
|
||||
public class Animator extends Thread {
|
||||
|
||||
private GestureImageView view;
|
||||
private Animation animation;
|
||||
private boolean running = false;
|
||||
private boolean active = false;
|
||||
private long lastTime = -1L;
|
||||
|
||||
public Animator(GestureImageView view, String threadName) {
|
||||
super(threadName);
|
||||
this.view = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
running = true;
|
||||
|
||||
while(running) {
|
||||
|
||||
while(active && animation != null) {
|
||||
long time = System.currentTimeMillis();
|
||||
active = animation.update(view, time - lastTime);
|
||||
view.redraw();
|
||||
lastTime = time;
|
||||
|
||||
while(active) {
|
||||
try {
|
||||
if(view.waitForDraw(32)) { // 30Htz
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (InterruptedException ignore) {
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized(this) {
|
||||
if(running) {
|
||||
try {
|
||||
wait();
|
||||
}
|
||||
catch (InterruptedException ignore) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void finish() {
|
||||
running = false;
|
||||
active = false;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public void play(Animation transformer) {
|
||||
if(active) {
|
||||
cancel();
|
||||
}
|
||||
this.animation = transformer;
|
||||
|
||||
activate();
|
||||
}
|
||||
|
||||
public synchronized void activate() {
|
||||
lastTime = System.currentTimeMillis();
|
||||
active = true;
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
/**
|
||||
* @author Jason Polites
|
||||
*
|
||||
*/
|
||||
public class FlingAnimation implements Animation {
|
||||
|
||||
private float velocityX;
|
||||
private float velocityY;
|
||||
|
||||
private float factor = 0.95f;
|
||||
|
||||
private float threshold = 10;
|
||||
|
||||
private FlingAnimationListener listener;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.polites.android.Transformer#update(com.polites.android.GestureImageView, long)
|
||||
*/
|
||||
@Override
|
||||
public boolean update(GestureImageView view, long time) {
|
||||
float seconds = (float) time / 1000.0f;
|
||||
|
||||
float dx = velocityX * seconds;
|
||||
float dy = velocityY * seconds;
|
||||
|
||||
velocityX *= factor;
|
||||
velocityY *= factor;
|
||||
|
||||
boolean active = (Math.abs(velocityX) > threshold && Math.abs(velocityY) > threshold);
|
||||
|
||||
if(listener != null) {
|
||||
listener.onMove(dx, dy);
|
||||
|
||||
if(!active) {
|
||||
listener.onComplete();
|
||||
}
|
||||
}
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
public void setVelocityX(float velocityX) {
|
||||
this.velocityX = velocityX;
|
||||
}
|
||||
|
||||
public void setVelocityY(float velocityY) {
|
||||
this.velocityY = velocityY;
|
||||
}
|
||||
|
||||
public void setFactor(float factor) {
|
||||
this.factor = factor;
|
||||
}
|
||||
|
||||
public void setListener(FlingAnimationListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jason Polites
|
||||
*
|
||||
*/
|
||||
public interface FlingAnimationListener {
|
||||
|
||||
public void onMove(float x, float y);
|
||||
|
||||
public void onComplete();
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
import android.view.GestureDetector.SimpleOnGestureListener;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jason Polites
|
||||
*
|
||||
*/
|
||||
public class FlingListener extends SimpleOnGestureListener {
|
||||
|
||||
private float velocityX;
|
||||
private float velocityY;
|
||||
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
this.velocityX = velocityX;
|
||||
this.velocityY = velocityY;
|
||||
return true;
|
||||
}
|
||||
|
||||
public float getVelocityX() {
|
||||
return velocityX;
|
||||
}
|
||||
|
||||
public float getVelocityY() {
|
||||
return velocityY;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,713 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup.LayoutParams;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class GestureImageView extends ImageView {
|
||||
|
||||
public static final String GLOBAL_NS = "http://schemas.android.com/apk/res/android";
|
||||
public static final String LOCAL_NS = "http://schemas.polites.com/android";
|
||||
|
||||
private final Semaphore drawLock = new Semaphore(0);
|
||||
private Animator animator;
|
||||
|
||||
private Drawable drawable;
|
||||
|
||||
private float x = 0, y = 0;
|
||||
|
||||
private boolean layout = false;
|
||||
|
||||
private float scaleAdjust = 1.0f;
|
||||
private float startingScale = -1.0f;
|
||||
|
||||
private float scale = 1.0f;
|
||||
private float maxScale = 5.0f;
|
||||
private float minScale = 0.75f;
|
||||
private float fitScaleHorizontal = 1.0f;
|
||||
private float fitScaleVertical = 1.0f;
|
||||
private float rotation = 0.0f;
|
||||
|
||||
private float centerX;
|
||||
private float centerY;
|
||||
|
||||
private Float startX, startY;
|
||||
|
||||
private int hWidth;
|
||||
private int hHeight;
|
||||
|
||||
private int resId = -1;
|
||||
private boolean recycle = false;
|
||||
private boolean strict = false;
|
||||
|
||||
private int displayHeight;
|
||||
private int displayWidth;
|
||||
|
||||
private int alpha = 255;
|
||||
private ColorFilter colorFilter;
|
||||
|
||||
private int deviceOrientation = -1;
|
||||
private int imageOrientation;
|
||||
|
||||
private GestureImageViewListener gestureImageViewListener;
|
||||
private GestureImageViewTouchListener gestureImageViewTouchListener;
|
||||
|
||||
private OnTouchListener customOnTouchListener;
|
||||
private OnClickListener onClickListener;
|
||||
|
||||
public GestureImageView(Context context, AttributeSet attrs, int defStyle) {
|
||||
this(context, attrs);
|
||||
}
|
||||
|
||||
public GestureImageView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
String scaleType = attrs.getAttributeValue(GLOBAL_NS, "scaleType");
|
||||
|
||||
if (scaleType == null || scaleType.trim().length() == 0) {
|
||||
setScaleType(ScaleType.CENTER_INSIDE);
|
||||
}
|
||||
|
||||
String strStartX = attrs.getAttributeValue(LOCAL_NS, "start-x");
|
||||
String strStartY = attrs.getAttributeValue(LOCAL_NS, "start-y");
|
||||
|
||||
if (strStartX != null && strStartX.trim().length() > 0) {
|
||||
startX = Float.parseFloat(strStartX);
|
||||
}
|
||||
|
||||
if (strStartY != null && strStartY.trim().length() > 0) {
|
||||
startY = Float.parseFloat(strStartY);
|
||||
}
|
||||
|
||||
setStartingScale(attrs.getAttributeFloatValue(LOCAL_NS, "start-scale", startingScale));
|
||||
setMinScale(attrs.getAttributeFloatValue(LOCAL_NS, "min-scale", minScale));
|
||||
setMaxScale(attrs.getAttributeFloatValue(LOCAL_NS, "max-scale", maxScale));
|
||||
setStrict(attrs.getAttributeBooleanValue(LOCAL_NS, "strict", strict));
|
||||
setRecycle(attrs.getAttributeBooleanValue(LOCAL_NS, "recycle", recycle));
|
||||
|
||||
initImage();
|
||||
}
|
||||
|
||||
public GestureImageView(Context context) {
|
||||
super(context);
|
||||
setScaleType(ScaleType.CENTER_INSIDE);
|
||||
initImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
|
||||
if (drawable != null) {
|
||||
int orientation = getResources().getConfiguration().orientation;
|
||||
if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
displayHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||
|
||||
if (getLayoutParams().width == LayoutParams.WRAP_CONTENT) {
|
||||
float ratio = (float) getImageWidth() / (float) getImageHeight();
|
||||
displayWidth = Math.round((float) displayHeight * ratio);
|
||||
} else {
|
||||
displayWidth = MeasureSpec.getSize(widthMeasureSpec);
|
||||
}
|
||||
} else {
|
||||
displayWidth = MeasureSpec.getSize(widthMeasureSpec);
|
||||
if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) {
|
||||
float ratio = (float) getImageHeight() / (float) getImageWidth();
|
||||
displayHeight = Math.round((float) displayWidth * ratio);
|
||||
} else {
|
||||
displayHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
displayHeight = MeasureSpec.getSize(heightMeasureSpec);
|
||||
displayWidth = MeasureSpec.getSize(widthMeasureSpec);
|
||||
}
|
||||
|
||||
setMeasuredDimension(displayWidth, displayHeight);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
if (changed || !layout) {
|
||||
setupCanvas(displayWidth, displayHeight, getResources().getConfiguration().orientation);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setupCanvas(int measuredWidth, int measuredHeight, int orientation) {
|
||||
|
||||
if (deviceOrientation != orientation) {
|
||||
layout = false;
|
||||
deviceOrientation = orientation;
|
||||
}
|
||||
|
||||
if (drawable != null && !layout) {
|
||||
int imageWidth = getImageWidth();
|
||||
int imageHeight = getImageHeight();
|
||||
|
||||
hWidth = Math.round(((float) imageWidth / 2.0f));
|
||||
hHeight = Math.round(((float) imageHeight / 2.0f));
|
||||
|
||||
measuredWidth -= (getPaddingLeft() + getPaddingRight());
|
||||
measuredHeight -= (getPaddingTop() + getPaddingBottom());
|
||||
|
||||
computeCropScale(imageWidth, imageHeight, measuredWidth, measuredHeight);
|
||||
|
||||
if (startingScale <= 0.0f) {
|
||||
computeStartingScale(imageWidth, imageHeight, measuredWidth, measuredHeight);
|
||||
}
|
||||
|
||||
scaleAdjust = startingScale;
|
||||
|
||||
this.centerX = (float) measuredWidth / 2.0f;
|
||||
this.centerY = (float) measuredHeight / 2.0f;
|
||||
|
||||
if (startX == null) {
|
||||
x = centerX;
|
||||
} else {
|
||||
x = startX;
|
||||
}
|
||||
|
||||
if (startY == null) {
|
||||
y = centerY;
|
||||
} else {
|
||||
y = startY;
|
||||
}
|
||||
|
||||
gestureImageViewTouchListener = new GestureImageViewTouchListener(this, measuredWidth, measuredHeight);
|
||||
|
||||
if (isLandscape()) {
|
||||
gestureImageViewTouchListener.setMinScale(minScale * fitScaleHorizontal);
|
||||
} else {
|
||||
gestureImageViewTouchListener.setMinScale(minScale * fitScaleVertical);
|
||||
}
|
||||
|
||||
|
||||
gestureImageViewTouchListener.setMaxScale(maxScale * startingScale);
|
||||
|
||||
gestureImageViewTouchListener.setFitScaleHorizontal(fitScaleHorizontal);
|
||||
gestureImageViewTouchListener.setFitScaleVertical(fitScaleVertical);
|
||||
gestureImageViewTouchListener.setCanvasWidth(measuredWidth);
|
||||
gestureImageViewTouchListener.setCanvasHeight(measuredHeight);
|
||||
gestureImageViewTouchListener.setOnClickListener(onClickListener);
|
||||
|
||||
drawable.setBounds(-hWidth, -hHeight, hWidth, hHeight);
|
||||
|
||||
super.setOnTouchListener(new OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (customOnTouchListener != null) {
|
||||
customOnTouchListener.onTouch(v, event);
|
||||
}
|
||||
return gestureImageViewTouchListener.onTouch(v, event);
|
||||
}
|
||||
});
|
||||
|
||||
layout = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void computeCropScale(int imageWidth, int imageHeight, int measuredWidth, int measuredHeight) {
|
||||
fitScaleHorizontal = (float) measuredWidth / (float) imageWidth;
|
||||
fitScaleVertical = (float) measuredHeight / (float) imageHeight;
|
||||
}
|
||||
|
||||
protected void computeStartingScale(int imageWidth, int imageHeight, int measuredWidth, int measuredHeight) {
|
||||
switch (getScaleType()) {
|
||||
case CENTER:
|
||||
// Center the image in the view, but perform no scaling.
|
||||
startingScale = 1.0f;
|
||||
break;
|
||||
|
||||
case CENTER_CROP:
|
||||
// Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions
|
||||
// (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).
|
||||
startingScale = Math.max((float) measuredHeight / (float) imageHeight, (float) measuredWidth / (float) imageWidth);
|
||||
break;
|
||||
|
||||
case CENTER_INSIDE:
|
||||
|
||||
// Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions
|
||||
// (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding).
|
||||
float wRatio = (float) imageWidth / (float) measuredWidth;
|
||||
float hRatio = (float) imageHeight / (float) measuredHeight;
|
||||
|
||||
if (wRatio > hRatio) {
|
||||
startingScale = fitScaleHorizontal;
|
||||
} else {
|
||||
startingScale = fitScaleVertical;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isRecycled() {
|
||||
if (drawable != null && drawable instanceof BitmapDrawable) {
|
||||
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
|
||||
if (bitmap != null) {
|
||||
return bitmap.isRecycled();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void recycle() {
|
||||
if (recycle && drawable != null && drawable instanceof BitmapDrawable) {
|
||||
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
|
||||
if (bitmap != null) {
|
||||
bitmap.recycle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
if (layout) {
|
||||
if (drawable != null && !isRecycled()) {
|
||||
canvas.save();
|
||||
|
||||
float adjustedScale = scale * scaleAdjust;
|
||||
|
||||
canvas.translate(x, y);
|
||||
|
||||
if (rotation != 0.0f) {
|
||||
canvas.rotate(rotation);
|
||||
}
|
||||
|
||||
if (adjustedScale != 1.0f) {
|
||||
canvas.scale(adjustedScale, adjustedScale);
|
||||
}
|
||||
|
||||
drawable.draw(canvas);
|
||||
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
if (drawLock.availablePermits() <= 0) {
|
||||
drawLock.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a draw
|
||||
*
|
||||
* @param max time to wait for draw (ms)
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
public boolean waitForDraw(long timeout) throws InterruptedException {
|
||||
return drawLock.tryAcquire(timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
animator = new Animator(this, "GestureImageViewAnimator");
|
||||
animator.start();
|
||||
|
||||
if (resId >= 0 && drawable == null) {
|
||||
setImageResource(resId);
|
||||
}
|
||||
|
||||
super.onAttachedToWindow();
|
||||
}
|
||||
|
||||
public void animationStart(Animation animation) {
|
||||
if (animator != null) {
|
||||
animator.play(animation);
|
||||
}
|
||||
}
|
||||
|
||||
public void animationStop() {
|
||||
if (animator != null) {
|
||||
animator.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
if (animator != null) {
|
||||
animator.finish();
|
||||
}
|
||||
if (recycle && drawable != null && !isRecycled()) {
|
||||
recycle();
|
||||
drawable = null;
|
||||
}
|
||||
super.onDetachedFromWindow();
|
||||
}
|
||||
|
||||
protected void initImage() {
|
||||
if (this.drawable != null) {
|
||||
this.drawable.setAlpha(alpha);
|
||||
this.drawable.setFilterBitmap(true);
|
||||
if (colorFilter != null) {
|
||||
this.drawable.setColorFilter(colorFilter);
|
||||
}
|
||||
}
|
||||
|
||||
if (!layout) {
|
||||
requestLayout();
|
||||
redraw();
|
||||
}
|
||||
}
|
||||
|
||||
public void setImageBitmap(Bitmap image) {
|
||||
this.drawable = new BitmapDrawable(getResources(), image);
|
||||
initImage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageDrawable(Drawable drawable) {
|
||||
this.drawable = drawable;
|
||||
initImage();
|
||||
}
|
||||
|
||||
public void setImageResource(int id) {
|
||||
if (this.drawable != null) {
|
||||
this.recycle();
|
||||
}
|
||||
if (id >= 0) {
|
||||
this.resId = id;
|
||||
setImageDrawable(getContext().getResources().getDrawable(id));
|
||||
}
|
||||
}
|
||||
|
||||
public int getScaledWidth() {
|
||||
return Math.round(getImageWidth() * getScale());
|
||||
}
|
||||
|
||||
public int getScaledHeight() {
|
||||
return Math.round(getImageHeight() * getScale());
|
||||
}
|
||||
|
||||
public int getImageWidth() {
|
||||
if (drawable != null) {
|
||||
return drawable.getIntrinsicWidth();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getImageHeight() {
|
||||
if (drawable != null) {
|
||||
return drawable.getIntrinsicHeight();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void moveBy(float x, float y) {
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
}
|
||||
|
||||
public void setPosition(float x, float y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public void redraw() {
|
||||
postInvalidate();
|
||||
}
|
||||
|
||||
public void setMinScale(float min) {
|
||||
this.minScale = min;
|
||||
if (gestureImageViewTouchListener != null) {
|
||||
gestureImageViewTouchListener.setMinScale(min * fitScaleHorizontal);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMaxScale(float max) {
|
||||
this.maxScale = max;
|
||||
if (gestureImageViewTouchListener != null) {
|
||||
gestureImageViewTouchListener.setMaxScale(max * startingScale);
|
||||
}
|
||||
}
|
||||
|
||||
public void setScale(float scale) {
|
||||
scaleAdjust = scale;
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return scaleAdjust;
|
||||
}
|
||||
|
||||
public float getImageX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public float getImageY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public boolean isStrict() {
|
||||
return strict;
|
||||
}
|
||||
|
||||
public void setStrict(boolean strict) {
|
||||
this.strict = strict;
|
||||
}
|
||||
|
||||
public boolean isRecycle() {
|
||||
return recycle;
|
||||
}
|
||||
|
||||
public void setRecycle(boolean recycle) {
|
||||
this.recycle = recycle;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
x = centerX;
|
||||
y = centerY;
|
||||
scaleAdjust = startingScale;
|
||||
if (gestureImageViewTouchListener != null) {
|
||||
gestureImageViewTouchListener.reset();
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
|
||||
public void setRotation(float rotation) {
|
||||
this.rotation = rotation;
|
||||
}
|
||||
|
||||
public void setGestureImageViewListener(GestureImageViewListener pinchImageViewListener) {
|
||||
this.gestureImageViewListener = pinchImageViewListener;
|
||||
}
|
||||
|
||||
public GestureImageViewListener getGestureImageViewListener() {
|
||||
return gestureImageViewListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getDrawable() {
|
||||
return drawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
this.alpha = alpha;
|
||||
if (drawable != null) {
|
||||
drawable.setAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter cf) {
|
||||
this.colorFilter = cf;
|
||||
if (drawable != null) {
|
||||
drawable.setColorFilter(cf);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageURI(Uri mUri) {
|
||||
if ("content".equals(mUri.getScheme())) {
|
||||
try {
|
||||
String[] orientationColumn = {MediaStore.Images.Media.ORIENTATION};
|
||||
|
||||
Cursor cur = getContext().getContentResolver().query(mUri, orientationColumn, null, null, null);
|
||||
|
||||
if (cur != null && cur.moveToFirst()) {
|
||||
imageOrientation = cur.getInt(cur.getColumnIndex(orientationColumn[0]));
|
||||
}
|
||||
|
||||
InputStream in = null;
|
||||
|
||||
try {
|
||||
in = getContext().getContentResolver().openInputStream(mUri);
|
||||
Bitmap bmp = BitmapFactory.decodeStream(in);
|
||||
|
||||
if (imageOrientation != 0) {
|
||||
Matrix m = new Matrix();
|
||||
m.postRotate(imageOrientation);
|
||||
Bitmap rotated = Bitmap.createBitmap(bmp, 0, 0, bmp.getWidth(), bmp.getHeight(), m, true);
|
||||
bmp.recycle();
|
||||
setImageDrawable(new BitmapDrawable(getResources(), rotated));
|
||||
} else {
|
||||
setImageDrawable(new BitmapDrawable(getResources(), bmp));
|
||||
}
|
||||
} finally {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
|
||||
if (cur != null) {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.w("GestureImageView", "Unable to open content: " + mUri, e);
|
||||
}
|
||||
} else {
|
||||
setImageDrawable(Drawable.createFromPath(mUri.toString()));
|
||||
}
|
||||
|
||||
if (drawable == null) {
|
||||
Log.e("GestureImageView", "resolveUri failed on bad bitmap uri: " + mUri);
|
||||
// Don't try again.
|
||||
mUri = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Matrix getImageMatrix() {
|
||||
if (strict) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
return super.getImageMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScaleType(ScaleType scaleType) {
|
||||
if (scaleType == ScaleType.CENTER ||
|
||||
scaleType == ScaleType.CENTER_CROP ||
|
||||
scaleType == ScaleType.CENTER_INSIDE) {
|
||||
|
||||
super.setScaleType(scaleType);
|
||||
} else if (strict) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateDrawable(Drawable dr) {
|
||||
if (strict) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
super.invalidateDrawable(dr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] onCreateDrawableState(int extraSpace) {
|
||||
if (strict) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
return super.onCreateDrawableState(extraSpace);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAdjustViewBounds(boolean adjustViewBounds) {
|
||||
if (strict) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
super.setAdjustViewBounds(adjustViewBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageLevel(int level) {
|
||||
if (strict) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
super.setImageLevel(level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageMatrix(Matrix matrix) {
|
||||
if (strict) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageState(int[] state, boolean merge) {
|
||||
if (strict) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(boolean selected) {
|
||||
if (strict) {
|
||||
throw new UnsupportedOperationException("Not supported");
|
||||
}
|
||||
super.setSelected(selected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnTouchListener(OnTouchListener l) {
|
||||
this.customOnTouchListener = l;
|
||||
}
|
||||
|
||||
public float getCenterX() {
|
||||
return centerX;
|
||||
}
|
||||
|
||||
public float getCenterY() {
|
||||
return centerY;
|
||||
}
|
||||
|
||||
public boolean isLandscape() {
|
||||
return getImageWidth() >= getImageHeight();
|
||||
}
|
||||
|
||||
public boolean isPortrait() {
|
||||
return getImageWidth() <= getImageHeight();
|
||||
}
|
||||
|
||||
public void setStartingScale(float startingScale) {
|
||||
this.startingScale = startingScale;
|
||||
}
|
||||
|
||||
public void setStartingPosition(float x, float y) {
|
||||
this.startX = x;
|
||||
this.startY = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnClickListener(OnClickListener l) {
|
||||
this.onClickListener = l;
|
||||
|
||||
if (gestureImageViewTouchListener != null) {
|
||||
gestureImageViewTouchListener.setOnClickListener(l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the image dimensions are aligned with the orientation of the device.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isOrientationAligned() {
|
||||
if (deviceOrientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
return isLandscape();
|
||||
} else if (deviceOrientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
return isPortrait();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getDeviceOrientation() {
|
||||
return deviceOrientation;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
/**
|
||||
* @author jasonpolites
|
||||
*
|
||||
*/
|
||||
public interface GestureImageViewListener {
|
||||
|
||||
public void onTouch(float x, float y);
|
||||
|
||||
public void onScale(float scale);
|
||||
|
||||
public void onPosition(float x, float y);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,540 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.PointF;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.GestureDetector.SimpleOnGestureListener;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnTouchListener;
|
||||
|
||||
public class GestureImageViewTouchListener implements OnTouchListener {
|
||||
|
||||
private GestureImageView image;
|
||||
private OnClickListener onClickListener;
|
||||
|
||||
private final PointF current = new PointF();
|
||||
private final PointF last = new PointF();
|
||||
private final PointF next = new PointF();
|
||||
private final PointF midpoint = new PointF();
|
||||
|
||||
private final VectorF scaleVector = new VectorF();
|
||||
private final VectorF pinchVector = new VectorF();
|
||||
|
||||
private boolean touched = false;
|
||||
private boolean inZoom = false;
|
||||
|
||||
private float initialDistance;
|
||||
private float lastScale = 1.0f;
|
||||
private float currentScale = 1.0f;
|
||||
|
||||
private float boundaryLeft = 0;
|
||||
private float boundaryTop = 0;
|
||||
private float boundaryRight = 0;
|
||||
private float boundaryBottom = 0;
|
||||
|
||||
private float maxScale = 5.0f;
|
||||
private float minScale = 0.25f;
|
||||
private float fitScaleHorizontal = 1.0f;
|
||||
private float fitScaleVertical = 1.0f;
|
||||
|
||||
private int canvasWidth = 0;
|
||||
private int canvasHeight = 0;
|
||||
|
||||
private float centerX = 0;
|
||||
private float centerY = 0;
|
||||
|
||||
private float startingScale = 0;
|
||||
|
||||
private boolean canDragX = false;
|
||||
private boolean canDragY = false;
|
||||
|
||||
private boolean multiTouch = false;
|
||||
|
||||
private int displayWidth;
|
||||
private int displayHeight;
|
||||
|
||||
private int imageWidth;
|
||||
private int imageHeight;
|
||||
|
||||
private FlingListener flingListener;
|
||||
private FlingAnimation flingAnimation;
|
||||
private ZoomAnimation zoomAnimation;
|
||||
private MoveAnimation moveAnimation;
|
||||
private GestureDetector tapDetector;
|
||||
private GestureDetector flingDetector;
|
||||
private GestureImageViewListener imageListener;
|
||||
|
||||
public GestureImageViewTouchListener(final GestureImageView image, int displayWidth, int displayHeight) {
|
||||
super();
|
||||
|
||||
this.image = image;
|
||||
|
||||
this.displayWidth = displayWidth;
|
||||
this.displayHeight = displayHeight;
|
||||
|
||||
this.centerX = (float) displayWidth / 2.0f;
|
||||
this.centerY = (float) displayHeight / 2.0f;
|
||||
|
||||
this.imageWidth = image.getImageWidth();
|
||||
this.imageHeight = image.getImageHeight();
|
||||
|
||||
startingScale = image.getScale();
|
||||
|
||||
currentScale = startingScale;
|
||||
lastScale = startingScale;
|
||||
|
||||
boundaryRight = displayWidth;
|
||||
boundaryBottom = displayHeight;
|
||||
boundaryLeft = 0;
|
||||
boundaryTop = 0;
|
||||
|
||||
next.x = image.getImageX();
|
||||
next.y = image.getImageY();
|
||||
|
||||
flingListener = new FlingListener();
|
||||
flingAnimation = new FlingAnimation();
|
||||
zoomAnimation = new ZoomAnimation();
|
||||
moveAnimation = new MoveAnimation();
|
||||
|
||||
flingAnimation.setListener(new FlingAnimationListener() {
|
||||
@Override
|
||||
public void onMove(float x, float y) {
|
||||
handleDrag(current.x + x, current.y + y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {}
|
||||
});
|
||||
|
||||
zoomAnimation.setZoom(2.0f);
|
||||
zoomAnimation.setZoomAnimationListener(new ZoomAnimationListener() {
|
||||
@Override
|
||||
public void onZoom(float scale, float x, float y) {
|
||||
if(scale <= maxScale && scale >= minScale) {
|
||||
handleScale(scale, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
inZoom = false;
|
||||
handleUp();
|
||||
}
|
||||
});
|
||||
|
||||
moveAnimation.setMoveAnimationListener(new MoveAnimationListener() {
|
||||
|
||||
@Override
|
||||
public void onMove(float x, float y) {
|
||||
image.setPosition(x, y);
|
||||
image.redraw();
|
||||
}
|
||||
});
|
||||
|
||||
tapDetector = new GestureDetector(image.getContext(), new SimpleOnGestureListener() {
|
||||
@Override
|
||||
public boolean onDoubleTap(MotionEvent e) {
|
||||
startZoom(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
||||
if(!inZoom) {
|
||||
if(onClickListener != null) {
|
||||
onClickListener.onClick(image);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
flingDetector = new GestureDetector(image.getContext(), flingListener);
|
||||
imageListener = image.getGestureImageViewListener();
|
||||
|
||||
calculateBoundaries();
|
||||
}
|
||||
|
||||
private void startFling() {
|
||||
flingAnimation.setVelocityX(flingListener.getVelocityX());
|
||||
flingAnimation.setVelocityY(flingListener.getVelocityY());
|
||||
image.animationStart(flingAnimation);
|
||||
}
|
||||
|
||||
private void startZoom(MotionEvent e) {
|
||||
inZoom = true;
|
||||
zoomAnimation.reset();
|
||||
|
||||
float zoomTo;
|
||||
|
||||
if(image.isLandscape()) {
|
||||
if(image.getDeviceOrientation() == Configuration.ORIENTATION_PORTRAIT) {
|
||||
int scaledHeight = image.getScaledHeight();
|
||||
|
||||
if(scaledHeight < canvasHeight) {
|
||||
zoomTo = fitScaleVertical / currentScale;
|
||||
zoomAnimation.setTouchX(e.getX());
|
||||
zoomAnimation.setTouchY(image.getCenterY());
|
||||
}
|
||||
else {
|
||||
zoomTo = fitScaleHorizontal / currentScale;
|
||||
zoomAnimation.setTouchX(image.getCenterX());
|
||||
zoomAnimation.setTouchY(image.getCenterY());
|
||||
}
|
||||
}
|
||||
else {
|
||||
int scaledWidth = image.getScaledWidth();
|
||||
|
||||
if(scaledWidth == canvasWidth) {
|
||||
zoomTo = currentScale*4.0f;
|
||||
zoomAnimation.setTouchX(e.getX());
|
||||
zoomAnimation.setTouchY(e.getY());
|
||||
}
|
||||
else if(scaledWidth < canvasWidth) {
|
||||
zoomTo = fitScaleHorizontal / currentScale;
|
||||
zoomAnimation.setTouchX(image.getCenterX());
|
||||
zoomAnimation.setTouchY(e.getY());
|
||||
}
|
||||
else {
|
||||
zoomTo = fitScaleHorizontal / currentScale;
|
||||
zoomAnimation.setTouchX(image.getCenterX());
|
||||
zoomAnimation.setTouchY(image.getCenterY());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(image.getDeviceOrientation() == Configuration.ORIENTATION_PORTRAIT) {
|
||||
|
||||
int scaledHeight = image.getScaledHeight();
|
||||
|
||||
if(scaledHeight == canvasHeight) {
|
||||
zoomTo = currentScale*4.0f;
|
||||
zoomAnimation.setTouchX(e.getX());
|
||||
zoomAnimation.setTouchY(e.getY());
|
||||
}
|
||||
else if(scaledHeight < canvasHeight) {
|
||||
zoomTo = fitScaleVertical / currentScale;
|
||||
zoomAnimation.setTouchX(e.getX());
|
||||
zoomAnimation.setTouchY(image.getCenterY());
|
||||
}
|
||||
else {
|
||||
zoomTo = fitScaleVertical / currentScale;
|
||||
zoomAnimation.setTouchX(image.getCenterX());
|
||||
zoomAnimation.setTouchY(image.getCenterY());
|
||||
}
|
||||
}
|
||||
else {
|
||||
int scaledWidth = image.getScaledWidth();
|
||||
|
||||
if(scaledWidth < canvasWidth) {
|
||||
zoomTo = fitScaleHorizontal / currentScale;
|
||||
zoomAnimation.setTouchX(image.getCenterX());
|
||||
zoomAnimation.setTouchY(e.getY());
|
||||
}
|
||||
else {
|
||||
zoomTo = fitScaleVertical / currentScale;
|
||||
zoomAnimation.setTouchX(image.getCenterX());
|
||||
zoomAnimation.setTouchY(image.getCenterY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zoomAnimation.setZoom(zoomTo);
|
||||
image.animationStart(zoomAnimation);
|
||||
}
|
||||
|
||||
|
||||
private void stopAnimations() {
|
||||
image.animationStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
|
||||
if(!inZoom) {
|
||||
|
||||
if(!tapDetector.onTouchEvent(event)) {
|
||||
if(event.getPointerCount() == 1 && flingDetector.onTouchEvent(event)) {
|
||||
startFling();
|
||||
}
|
||||
|
||||
if(event.getAction() == MotionEvent.ACTION_UP) {
|
||||
handleUp();
|
||||
}
|
||||
else if(event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
stopAnimations();
|
||||
|
||||
last.x = event.getX();
|
||||
last.y = event.getY();
|
||||
|
||||
if(imageListener != null) {
|
||||
imageListener.onTouch(last.x, last.y);
|
||||
}
|
||||
|
||||
touched = true;
|
||||
}
|
||||
else if(event.getAction() == MotionEvent.ACTION_MOVE) {
|
||||
if(event.getPointerCount() > 1) {
|
||||
multiTouch = true;
|
||||
if(initialDistance > 0) {
|
||||
|
||||
pinchVector.set(event);
|
||||
pinchVector.calculateLength();
|
||||
|
||||
float distance = pinchVector.length;
|
||||
|
||||
if(initialDistance != distance) {
|
||||
|
||||
float newScale = (distance / initialDistance) * lastScale;
|
||||
|
||||
if(newScale <= maxScale) {
|
||||
scaleVector.length *= newScale;
|
||||
|
||||
scaleVector.calculateEndPoint();
|
||||
|
||||
scaleVector.length /= newScale;
|
||||
|
||||
float newX = scaleVector.end.x;
|
||||
float newY = scaleVector.end.y;
|
||||
|
||||
handleScale(newScale, newX, newY);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
initialDistance = MathUtils.distance(event);
|
||||
|
||||
MathUtils.midpoint(event, midpoint);
|
||||
|
||||
scaleVector.setStart(midpoint);
|
||||
scaleVector.setEnd(next);
|
||||
|
||||
scaleVector.calculateLength();
|
||||
scaleVector.calculateAngle();
|
||||
|
||||
scaleVector.length /= lastScale;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!touched) {
|
||||
touched = true;
|
||||
last.x = event.getX();
|
||||
last.y = event.getY();
|
||||
next.x = image.getImageX();
|
||||
next.y = image.getImageY();
|
||||
}
|
||||
else if(!multiTouch) {
|
||||
if(handleDrag(event.getX(), event.getY())) {
|
||||
image.redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void handleUp() {
|
||||
|
||||
multiTouch = false;
|
||||
|
||||
initialDistance = 0;
|
||||
lastScale = currentScale;
|
||||
|
||||
if(!canDragX) {
|
||||
next.x = centerX;
|
||||
}
|
||||
|
||||
if(!canDragY) {
|
||||
next.y = centerY;
|
||||
}
|
||||
|
||||
boundCoordinates();
|
||||
|
||||
if(!canDragX && !canDragY) {
|
||||
|
||||
if(image.isLandscape()) {
|
||||
currentScale = fitScaleHorizontal;
|
||||
lastScale = fitScaleHorizontal;
|
||||
}
|
||||
else {
|
||||
currentScale = fitScaleVertical;
|
||||
lastScale = fitScaleVertical;
|
||||
}
|
||||
}
|
||||
|
||||
image.setScale(currentScale);
|
||||
image.setPosition(next.x, next.y);
|
||||
|
||||
if(imageListener != null) {
|
||||
imageListener.onScale(currentScale);
|
||||
imageListener.onPosition(next.x, next.y);
|
||||
}
|
||||
|
||||
image.redraw();
|
||||
}
|
||||
|
||||
protected void handleScale(float scale, float x, float y) {
|
||||
|
||||
currentScale = scale;
|
||||
|
||||
if(currentScale > maxScale) {
|
||||
currentScale = maxScale;
|
||||
}
|
||||
else if (currentScale < minScale) {
|
||||
currentScale = minScale;
|
||||
}
|
||||
else {
|
||||
next.x = x;
|
||||
next.y = y;
|
||||
}
|
||||
|
||||
calculateBoundaries();
|
||||
|
||||
image.setScale(currentScale);
|
||||
image.setPosition(next.x, next.y);
|
||||
|
||||
if(imageListener != null) {
|
||||
imageListener.onScale(currentScale);
|
||||
imageListener.onPosition(next.x, next.y);
|
||||
}
|
||||
|
||||
image.redraw();
|
||||
}
|
||||
|
||||
protected boolean handleDrag(float x, float y) {
|
||||
current.x = x;
|
||||
current.y = y;
|
||||
|
||||
float diffX = (current.x - last.x);
|
||||
float diffY = (current.y - last.y);
|
||||
|
||||
if(diffX != 0 || diffY != 0) {
|
||||
|
||||
if(canDragX) next.x += diffX;
|
||||
if(canDragY) next.y += diffY;
|
||||
|
||||
boundCoordinates();
|
||||
|
||||
last.x = current.x;
|
||||
last.y = current.y;
|
||||
|
||||
if(canDragX || canDragY) {
|
||||
image.setPosition(next.x, next.y);
|
||||
|
||||
if(imageListener != null) {
|
||||
imageListener.onPosition(next.x, next.y);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
currentScale = startingScale;
|
||||
next.x = centerX;
|
||||
next.y = centerY;
|
||||
calculateBoundaries();
|
||||
image.setScale(currentScale);
|
||||
image.setPosition(next.x, next.y);
|
||||
image.redraw();
|
||||
}
|
||||
|
||||
|
||||
public float getMaxScale() {
|
||||
return maxScale;
|
||||
}
|
||||
|
||||
public void setMaxScale(float maxScale) {
|
||||
this.maxScale = maxScale;
|
||||
}
|
||||
|
||||
public float getMinScale() {
|
||||
return minScale;
|
||||
}
|
||||
|
||||
public void setMinScale(float minScale) {
|
||||
this.minScale = minScale;
|
||||
}
|
||||
|
||||
public void setOnClickListener(OnClickListener onClickListener) {
|
||||
this.onClickListener = onClickListener;
|
||||
}
|
||||
|
||||
protected void setCanvasWidth(int canvasWidth) {
|
||||
this.canvasWidth = canvasWidth;
|
||||
}
|
||||
|
||||
protected void setCanvasHeight(int canvasHeight) {
|
||||
this.canvasHeight = canvasHeight;
|
||||
}
|
||||
|
||||
protected void setFitScaleHorizontal(float fitScale) {
|
||||
this.fitScaleHorizontal = fitScale;
|
||||
}
|
||||
|
||||
protected void setFitScaleVertical(float fitScaleVertical) {
|
||||
this.fitScaleVertical = fitScaleVertical;
|
||||
}
|
||||
|
||||
protected void boundCoordinates() {
|
||||
if(next.x < boundaryLeft) {
|
||||
next.x = boundaryLeft;
|
||||
}
|
||||
else if(next.x > boundaryRight) {
|
||||
next.x = boundaryRight;
|
||||
}
|
||||
|
||||
if(next.y < boundaryTop) {
|
||||
next.y = boundaryTop;
|
||||
}
|
||||
else if(next.y > boundaryBottom) {
|
||||
next.y = boundaryBottom;
|
||||
}
|
||||
}
|
||||
|
||||
protected void calculateBoundaries() {
|
||||
|
||||
int effectiveWidth = Math.round( (float) imageWidth * currentScale );
|
||||
int effectiveHeight = Math.round( (float) imageHeight * currentScale );
|
||||
|
||||
canDragX = effectiveWidth > displayWidth;
|
||||
canDragY = effectiveHeight > displayHeight;
|
||||
|
||||
if(canDragX) {
|
||||
float diff = (float)(effectiveWidth - displayWidth) / 2.0f;
|
||||
boundaryLeft = centerX - diff;
|
||||
boundaryRight = centerX + diff;
|
||||
}
|
||||
|
||||
if(canDragY) {
|
||||
float diff = (float)(effectiveHeight - displayHeight) / 2.0f;
|
||||
boundaryTop = centerY - diff;
|
||||
boundaryBottom = centerY + diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.util.FloatMath;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class MathUtils {
|
||||
|
||||
public static float distance(MotionEvent event) {
|
||||
float x = event.getX(0) - event.getX(1);
|
||||
float y = event.getY(0) - event.getY(1);
|
||||
return FloatMath.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
public static float distance(PointF p1, PointF p2) {
|
||||
float x = p1.x - p2.x;
|
||||
float y = p1.y - p2.y;
|
||||
return FloatMath.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
public static float distance(float x1, float y1, float x2, float y2) {
|
||||
float x = x1 - x2;
|
||||
float y = y1 - y2;
|
||||
return FloatMath.sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
public static void midpoint(MotionEvent event, PointF point) {
|
||||
float x1 = event.getX(0);
|
||||
float y1 = event.getY(0);
|
||||
float x2 = event.getX(1);
|
||||
float y2 = event.getY(1);
|
||||
midpoint(x1, y1, x2, y2, point);
|
||||
}
|
||||
|
||||
public static void midpoint(float x1, float y1, float x2, float y2, PointF point) {
|
||||
point.x = (x1 + x2) / 2.0f;
|
||||
point.y = (y1 + y2) / 2.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotates p1 around p2 by angle degrees.
|
||||
*
|
||||
* @param p1
|
||||
* @param p2
|
||||
* @param angle
|
||||
*/
|
||||
public void rotate(PointF p1, PointF p2, float angle) {
|
||||
float px = p1.x;
|
||||
float py = p1.y;
|
||||
float ox = p2.x;
|
||||
float oy = p2.y;
|
||||
p1.x = (FloatMath.cos(angle) * (px - ox) - FloatMath.sin(angle) * (py - oy) + ox);
|
||||
p1.y = (FloatMath.sin(angle) * (px - ox) + FloatMath.cos(angle) * (py - oy) + oy);
|
||||
}
|
||||
|
||||
public static float angle(PointF p1, PointF p2) {
|
||||
return angle(p1.x, p1.y, p2.x, p2.y);
|
||||
}
|
||||
|
||||
public static float angle(float x1, float y1, float x2, float y2) {
|
||||
return (float) Math.atan2(y2 - y1, x2 - x1);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jason Polites
|
||||
*
|
||||
*/
|
||||
public class MoveAnimation implements Animation {
|
||||
|
||||
private boolean firstFrame = true;
|
||||
|
||||
private float startX;
|
||||
private float startY;
|
||||
|
||||
private float targetX;
|
||||
private float targetY;
|
||||
private long animationTimeMS = 100;
|
||||
private long totalTime = 0;
|
||||
|
||||
private MoveAnimationListener moveAnimationListener;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.polites.android.Animation#update(com.polites.android.GestureImageView, long)
|
||||
*/
|
||||
@Override
|
||||
public boolean update(GestureImageView view, long time) {
|
||||
totalTime += time;
|
||||
|
||||
if(firstFrame) {
|
||||
firstFrame = false;
|
||||
startX = view.getImageX();
|
||||
startY = view.getImageY();
|
||||
}
|
||||
|
||||
if(totalTime < animationTimeMS) {
|
||||
|
||||
float ratio = (float) totalTime / animationTimeMS;
|
||||
|
||||
float newX = ((targetX - startX) * ratio) + startX;
|
||||
float newY = ((targetY - startY) * ratio) + startY;
|
||||
|
||||
if(moveAnimationListener != null) {
|
||||
moveAnimationListener.onMove(newX, newY);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if(moveAnimationListener != null) {
|
||||
moveAnimationListener.onMove(targetX, targetY);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
firstFrame = true;
|
||||
totalTime = 0;
|
||||
}
|
||||
|
||||
|
||||
public float getTargetX() {
|
||||
return targetX;
|
||||
}
|
||||
|
||||
|
||||
public void setTargetX(float targetX) {
|
||||
this.targetX = targetX;
|
||||
}
|
||||
|
||||
|
||||
public float getTargetY() {
|
||||
return targetY;
|
||||
}
|
||||
|
||||
public void setTargetY(float targetY) {
|
||||
this.targetY = targetY;
|
||||
}
|
||||
|
||||
public long getAnimationTimeMS() {
|
||||
return animationTimeMS;
|
||||
}
|
||||
|
||||
public void setAnimationTimeMS(long animationTimeMS) {
|
||||
this.animationTimeMS = animationTimeMS;
|
||||
}
|
||||
|
||||
public void setMoveAnimationListener(MoveAnimationListener moveAnimationListener) {
|
||||
this.moveAnimationListener = moveAnimationListener;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jason Polites
|
||||
*
|
||||
*/
|
||||
public interface MoveAnimationListener {
|
||||
|
||||
public void onMove(float x, float y);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
import android.graphics.PointF;
|
||||
import android.util.FloatMath;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
public class VectorF {
|
||||
|
||||
public float angle;
|
||||
public float length;
|
||||
|
||||
public final PointF start = new PointF();
|
||||
public final PointF end = new PointF();
|
||||
|
||||
public void calculateEndPoint() {
|
||||
end.x = FloatMath.cos(angle) * length + start.x;
|
||||
end.y = FloatMath.sin(angle) * length + start.y;
|
||||
}
|
||||
|
||||
public void setStart(PointF p) {
|
||||
this.start.x = p.x;
|
||||
this.start.y = p.y;
|
||||
}
|
||||
|
||||
public void setEnd(PointF p) {
|
||||
this.end.x = p.x;
|
||||
this.end.y = p.y;
|
||||
}
|
||||
|
||||
public void set(MotionEvent event) {
|
||||
this.start.x = event.getX(0);
|
||||
this.start.y = event.getY(0);
|
||||
this.end.x = event.getX(1);
|
||||
this.end.y = event.getY(1);
|
||||
}
|
||||
|
||||
public float calculateLength() {
|
||||
length = MathUtils.distance(start, end);
|
||||
return length;
|
||||
}
|
||||
|
||||
public float calculateAngle() {
|
||||
angle = MathUtils.angle(start, end);
|
||||
return angle;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
import android.graphics.PointF;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jason Polites
|
||||
*
|
||||
*/
|
||||
public class ZoomAnimation implements Animation {
|
||||
|
||||
private boolean firstFrame = true;
|
||||
|
||||
private float touchX;
|
||||
private float touchY;
|
||||
|
||||
private float zoom;
|
||||
|
||||
private float startX;
|
||||
private float startY;
|
||||
private float startScale;
|
||||
|
||||
private float xDiff;
|
||||
private float yDiff;
|
||||
private float scaleDiff;
|
||||
|
||||
private long animationLengthMS = 200;
|
||||
private long totalTime = 0;
|
||||
|
||||
private ZoomAnimationListener zoomAnimationListener;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see com.polites.android.Animation#update(com.polites.android.GestureImageView, long)
|
||||
*/
|
||||
@Override
|
||||
public boolean update(GestureImageView view, long time) {
|
||||
if(firstFrame) {
|
||||
firstFrame = false;
|
||||
|
||||
startX = view.getImageX();
|
||||
startY = view.getImageY();
|
||||
startScale = view.getScale();
|
||||
scaleDiff = (zoom * startScale) - startScale;
|
||||
|
||||
if(scaleDiff > 0) {
|
||||
// Calculate destination for midpoint
|
||||
VectorF vector = new VectorF();
|
||||
|
||||
// Set the touch point as start because we want to move the end
|
||||
vector.setStart(new PointF(touchX, touchY));
|
||||
vector.setEnd(new PointF(startX, startY));
|
||||
|
||||
vector.calculateAngle();
|
||||
|
||||
// Get the current length
|
||||
float length = vector.calculateLength();
|
||||
|
||||
// Multiply length by zoom to get the new length
|
||||
vector.length = length*zoom;
|
||||
|
||||
// Now deduce the new endpoint
|
||||
vector.calculateEndPoint();
|
||||
|
||||
xDiff = vector.end.x - startX;
|
||||
yDiff = vector.end.y - startY;
|
||||
}
|
||||
else {
|
||||
// Zoom out to center
|
||||
xDiff = view.getCenterX() - startX;
|
||||
yDiff = view.getCenterY() - startY;
|
||||
}
|
||||
}
|
||||
|
||||
totalTime += time;
|
||||
|
||||
float ratio = (float) totalTime / (float) animationLengthMS;
|
||||
|
||||
if(ratio < 1) {
|
||||
|
||||
if(ratio > 0) {
|
||||
// we still have time left
|
||||
float newScale = (ratio * scaleDiff) + startScale;
|
||||
float newX = (ratio * xDiff) + startX;
|
||||
float newY = (ratio * yDiff) + startY;
|
||||
|
||||
if(zoomAnimationListener != null) {
|
||||
zoomAnimationListener.onZoom(newScale, newX, newY);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
||||
float newScale = scaleDiff + startScale;
|
||||
float newX = xDiff + startX;
|
||||
float newY = yDiff + startY;
|
||||
|
||||
if(zoomAnimationListener != null) {
|
||||
zoomAnimationListener.onZoom(newScale, newX, newY);
|
||||
zoomAnimationListener.onComplete();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
firstFrame = true;
|
||||
totalTime = 0;
|
||||
}
|
||||
|
||||
public float getZoom() {
|
||||
return zoom;
|
||||
}
|
||||
|
||||
public void setZoom(float zoom) {
|
||||
this.zoom = zoom;
|
||||
}
|
||||
|
||||
public float getTouchX() {
|
||||
return touchX;
|
||||
}
|
||||
|
||||
public void setTouchX(float touchX) {
|
||||
this.touchX = touchX;
|
||||
}
|
||||
|
||||
public float getTouchY() {
|
||||
return touchY;
|
||||
}
|
||||
|
||||
public void setTouchY(float touchY) {
|
||||
this.touchY = touchY;
|
||||
}
|
||||
|
||||
public long getAnimationLengthMS() {
|
||||
return animationLengthMS;
|
||||
}
|
||||
|
||||
public void setAnimationLengthMS(long animationLengthMS) {
|
||||
this.animationLengthMS = animationLengthMS;
|
||||
}
|
||||
|
||||
public ZoomAnimationListener getZoomAnimationListener() {
|
||||
return zoomAnimationListener;
|
||||
}
|
||||
|
||||
public void setZoomAnimationListener(ZoomAnimationListener zoomAnimationListener) {
|
||||
this.zoomAnimationListener = zoomAnimationListener;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2012 Jason Polites
|
||||
*
|
||||
* 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.polites.android;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jason Polites
|
||||
*
|
||||
*/
|
||||
public interface ZoomAnimationListener {
|
||||
public void onZoom(float scale, float x, float y);
|
||||
public void onComplete();
|
||||
}
|
||||
|
|
@ -7,22 +7,10 @@ The following files were *not* copied into the new Gradle project; you
|
|||
should evaluate whether these are still needed in your project and if
|
||||
so manually move them:
|
||||
|
||||
* .idea/
|
||||
* .idea/.name
|
||||
* .idea/compiler.xml
|
||||
* .idea/copyright/
|
||||
* .idea/copyright/profiles_settings.xml
|
||||
* .idea/libraries/
|
||||
* .idea/libraries/PdfViewer.xml
|
||||
* .idea/misc.xml
|
||||
* .idea/modules.xml
|
||||
* .idea/vcs.xml
|
||||
* .idea/workspace.xml
|
||||
* Android-Pdf-Viewer-Library.iml
|
||||
* PdfViewer.jar
|
||||
* README.txt
|
||||
* .DS_Store
|
||||
* .gitignore
|
||||
* build.xml
|
||||
* default.properties
|
||||
* gesture-imageview.iml
|
||||
* proguard.cfg
|
||||
|
||||
Moved Files:
|
||||
|
|
@ -30,28 +18,11 @@ Moved Files:
|
|||
Android Gradle projects use a different directory structure than ADT
|
||||
Eclipse projects. Here's how the projects were restructured:
|
||||
|
||||
* AndroidManifest.xml => app/src/main/AndroidManifest.xml
|
||||
* crypto-src/ => app/src/main/java/
|
||||
* res/ => app/src/main/res/
|
||||
* src/ => app/src/main/java/
|
||||
* src/com/sun/pdfview/.cvsignore => app/src/main/resources/com/sun/pdfview/.cvsignore
|
||||
* src/com/sun/pdfview/decode/CCITTCodes => app/src/main/resources/com/sun/pdfview/decode/CCITTCodes
|
||||
* src/com/sun/pdfview/font/res/BaseFonts.properties => app/src/main/resources/com/sun/pdfview/font/res/BaseFonts.properties
|
||||
* src/com/sun/pdfview/font/res/d050000l.pfb => app/src/main/resources/com/sun/pdfview/font/res/d050000l.pfb
|
||||
* src/com/sun/pdfview/font/res/n019003l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n019003l.pfb
|
||||
* src/com/sun/pdfview/font/res/n019004l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n019004l.pfb
|
||||
* src/com/sun/pdfview/font/res/n019023l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n019023l.pfb
|
||||
* src/com/sun/pdfview/font/res/n019024l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n019024l.pfb
|
||||
* src/com/sun/pdfview/font/res/n021003l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n021003l.pfb
|
||||
* src/com/sun/pdfview/font/res/n021004l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n021004l.pfb
|
||||
* src/com/sun/pdfview/font/res/n021023l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n021023l.pfb
|
||||
* src/com/sun/pdfview/font/res/n021024l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n021024l.pfb
|
||||
* src/com/sun/pdfview/font/res/n022003l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n022003l.pfb
|
||||
* src/com/sun/pdfview/font/res/n022004l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n022004l.pfb
|
||||
* src/com/sun/pdfview/font/res/n022023l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n022023l.pfb
|
||||
* src/com/sun/pdfview/font/res/n022024l.pfb => app/src/main/resources/com/sun/pdfview/font/res/n022024l.pfb
|
||||
* src/com/sun/pdfview/font/res/s050000l.pfb => app/src/main/resources/com/sun/pdfview/font/res/s050000l.pfb
|
||||
* src/com/sun/pdfview/font/ttf/resource/glyphlist.txt => app/src/main/resources/com/sun/pdfview/font/ttf/resource/glyphlist.txt
|
||||
* AndroidManifest.xml => gestureimageview/src/main/AndroidManifest.xml
|
||||
* src/ => gestureimageview/src/main/java/
|
||||
* src/.DS_Store => gestureimageview/src/main/resources/.DS_Store
|
||||
* src/com/.DS_Store => gestureimageview/src/main/resources/com/.DS_Store
|
||||
* src/com/polites/.DS_Store => gestureimageview/src/main/resources/com/polites/.DS_Store
|
||||
|
||||
Next Steps:
|
||||
-----------
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
<net.sf.andpdf.pdfviewer.gui.PdfView
|
||||
android:id="@+id/pdf_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="20dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
|||