├── .classpath
├── .gitignore
├── .project
├── AndroidManifest.xml
├── README.md
├── proguard.cfg
├── project.properties
├── res
├── drawable-hdpi
│ ├── bg_foot.png
│ ├── bg_footbar.png
│ ├── bg_title.png
│ ├── btn_sx.png
│ ├── btn_xr.png
│ ├── dk.jpg
│ ├── home_btn_bg_d.png
│ ├── home_btn_bg_n.png
│ ├── home_btn_bg_s.png
│ ├── ic_launcher.png
│ ├── ico_dp01.png
│ ├── ico_gd01.png
│ ├── ico_tt01.png
│ ├── ico_zh01.png
│ ├── ico_zy01.png
│ ├── radio_bg.xml
│ ├── shelf_bkg.png
│ ├── storm.jpg
│ └── top.gif
├── drawable-ldpi
│ ├── ic_launcher.png
│ └── text.png
├── drawable-mdpi
│ ├── focused_application_background.9.png
│ ├── ic_launcher.png
│ ├── mainbg.jpg
│ └── pressed_application_background.9.png
├── drawable
│ ├── item_selector.xml
│ ├── itemcolor.xml
│ └── itemsize.xml
├── layout
│ ├── main.xml
│ ├── mainmenu.xml
│ └── relative.xml
├── menu
│ └── game_menu.xml
└── values
│ ├── arrays.xml
│ ├── strings.xml
│ └── styles.xml
└── src
└── com
├── ebook
├── EbookActivity.java
├── MainMenu.java
├── bookpage
│ ├── BookPageFactory.java
│ └── PageWidget.java
└── scansd
│ ├── BookMark.java
│ └── ScanSD.java
└── sqlite
└── DbHelper.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 |
15 | # Local configuration file (sdk path, etc)
16 | local.properties
17 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | ebook
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
12 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ebook
2 | =====
3 |
4 | 使用赛贝尔曲线的电子书,可以随意翻卷 The first version, copy from http://www.eoeandroid.com/forum.php?mod=viewthread&tid=147987&extra=page%3D1&page=1
--------------------------------------------------------------------------------
/proguard.cfg:
--------------------------------------------------------------------------------
1 | -optimizationpasses 5
2 | -dontusemixedcaseclassnames
3 | -dontskipnonpubliclibraryclasses
4 | -dontpreverify
5 | -verbose
6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
7 |
8 | -keep public class * extends android.app.Activity
9 | -keep public class * extends android.app.Application
10 | -keep public class * extends android.app.Service
11 | -keep public class * extends android.content.BroadcastReceiver
12 | -keep public class * extends android.content.ContentProvider
13 | -keep public class * extends android.app.backup.BackupAgentHelper
14 | -keep public class * extends android.preference.Preference
15 | -keep public class com.android.vending.licensing.ILicensingService
16 |
17 | -keepclasseswithmembernames class * {
18 | native ;
19 | }
20 |
21 | -keepclasseswithmembers class * {
22 | public (android.content.Context, android.util.AttributeSet);
23 | }
24 |
25 | -keepclasseswithmembers class * {
26 | public (android.content.Context, android.util.AttributeSet, int);
27 | }
28 |
29 | -keepclassmembers class * extends android.app.Activity {
30 | public void *(android.view.View);
31 | }
32 |
33 | -keepclassmembers enum * {
34 | public static **[] values();
35 | public static ** valueOf(java.lang.String);
36 | }
37 |
38 | -keep class * implements android.os.Parcelable {
39 | public static final android.os.Parcelable$Creator *;
40 | }
41 |
--------------------------------------------------------------------------------
/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=android-10
12 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/bg_foot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/bg_foot.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/bg_footbar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/bg_footbar.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/bg_title.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/bg_title.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_sx.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/btn_sx.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/btn_xr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/btn_xr.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/dk.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/dk.jpg
--------------------------------------------------------------------------------
/res/drawable-hdpi/home_btn_bg_d.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/home_btn_bg_d.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/home_btn_bg_n.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/home_btn_bg_n.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/home_btn_bg_s.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/home_btn_bg_s.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ico_dp01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/ico_dp01.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ico_gd01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/ico_gd01.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ico_tt01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/ico_tt01.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ico_zh01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/ico_zh01.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/ico_zy01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/ico_zy01.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/radio_bg.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/shelf_bkg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/shelf_bkg.png
--------------------------------------------------------------------------------
/res/drawable-hdpi/storm.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/storm.jpg
--------------------------------------------------------------------------------
/res/drawable-hdpi/top.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-hdpi/top.gif
--------------------------------------------------------------------------------
/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-ldpi/text.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/focused_application_background.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-mdpi/focused_application_background.9.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/mainbg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-mdpi/mainbg.jpg
--------------------------------------------------------------------------------
/res/drawable-mdpi/pressed_application_background.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/watermelon/ebook/ae22b34035bd8e8e2e9c2bb36ab2353f8d62dbc5/res/drawable-mdpi/pressed_application_background.9.png
--------------------------------------------------------------------------------
/res/drawable/item_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
7 |
9 |
10 |
--------------------------------------------------------------------------------
/res/drawable/itemcolor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/res/drawable/itemsize.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
23 |
24 |
31 |
32 |
39 |
40 |
41 |
49 |
50 |
55 |
56 |
60 |
61 |
66 |
67 |
73 |
74 |
81 |
82 |
88 |
89 |
95 |
96 |
102 |
103 |
109 |
110 |
111 |
112 |
113 |
114 |
121 |
122 |
126 |
127 |
133 |
134 |
139 |
140 |
146 |
147 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/res/layout/mainmenu.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
23 |
24 |
31 |
32 |
39 |
40 |
41 |
49 |
50 |
55 |
56 |
60 |
61 |
66 |
67 |
73 |
74 |
81 |
82 |
88 |
89 |
95 |
96 |
102 |
103 |
109 |
110 |
111 |
112 |
113 |
114 |
121 |
122 |
126 |
127 |
133 |
134 |
139 |
140 |
146 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/res/layout/relative.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
19 |
--------------------------------------------------------------------------------
/res/menu/game_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - 书签1
5 | - 书签2
6 | - 书签3
7 | - 书签4
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Hello World, EbookActivity!
5 | Ebook
6 | 书签
7 | 保存
8 | 打开
9 |
10 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
16 |
17 |
--------------------------------------------------------------------------------
/src/com/ebook/EbookActivity.java:
--------------------------------------------------------------------------------
1 | package com.ebook;
2 |
3 | import java.io.IOException;
4 |
5 | import android.app.Activity;
6 | import android.app.AlertDialog;
7 | import android.app.Dialog;
8 | import android.content.Context;
9 | import android.content.DialogInterface;
10 | import android.content.Intent;
11 | import android.database.Cursor;
12 | import android.graphics.Bitmap;
13 | import android.graphics.BitmapFactory;
14 | import android.graphics.Canvas;
15 | import android.graphics.Color;
16 | import android.os.Bundle;
17 | import android.os.Handler;
18 | import android.os.Message;
19 | import android.util.DisplayMetrics;
20 | import android.util.Log;
21 | import android.view.Menu;
22 | import android.view.MenuItem;
23 | import android.view.MotionEvent;
24 | import android.view.View;
25 | import android.view.View.OnTouchListener;
26 | import android.view.Window;
27 | import android.view.WindowManager;
28 | import android.widget.Toast;
29 |
30 | import com.ebook.bookpage.BookPageFactory;
31 | import com.ebook.bookpage.PageWidget;
32 | import com.sqlite.DbHelper;
33 |
34 | public class EbookActivity extends Activity {
35 |
36 | public final static int OPENMARK = 0;
37 | public final static int SAVEMARK = 1;
38 | public final static int TEXTSET = 2;
39 |
40 | private PageWidget mPageWidget;
41 | private BookPageFactory pagefactory;
42 | DbHelper db;
43 | Bitmap mCurPageBitmap, mNextPageBitmap;
44 | Canvas mCurPageCanvas, mNextPageCanvas;
45 | Context mContext;
46 | Cursor mCursor;
47 | final String[] items = { "书签1 未使用", "书签2 未使用", "书签3 未使用", "书签4 未使用", "自动书签 未使用" };
48 | String fileName;
49 | String path;
50 | int curPostion;
51 | int screenWidth;
52 | int screenHeight;
53 | int bookMarkPos;
54 |
55 | /** Called when the activity is first created. */
56 | @Override
57 | public void onCreate(Bundle savedInstanceState) {
58 | super.onCreate(savedInstanceState);
59 | requestWindowFeature(Window.FEATURE_NO_TITLE);
60 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
61 | WindowManager.LayoutParams.FLAG_FULLSCREEN);
62 |
63 | initScreedWH();
64 | mPageWidget = new PageWidget(this);
65 | mPageWidget.setWidth(screenWidth);
66 | mPageWidget.setHeight(screenHeight);
67 | mContext = this;
68 |
69 | initBookMark();
70 |
71 | setContentView(mPageWidget);
72 |
73 | initBookPage();
74 |
75 | String pos = this.getIntent().getStringExtra("pos");
76 |
77 | if (!isViewIntent()) {
78 | path = this.getIntent().getStringExtra("pathes");
79 |
80 | } else {
81 | path = this.getIntent().getData().getPath();
82 | }
83 |
84 | try {
85 | Log.i("path", path);
86 | pagefactory.openBook(path);
87 | fileName = pagefactory.getFileName();
88 | if (pos != null) {
89 | pagefactory.setBeginPos(Integer.valueOf(pos));
90 | pagefactory.pageUp();
91 | }
92 | pagefactory.onDraw(mCurPageCanvas);
93 | } catch (IOException e1) {
94 | Toast.makeText(this, fileName + "不存在,请将文件放在SD卡根目录下,可以超过100M容量",
95 | Toast.LENGTH_LONG).show();
96 | }
97 |
98 | mPageWidget.setBitmaps(mCurPageBitmap, mCurPageBitmap);
99 |
100 | mPageWidget.setOnTouchListener(new OnTouchListener() {
101 | public boolean onTouch(View v, MotionEvent e) {
102 | // TODO Auto-generated method stub
103 | boolean ret = false;
104 | if (v == mPageWidget) {
105 | if (e.getAction() == MotionEvent.ACTION_DOWN) {
106 | mPageWidget.abortAnimation();
107 | mPageWidget.calcCornerXY(e.getX(), e.getY());
108 | pagefactory.onDraw(mCurPageCanvas);
109 | if (mPageWidget.DragToRight()) {
110 | try {
111 | pagefactory.prePage();
112 | } catch (IOException e1) {
113 | e1.printStackTrace();
114 | }
115 | if (pagefactory.isFirstPage())
116 | return false;
117 | pagefactory.onDraw(mNextPageCanvas);
118 | } else {
119 | try {
120 | pagefactory.nextPage();
121 | } catch (IOException e1) {
122 | e1.printStackTrace();
123 | }
124 | if (pagefactory.isLastPage()) {
125 | return false;
126 | }
127 | pagefactory.onDraw(mNextPageCanvas);
128 | }
129 | mPageWidget.setBitmaps(mCurPageBitmap, mNextPageBitmap);
130 | }
131 | ret = mPageWidget.doTouchEvent(e);
132 |
133 | return ret;
134 | }
135 | return false;
136 | }
137 | });
138 | }
139 |
140 | private void initScreedWH() {
141 | DisplayMetrics dm = new DisplayMetrics();
142 | getWindowManager().getDefaultDisplay().getMetrics(dm);
143 | screenHeight = dm.heightPixels;
144 | screenWidth = dm.widthPixels;
145 | }
146 |
147 | private boolean isViewIntent() {
148 | String action = getIntent().getAction();
149 | return Intent.ACTION_VIEW.equals(action);
150 | }
151 |
152 | private void initBookPage() {
153 | mCurPageBitmap = Bitmap.createBitmap(screenWidth, screenHeight,
154 | Bitmap.Config.ARGB_8888);
155 | mNextPageBitmap = Bitmap.createBitmap(screenWidth, screenHeight,
156 | Bitmap.Config.ARGB_8888);
157 |
158 | mCurPageCanvas = new Canvas(mCurPageBitmap);
159 | mNextPageCanvas = new Canvas(mNextPageBitmap);
160 | pagefactory = new BookPageFactory(screenWidth, screenHeight);
161 |
162 | pagefactory.setBgBitmap(BitmapFactory.decodeResource(
163 | mContext.getResources(), R.drawable.shelf_bkg));
164 | }
165 |
166 | private void initBookMark() {
167 | db = new DbHelper(mContext);
168 | try {
169 | mCursor = db.select();
170 |
171 | } catch (Exception e) {
172 | e.printStackTrace();
173 | }
174 | if (mCursor.getCount() > 0) {
175 | for (int i = 0; i < mCursor.getCount(); i++) {
176 | mCursor.moveToPosition(mCursor.getCount() - (i + 1));
177 | String str = mCursor.getString(1);
178 | str = str.substring(str.lastIndexOf('/') + 1, str.length());
179 | items[i] = str + ": " + mCursor.getString(2);
180 | }
181 | }
182 | db.close();
183 | }
184 |
185 | public boolean onCreateOptionsMenu(Menu menu) {
186 | menu.add(0, 1, 1, fileName);
187 | menu.add(0, 2, 2, "书签");
188 | menu.add(0, 3, 3, "设置");
189 | menu.add(0, 4, 4, "退出");
190 | return super.onCreateOptionsMenu(menu);
191 | }
192 |
193 | public boolean onOptionsItemSelected(MenuItem item) {
194 | switch (item.getItemId()) {
195 | case 1:
196 | Toast.makeText(this, "您正在观看: " + fileName, Toast.LENGTH_SHORT)
197 | .show();
198 | return true;
199 | case 2:
200 | showDialog(OPENMARK);
201 | return true;
202 |
203 | case 3:
204 | showDialog(TEXTSET);
205 | break;
206 |
207 | case 4:
208 | finish();
209 | default:
210 | break;
211 | }
212 | return super.onOptionsItemSelected(item);
213 | }
214 |
215 | protected Dialog onCreateDialog(int id) {
216 | switch (id) {
217 | case OPENMARK:
218 | return new AlertDialog.Builder(mContext)
219 | .setTitle(R.string.bookmark)
220 |
221 | .setSingleChoiceItems(items, 0,
222 | new DialogInterface.OnClickListener() {
223 | public void onClick(DialogInterface dialog,
224 | int which) {
225 | bookMarkPos = which;
226 | }
227 | })
228 | .setPositiveButton(R.string.load_bookmark,
229 | new DialogInterface.OnClickListener() {
230 | public void onClick(DialogInterface dialog,
231 | int which) {
232 | Message msg = new Message();
233 | msg.what = OPENMARK;
234 | msg.arg1 = bookMarkPos;
235 | mhHandler.sendMessage(msg);
236 | }
237 | })
238 | .setNegativeButton(R.string.save_bookmark,
239 | new DialogInterface.OnClickListener() {
240 | public void onClick(DialogInterface dialog,
241 | int which) {
242 | Message msg = new Message();
243 | msg.what = SAVEMARK;
244 | msg.arg1 = bookMarkPos;
245 | curPostion = pagefactory.getCurPostion();
246 | msg.arg2 = curPostion;
247 | mhHandler.sendMessage(msg);
248 | }
249 | }).create();
250 | case TEXTSET:
251 | String color[] = new String[] { "红色", "深灰色", "黄色", "蓝色", "黑色" };
252 | return new AlertDialog.Builder(mContext)
253 | .setTitle("字体颜色设置")
254 | .setSingleChoiceItems(color, 0,
255 | new DialogInterface.OnClickListener() {
256 | public void onClick(DialogInterface dialog,
257 | int which) {
258 | bookMarkPos = which;
259 | }
260 | })
261 | .setPositiveButton("ok",
262 | new DialogInterface.OnClickListener() {
263 | public void onClick(DialogInterface dialog,
264 | int which) {
265 | Message msg = new Message();
266 | msg.what = TEXTSET;
267 | switch (bookMarkPos) {
268 | case 0:
269 | msg.arg1 = Color.RED;
270 | break;
271 | case 1:
272 | msg.arg1 = Color.DKGRAY;
273 | break;
274 | case 2:
275 | msg.arg1 = Color.YELLOW;
276 | break;
277 | case 3:
278 | msg.arg1 = Color.BLUE;
279 | break;
280 | case 4:
281 | msg.arg1 = Color.BLACK;
282 | break;
283 |
284 | default:
285 | break;
286 | }
287 | mhHandler.sendMessage(msg);
288 | }
289 | })
290 | .setNegativeButton("cancle",
291 | new DialogInterface.OnClickListener() {
292 | public void onClick(DialogInterface dialog,
293 | int which) {
294 | }
295 | }).create();
296 | default:
297 | break;
298 | }
299 | return null;
300 |
301 | }
302 |
303 | Handler mhHandler = new Handler() {
304 | public void handleMessage(Message msg) {
305 | switch (msg.what) {
306 |
307 | case TEXTSET:
308 | pagefactory.changBackGround(msg.arg1);
309 | pagefactory.onDraw(mCurPageCanvas);
310 | mPageWidget.postInvalidate();
311 | break;
312 |
313 | case OPENMARK:
314 | try {
315 | mCursor = db.select();
316 |
317 | } catch (Exception e) {
318 | e.printStackTrace();
319 | }
320 | if (mCursor.getCount() > 0) {
321 | mCursor.moveToPosition(mCursor.getCount() - (msg.arg1 + 1));
322 | String pos = mCursor.getString(2);
323 | String tmp = mCursor.getString(1);
324 |
325 | if (fileName.equals(tmp.substring(tmp.lastIndexOf('/') + 1,
326 | tmp.length()))) {
327 |
328 | pagefactory.setBeginPos(Integer.valueOf(pos));
329 | try {
330 | pagefactory.prePage();
331 | } catch (IOException e) {
332 | // TODO Auto-generated catch block
333 | e.printStackTrace();
334 | }
335 | pagefactory.onDraw(mNextPageCanvas);
336 | mPageWidget.setBitmaps(mCurPageBitmap, mNextPageBitmap);
337 | mPageWidget.invalidate();
338 | db.close();
339 | } else {
340 | Intent intent = new Intent(EbookActivity.this,
341 | EbookActivity.class);
342 | intent.putExtra("pathes", mCursor.getString(1));
343 | intent.putExtra("pos", mCursor.getString(2));
344 | db.close();
345 | startActivity(intent);
346 | finish();
347 | }
348 | }
349 | break;
350 |
351 | case SAVEMARK:
352 | try {
353 | mCursor = db.select();
354 | } catch (Exception e) {
355 | e.printStackTrace();
356 | }
357 | if (mCursor.getCount() > 0 && mCursor.getCount() > msg.arg1) {
358 | mCursor.moveToPosition(mCursor.getCount() - (msg.arg1 + 1));
359 | db.update(mCursor.getInt(0), path, String.valueOf(msg.arg2));
360 | } else {
361 | db.insert(path, String.valueOf(msg.arg2));
362 | }
363 | db.close();
364 | items[msg.arg1] = path.substring(path.lastIndexOf('/') + 1,
365 | path.length()) + ": " + String.valueOf(msg.arg2);
366 | break;
367 |
368 | default:
369 | break;
370 | }
371 | super.handleMessage(msg);
372 | }
373 | };
374 | }
--------------------------------------------------------------------------------
/src/com/ebook/MainMenu.java:
--------------------------------------------------------------------------------
1 | package com.ebook;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 | import java.util.HashMap;
6 |
7 | import android.app.Activity;
8 | import android.app.AlertDialog;
9 | import android.app.Dialog;
10 | import android.content.Context;
11 | import android.content.DialogInterface;
12 | import android.content.Intent;
13 | import android.database.Cursor;
14 | import android.os.Bundle;
15 | import android.os.Handler;
16 | import android.os.Message;
17 | import android.util.Log;
18 | import android.view.View;
19 | import android.view.View.OnClickListener;
20 | import android.view.Window;
21 | import android.view.WindowManager;
22 | import android.widget.AdapterView;
23 | import android.widget.AdapterView.OnItemClickListener;
24 | import android.widget.ImageView;
25 | import android.widget.ListView;
26 | import android.widget.RadioButton;
27 | import android.widget.SimpleAdapter;
28 | import android.widget.TextView;
29 | import android.widget.Toast;
30 |
31 | import com.ebook.scansd.ScanSD;
32 | import com.sqlite.DbHelper;
33 |
34 | public class MainMenu extends Activity {
35 |
36 | public final static int OPENMARK = 0;
37 | ScanSD scanSD;
38 | Intent intent;
39 | Context mContext;
40 | RadioButton nextPage;
41 | RadioButton bmRadioButton;
42 | ListView ListView;
43 | TextView textView;
44 | ImageView storm;
45 | private DbHelper db;
46 | private int pos;
47 | final String[] items = { "书签1 未使用", "书签2 未使用", "书签3 未使用", "书签4 未使用", "自动书签 未使用" };
48 | Cursor mCursor;
49 |
50 | /** Called when the activity is first created. */
51 | public void onCreate(Bundle savedInstanceState) {
52 | super.onCreate(savedInstanceState);
53 | requestWindowFeature(Window.FEATURE_NO_TITLE);
54 | getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
55 | WindowManager.LayoutParams.FLAG_FULLSCREEN);
56 | setContentView(R.layout.mainmenu);
57 | intent = new Intent();
58 | mContext = this;
59 |
60 | scanSD = new ScanSD();
61 |
62 | findView();
63 | initBookMark();
64 | initListView();
65 | textView.setOnClickListener(radButtonClicked);
66 | nextPage.setOnClickListener(radButtonClicked);
67 | bmRadioButton.setOnClickListener(radButtonClicked);
68 | }
69 |
70 | private void findView() {
71 | textView = (TextView) findViewById(R.id.textView1);
72 | bmRadioButton = (RadioButton) findViewById(R.id.bookmark);
73 | storm = (ImageView) findViewById(R.id.storm);
74 | nextPage = (RadioButton) findViewById(R.id.radio_next);
75 | ListView = (ListView) findViewById(R.id.listfile);
76 | }
77 |
78 | private OnClickListener radButtonClicked = new OnClickListener() {
79 |
80 | @Override
81 | public void onClick(View view) {
82 | // TODO Auto-generated method stub
83 | switch (view.getId()) {
84 | case R.id.bookmark:
85 | showDialog(0);
86 | break;
87 |
88 | case R.id.radio_next:
89 | if (nextPage.getText().equals("下一页")) {
90 | nextPage.setText("上一页");
91 | } else {
92 | nextPage.setText("下一页");
93 | }
94 | break;
95 | case R.id.textView1:
96 | Toast.makeText(MainMenu.this, "thanks", 500).show();
97 | finish();
98 | break;
99 | }
100 | }
101 | };
102 |
103 | private void initBookMark() {
104 | db = new DbHelper(mContext);
105 | try {
106 | mCursor = db.select();
107 | } catch (Exception e) {
108 | e.printStackTrace();
109 | }
110 | if (mCursor.getCount() > 0) {
111 | for (int i = 0; i < mCursor.getCount(); i++) {
112 | mCursor.moveToPosition(mCursor.getCount() - (i + 1));
113 | String str = mCursor.getString(1);
114 | str = str.substring(str.lastIndexOf('/') + 1, str.length());
115 | items[i] = str + ": " + mCursor.getString(2);
116 | }
117 | }
118 | db.close();
119 | }
120 |
121 | private void initListView() {
122 | ArrayList list = new ArrayList();
123 | list = scanSD.getFileList();
124 |
125 | final SimpleAdapter adapter = new SimpleAdapter(this,
126 | scanSD.getMapData(list), R.layout.relative,
127 | new String[] { "ItemName" }, new int[] { R.id.ItemText });
128 |
129 | ListView.setAdapter(adapter);
130 | ListView.setSelector(R.drawable.item_selector);
131 | ListView.setOnItemClickListener(new OnItemClickListener() {
132 | public void onItemClick(AdapterView> arg0, View view, int pos,
133 | long id) {
134 | String path;
135 | @SuppressWarnings("unchecked")
136 | HashMap map = (HashMap) ListView
137 | .getItemAtPosition(pos);
138 | // String name = map.get("ItemText");
139 | path = map.get("ItemPath");
140 |
141 | intent.setClass(mContext, EbookActivity.class);
142 | intent.putExtra("pathes", path);
143 | startActivity(intent);
144 | adapter.notifyDataSetChanged(); // 通知adapter刷新数据
145 | }
146 | });
147 | }
148 |
149 | protected Dialog onCreateDialog(int id) {
150 | return new AlertDialog.Builder(mContext)
151 | .setTitle(R.string.bookmark)
152 |
153 | .setSingleChoiceItems(items, 0,
154 | new DialogInterface.OnClickListener() {
155 | public void onClick(DialogInterface dialog,
156 | int which) {
157 | pos = which;
158 | }
159 | })
160 | .setPositiveButton("取消", new DialogInterface.OnClickListener() {
161 | public void onClick(DialogInterface dialog, int which) {
162 | }
163 | })
164 | .setNegativeButton(R.string.load_bookmark,
165 | new DialogInterface.OnClickListener() {
166 | public void onClick(DialogInterface dialog,
167 | int which) {
168 | Message msg = new Message();
169 | msg.what = 0;
170 | msg.arg1 = pos;
171 | mhHandler.sendMessage(msg);
172 | }
173 | }).create();
174 | }
175 |
176 | Handler mhHandler = new Handler() {
177 | public void handleMessage(Message msg) {
178 | switch (msg.what) {
179 | case OPENMARK:
180 | try {
181 | mCursor = db.select();
182 | } catch (Exception e) {
183 | e.printStackTrace();
184 | }
185 | if (mCursor.getCount() > 0) {
186 | mCursor.moveToPosition(mCursor.getCount() - (msg.arg1 + 1));
187 | Log.i("string", items[mCursor.getCount() - (msg.arg1 + 1)]);
188 | intent.setClass(mContext, EbookActivity.class);
189 | intent.putExtra("pathes", mCursor.getString(1));
190 | intent.putExtra("pos", mCursor.getString(2));
191 | startActivity(intent);
192 | }
193 | db.close();// 打开之后记得关闭数据库
194 | break;
195 |
196 | default:
197 | break;
198 | }
199 | super.handleMessage(msg);
200 | }
201 | };
202 | }
--------------------------------------------------------------------------------
/src/com/ebook/bookpage/BookPageFactory.java:
--------------------------------------------------------------------------------
1 | package com.ebook.bookpage;
2 |
3 | import java.io.File;
4 | import java.io.IOException;
5 | import java.io.RandomAccessFile;
6 | import java.io.UnsupportedEncodingException;
7 | import java.nio.MappedByteBuffer;
8 | import java.nio.channels.FileChannel;
9 | import java.text.DecimalFormat;
10 | import java.util.Vector;
11 |
12 | import android.graphics.Bitmap;
13 | import android.graphics.Canvas;
14 | import android.graphics.Color;
15 | import android.graphics.Paint;
16 | import android.graphics.Paint.Align;
17 |
18 | public class BookPageFactory {
19 |
20 | private File book_file = null;
21 | private MappedByteBuffer m_mbBuf = null;
22 | private int m_mbBufLen = 0;// 总长度
23 | private int m_mbBufBegin = 0;// 当前长度
24 | private int m_mbBufEnd = 0;
25 | private String m_strCharsetName = "GBK";
26 | private Bitmap m_book_bg = null;
27 | private int mWidth;
28 | private int mHeight;
29 |
30 | private String fileName;
31 |
32 | private Vector m_lines = new Vector();
33 |
34 | private int m_fontSize = 24;
35 | private int m_textColor = Color.BLACK;
36 | private int m_backColor = 0xffff9e85; // 背景颜色
37 | private int marginWidth = 15; // 左右与边缘的距离
38 | private int marginHeight = 20; // 上下与边缘的距离
39 |
40 | private int mLineCount; // 每页可以显示的行数
41 | private float mVisibleHeight; // 绘制内容的宽
42 | private float mVisibleWidth; // 绘制内容的
43 | private boolean m_isfirstPage, m_islastPage;
44 |
45 | private Paint mPaint;
46 |
47 | // 进度格式
48 | DecimalFormat df = new DecimalFormat("##.##");
49 |
50 | public BookPageFactory(int w, int h) {
51 | mWidth = w;
52 | mHeight = h;
53 | mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
54 | mPaint.setTextAlign(Align.LEFT);
55 | mPaint.setTextSize(m_fontSize);
56 | mPaint.setColor(m_textColor);
57 | mVisibleWidth = mWidth - marginWidth * 2;
58 | mVisibleHeight = mHeight - marginHeight * 2;
59 | mLineCount = (int) (mVisibleHeight / m_fontSize); // 可显示的行数
60 | }
61 |
62 | public void openBook(String strFilePath) throws IOException {
63 | book_file = new File(strFilePath);
64 | long lLen = book_file.length();
65 | m_mbBufLen = (int) lLen;
66 | fileName = book_file.getName();
67 | m_mbBuf = new RandomAccessFile(book_file, "r").getChannel().map(
68 | FileChannel.MapMode.READ_ONLY, 0, lLen);
69 | }
70 |
71 | // 读取上一段落
72 | protected byte[] readParagraphBack(int nFromPos) {
73 | int nEnd = nFromPos;
74 | int i;
75 | byte b0, b1;
76 | if (m_strCharsetName.equals("UTF-16LE")) {
77 | i = nEnd - 2;
78 | while (i > 0) {
79 | b0 = m_mbBuf.get(i);
80 | b1 = m_mbBuf.get(i + 1);
81 | if (b0 == 0x0a && b1 == 0x00 && i != nEnd - 2) {
82 | i += 2;
83 | break;
84 | }
85 | i--;
86 | }
87 |
88 | } else if (m_strCharsetName.equals("UTF-16BE")) {
89 | i = nEnd - 2;
90 | while (i > 0) {
91 | b0 = m_mbBuf.get(i);
92 | b1 = m_mbBuf.get(i + 1);
93 | if (b0 == 0x00 && b1 == 0x0a && i != nEnd - 2) {
94 | i += 2;
95 | break;
96 | }
97 | i--;
98 | }
99 | } else {
100 | i = nEnd - 1;
101 | while (i > 0) {
102 | b0 = m_mbBuf.get(i);
103 | if (b0 == 0x0a && i != nEnd - 1) {
104 | i++;
105 | break;
106 | }
107 | i--;
108 | }
109 | }
110 | if (i < 0)
111 | i = 0;
112 | int nParaSize = nEnd - i;
113 | int j;
114 | byte[] buf = new byte[nParaSize];
115 | for (j = 0; j < nParaSize; j++) {
116 | buf[j] = m_mbBuf.get(i + j);
117 | }
118 | return buf;
119 | }
120 |
121 | // 读取下一段落
122 | protected byte[] readParagraphForward(int nFromPos) {
123 | int nStart = nFromPos;
124 | int i = nStart;
125 | byte b0, b1;
126 | // 根据编码格式判断换行
127 | if (m_strCharsetName.equals("UTF-16LE")) {
128 | while (i < m_mbBufLen - 1) {
129 | b0 = m_mbBuf.get(i++);
130 | b1 = m_mbBuf.get(i++);
131 | if (b0 == 0x0a && b1 == 0x00) {
132 | break;
133 | }
134 | }
135 | } else if (m_strCharsetName.equals("UTF-16BE")) {
136 | while (i < m_mbBufLen - 1) {
137 | b0 = m_mbBuf.get(i++);
138 | b1 = m_mbBuf.get(i++);
139 | if (b0 == 0x00 && b1 == 0x0a) {
140 | break;
141 | }
142 | }
143 | } else {
144 | while (i < m_mbBufLen) {
145 | b0 = m_mbBuf.get(i++);
146 | if (b0 == 0x0a) {
147 | break;
148 | }
149 | }
150 | }
151 | int nParaSize = i - nStart;
152 | byte[] buf = new byte[nParaSize];
153 | for (i = 0; i < nParaSize; i++) {
154 | buf[i] = m_mbBuf.get(nFromPos + i);
155 | }
156 | return buf;
157 | }
158 |
159 | protected Vector pageDown() {
160 | String strParagraph = "";
161 | Vector lines = new Vector();
162 | while (lines.size() < mLineCount && m_mbBufEnd < m_mbBufLen) {
163 | byte[] paraBuf = readParagraphForward(m_mbBufEnd); // 读取一个段落
164 | m_mbBufEnd += paraBuf.length;
165 | try {
166 | strParagraph = new String(paraBuf, m_strCharsetName);
167 | } catch (UnsupportedEncodingException e) {
168 | // TODO Auto-generated catch block
169 | e.printStackTrace();
170 | }
171 | String strReturn = "";
172 | if (strParagraph.indexOf("\r\n") != -1) {
173 | strReturn = "\r\n";
174 | strParagraph = strParagraph.replaceAll("\r\n", "");
175 | } else if (strParagraph.indexOf("\n") != -1) {
176 | strReturn = "\n";
177 | strParagraph = strParagraph.replaceAll("\n", "");
178 | }
179 |
180 | if (strParagraph.length() == 0) {
181 | lines.add(strParagraph);
182 | }
183 | while (strParagraph.length() > 0) {
184 | int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth,
185 | null);
186 | lines.add(strParagraph.substring(0, nSize));
187 | strParagraph = strParagraph.substring(nSize);
188 | if (lines.size() >= mLineCount) {
189 | break;
190 | }
191 | }
192 | if (strParagraph.length() != 0) {
193 | try {
194 | m_mbBufEnd -= (strParagraph + strReturn)
195 | .getBytes(m_strCharsetName).length;
196 | } catch (UnsupportedEncodingException e) {
197 | // TODO Auto-generated catch block
198 | e.printStackTrace();
199 | }
200 | }
201 | }
202 | return lines;
203 | }
204 |
205 | public Vector pageUp() {
206 | if (m_mbBufBegin < 0) {
207 | m_mbBufBegin = 0;
208 | }
209 | Vector lines = new Vector();
210 | String strParagraph = "";
211 | while (lines.size() < mLineCount && m_mbBufBegin > 0) {
212 | Vector paraLines = new Vector();
213 | byte[] paraBuf = readParagraphBack(m_mbBufBegin);
214 | m_mbBufBegin -= paraBuf.length;
215 | try {
216 | strParagraph = new String(paraBuf, m_strCharsetName);
217 | } catch (UnsupportedEncodingException e) {
218 | // TODO Auto-generated catch block
219 | e.printStackTrace();
220 | }
221 | strParagraph = strParagraph.replaceAll("\r\n", "");
222 | strParagraph = strParagraph.replaceAll("\n", "");
223 |
224 | if (strParagraph.length() == 0) {
225 | paraLines.add(strParagraph);
226 | }
227 | while (strParagraph.length() > 0) {
228 | int nSize = mPaint.breakText(strParagraph, true, mVisibleWidth,
229 | null);
230 | paraLines.add(strParagraph.substring(0, nSize));
231 | strParagraph = strParagraph.substring(nSize);
232 | }
233 | lines.addAll(0, paraLines);
234 | }
235 | while (lines.size() > mLineCount) {
236 | try {
237 | m_mbBufBegin += lines.get(0).getBytes(m_strCharsetName).length;
238 | lines.remove(0);
239 | } catch (UnsupportedEncodingException e) {
240 | // TODO Auto-generated catch block
241 | e.printStackTrace();
242 | }
243 | }
244 | m_mbBufEnd = m_mbBufBegin;
245 |
246 | return lines;
247 | }
248 |
249 | public void prePage() throws IOException {
250 | if (m_mbBufBegin <= 0) {
251 | m_mbBufBegin = 0;
252 | m_isfirstPage = true;
253 | return;
254 | } else {
255 | m_isfirstPage = false;
256 | }
257 | m_lines.clear();
258 | pageUp();
259 | m_lines = pageDown();
260 | }
261 |
262 | public void nextPage() throws IOException {
263 | if (m_mbBufEnd >= m_mbBufLen) {
264 | m_islastPage = true;
265 | return;
266 | } else {
267 | m_islastPage = false;
268 | }
269 | m_lines.clear();
270 | m_mbBufBegin = m_mbBufEnd;
271 | m_lines = pageDown();
272 | }
273 |
274 | public void onDraw(Canvas c) {
275 | if (m_lines.size() == 0) {
276 | m_lines = pageDown();
277 | }
278 | if (m_lines.size() > 0) {
279 | if (m_book_bg == null)
280 | c.drawColor(m_backColor);
281 | else
282 | c.drawBitmap(m_book_bg, 0, 0, null);
283 | int y = marginHeight;
284 | for (String strLine : m_lines) {
285 | y += m_fontSize;
286 | c.drawText(strLine, marginWidth, y, mPaint);
287 | }
288 | }
289 | float fPercent = (float) (m_mbBufBegin * 1.0 / m_mbBufLen);
290 | String strPercent = df.format(fPercent * 100) + "%";
291 | int nPercentWidth = (int) mPaint.measureText("999.9%") + 1;
292 | c.drawText(strPercent, mWidth - nPercentWidth, mHeight - 5, mPaint);
293 | }
294 |
295 | public void setBgBitmap(Bitmap BG) {
296 | m_book_bg = BG;
297 | }
298 |
299 | public boolean isFirstPage() {
300 | return m_isfirstPage;
301 | }
302 |
303 | public boolean isLastPage() {
304 | return m_islastPage;
305 | }
306 |
307 | public String getFileName() {
308 | return fileName;
309 | }
310 |
311 | public int getCurPostion() {
312 | return m_mbBufEnd;
313 | }
314 |
315 | public void setBeginPos(int pos) {
316 | m_mbBufEnd = pos;
317 | m_mbBufBegin = pos;
318 | }
319 |
320 | public int getBufLen() {
321 | return m_mbBufLen;
322 | }
323 |
324 | public String getOneLine() {
325 | return m_lines.toString().substring(0, 10);
326 | }
327 |
328 | public void changBackGround(int color) {
329 | mPaint.setColor(color);
330 | }
331 |
332 | public void setFontSize(int size) {
333 | m_fontSize = size;
334 | mPaint.setTextSize(size);
335 | }
336 |
337 |
338 | }
339 |
--------------------------------------------------------------------------------
/src/com/ebook/bookpage/PageWidget.java:
--------------------------------------------------------------------------------
1 | package com.ebook.bookpage;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Canvas;
6 | import android.graphics.ColorMatrix;
7 | import android.graphics.ColorMatrixColorFilter;
8 | import android.graphics.Matrix;
9 | import android.graphics.Paint;
10 | import android.graphics.Path;
11 | import android.graphics.PointF;
12 | import android.graphics.Region;
13 | import android.graphics.drawable.GradientDrawable;
14 | import android.view.MotionEvent;
15 | import android.view.View;
16 | import android.widget.Scroller;
17 |
18 | public class PageWidget extends View {
19 |
20 | private int mWidth = 480;
21 | private int mHeight = 800;
22 | private int mCornerX = 0; // 拖拽点对应的页脚
23 | private int mCornerY = 0;
24 | private Path mPath0;
25 | private Path mPath1;
26 | Bitmap mCurPageBitmap = null; // 当前页
27 | Bitmap mNextPageBitmap = null;
28 |
29 | PointF mTouch = new PointF(); // 拖拽点
30 | PointF mBezierStart1 = new PointF(); // 贝塞尔曲线起始点
31 | PointF mBezierControl1 = new PointF(); // 贝塞尔曲线控制点
32 | PointF mBeziervertex1 = new PointF(); // 贝塞尔曲线顶点
33 | PointF mBezierEnd1 = new PointF(); // 贝塞尔曲线结束点
34 |
35 | PointF mBezierStart2 = new PointF(); // 另一条贝塞尔曲线
36 | PointF mBezierControl2 = new PointF();
37 | PointF mBeziervertex2 = new PointF();
38 | PointF mBezierEnd2 = new PointF();
39 |
40 | float mMiddleX;
41 | float mMiddleY;
42 | float mDegrees;
43 | float mTouchToCornerDis;
44 | ColorMatrixColorFilter mColorMatrixFilter;
45 | Matrix mMatrix;
46 | float[] mMatrixArray = { 0, 0, 0, 0, 0, 0, 0, 0, 1.0f };
47 |
48 | boolean mIsRTandLB; // 是否属于右上左下
49 | float mMaxLength = (float) Math.hypot(mWidth, mHeight);
50 | int[] mBackShadowColors;
51 | int[] mFrontShadowColors;
52 | GradientDrawable mBackShadowDrawableLR;
53 | GradientDrawable mBackShadowDrawableRL;
54 | GradientDrawable mFolderShadowDrawableLR;
55 | GradientDrawable mFolderShadowDrawableRL;
56 |
57 | GradientDrawable mFrontShadowDrawableHBT;
58 | GradientDrawable mFrontShadowDrawableHTB;
59 | GradientDrawable mFrontShadowDrawableVLR;
60 | GradientDrawable mFrontShadowDrawableVRL;
61 |
62 | Paint mPaint;
63 |
64 | Scroller mScroller;
65 |
66 | public PageWidget(Context context) {
67 | super(context);
68 | // TODO Auto-generated constructor stub
69 | mPath0 = new Path();
70 | mPath1 = new Path();
71 | createDrawable();
72 |
73 | mPaint = new Paint();
74 | mPaint.setStyle(Paint.Style.FILL);
75 |
76 | ColorMatrix cm = new ColorMatrix();
77 | float array[] = { 0.55f, 0, 0, 0, 80.0f, 0, 0.55f, 0, 0, 80.0f, 0, 0,
78 | 0.55f, 0, 80.0f, 0, 0, 0, 0.2f, 0 };
79 | cm.set(array);
80 | mColorMatrixFilter = new ColorMatrixColorFilter(cm);
81 | mMatrix = new Matrix();
82 | mScroller = new Scroller(getContext());
83 |
84 | mTouch.x = 0.01f; // 不让x,y为0,否则在点计算时会有问题
85 | mTouch.y = 0.01f;
86 |
87 | }
88 |
89 | public void setWidth(int width) {
90 | mWidth = width;
91 | }
92 |
93 | public void setHeight(int height) {
94 | mHeight = height;
95 | }
96 |
97 | /**
98 | * Author : hmg25 Version: 1.0 Description : 计算拖拽点对应的拖拽脚
99 | */
100 | public void calcCornerXY(float x, float y) {
101 | if (x <= mWidth / 2)
102 | mCornerX = 0;
103 | else
104 | mCornerX = mWidth;
105 | if (y <= mHeight / 2)
106 | mCornerY = 0;
107 | else
108 | mCornerY = mHeight;
109 | if ((mCornerX == 0 && mCornerY == mHeight)
110 | || (mCornerX == mWidth && mCornerY == 0))
111 | mIsRTandLB = true;
112 | else
113 | mIsRTandLB = false;
114 | }
115 |
116 | public boolean doTouchEvent(MotionEvent event) {
117 | // TODO Auto-generated method stub
118 | if (event.getAction() == MotionEvent.ACTION_MOVE) {
119 | mTouch.x = event.getX();
120 | mTouch.y = event.getY();
121 | this.postInvalidate();
122 | }
123 | if (event.getAction() == MotionEvent.ACTION_DOWN) {
124 | mTouch.x = event.getX();
125 | mTouch.y = event.getY();
126 | // calcCornerXY(mTouch.x, mTouch.y);
127 | // this.postInvalidate();
128 | }
129 | if (event.getAction() == MotionEvent.ACTION_UP) {
130 | if (canDragOver()) {
131 | startAnimation(1200);
132 | } else {
133 | mTouch.x = mCornerX - 0.09f;
134 | mTouch.y = mCornerY - 0.09f;
135 | }
136 |
137 | this.postInvalidate();
138 | }
139 | // return super.onTouchEvent(event);
140 | this.postInvalidate();
141 | return true;
142 | }
143 | /**
144 | * Author : hmg25 Version: 1.0 Description : 求解直线P1P2和直线P3P4的交点坐标
145 | */
146 | public PointF getCross(PointF P1, PointF P2, PointF P3, PointF P4) {
147 | PointF CrossP = new PointF();
148 | // 二元函数通式: y=ax+b
149 | float a1 = (P2.y - P1.y) / (P2.x - P1.x);
150 | float b1 = ((P1.x * P2.y) - (P2.x * P1.y)) / (P1.x - P2.x);
151 |
152 | float a2 = (P4.y - P3.y) / (P4.x - P3.x);
153 | float b2 = ((P3.x * P4.y) - (P4.x * P3.y)) / (P3.x - P4.x);
154 | CrossP.x = (b2 - b1) / (a1 - a2);
155 | CrossP.y = a1 * CrossP.x + b1;
156 | return CrossP;
157 | }
158 |
159 | private void calcPoints() {
160 | mMiddleX = (mTouch.x + mCornerX) / 2;
161 | mMiddleY = (mTouch.y + mCornerY) / 2;
162 | mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)
163 | * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);
164 | mBezierControl1.y = mCornerY;
165 | mBezierControl2.x = mCornerX;
166 | mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
167 | * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);
168 |
169 | mBezierStart1.x = mBezierControl1.x - (mCornerX - mBezierControl1.x)
170 | / 2;
171 | mBezierStart1.y = mCornerY;
172 |
173 | // 当mBezierStart1.x < 0或者mBezierStart1.x > 480时
174 | // 如果继续翻页,会出现BUG故在此限制
175 | if (mTouch.x > 0 && mTouch.x < mWidth) {
176 | if (mBezierStart1.x < 0 || mBezierStart1.x > mWidth) {
177 | if (mBezierStart1.x < 0)
178 | mBezierStart1.x = mWidth - mBezierStart1.x;
179 |
180 | float f1 = Math.abs(mCornerX - mTouch.x);
181 | float f2 = mWidth * f1 / mBezierStart1.x;
182 | mTouch.x = Math.abs(mCornerX - f2);
183 |
184 | float f3 = Math.abs(mCornerX - mTouch.x)
185 | * Math.abs(mCornerY - mTouch.y) / f1;
186 | mTouch.y = Math.abs(mCornerY - f3);
187 |
188 | mMiddleX = (mTouch.x + mCornerX) / 2;
189 | mMiddleY = (mTouch.y + mCornerY) / 2;
190 |
191 | mBezierControl1.x = mMiddleX - (mCornerY - mMiddleY)
192 | * (mCornerY - mMiddleY) / (mCornerX - mMiddleX);
193 | mBezierControl1.y = mCornerY;
194 |
195 | mBezierControl2.x = mCornerX;
196 | mBezierControl2.y = mMiddleY - (mCornerX - mMiddleX)
197 | * (mCornerX - mMiddleX) / (mCornerY - mMiddleY);
198 | // Log.i("hmg", "mTouchX --> " + mTouch.x + " mTouchY--> "
199 | // + mTouch.y);
200 | // Log.i("hmg", "mBezierControl1.x-- " + mBezierControl1.x
201 | // + " mBezierControl1.y -- " + mBezierControl1.y);
202 | // Log.i("hmg", "mBezierControl2.x -- " + mBezierControl2.x
203 | // + " mBezierControl2.y -- " + mBezierControl2.y);
204 | mBezierStart1.x = mBezierControl1.x
205 | - (mCornerX - mBezierControl1.x) / 2;
206 | }
207 | }
208 | mBezierStart2.x = mCornerX;
209 | mBezierStart2.y = mBezierControl2.y - (mCornerY - mBezierControl2.y)
210 | / 2;
211 |
212 | mTouchToCornerDis = (float) Math.hypot((mTouch.x - mCornerX),
213 | (mTouch.y - mCornerY));
214 |
215 | mBezierEnd1 = getCross(mTouch, mBezierControl1, mBezierStart1,
216 | mBezierStart2);
217 | mBezierEnd2 = getCross(mTouch, mBezierControl2, mBezierStart1,
218 | mBezierStart2);
219 |
220 | mBeziervertex1.x = (mBezierStart1.x + 2 * mBezierControl1.x + mBezierEnd1.x) / 4;
221 | mBeziervertex1.y = (2 * mBezierControl1.y + mBezierStart1.y + mBezierEnd1.y) / 4;
222 | mBeziervertex2.x = (mBezierStart2.x + 2 * mBezierControl2.x + mBezierEnd2.x) / 4;
223 | mBeziervertex2.y = (2 * mBezierControl2.y + mBezierStart2.y + mBezierEnd2.y) / 4;
224 | }
225 |
226 | /**
227 | * 绘制当前页
228 | */
229 | private void drawCurrentPageArea(Canvas canvas, Bitmap bitmap, Path path) {
230 | mPath0.reset();
231 | mPath0.moveTo(mBezierStart1.x, mBezierStart1.y);
232 | mPath0.quadTo(mBezierControl1.x, mBezierControl1.y, mBezierEnd1.x,
233 | mBezierEnd1.y);
234 | mPath0.lineTo(mTouch.x, mTouch.y);
235 | mPath0.lineTo(mBezierEnd2.x, mBezierEnd2.y);
236 | mPath0.quadTo(mBezierControl2.x, mBezierControl2.y, mBezierStart2.x,
237 | mBezierStart2.y);
238 | mPath0.lineTo(mCornerX, mCornerY);
239 | mPath0.close();
240 |
241 | canvas.save();
242 | canvas.clipPath(path, Region.Op.XOR);
243 | canvas.drawBitmap(bitmap, 0, 0, null);
244 | canvas.restore();
245 |
246 | }
247 |
248 | /**
249 | * 绘制下一页
250 | */
251 | private void drawNextPageAreaAndShadow(Canvas canvas, Bitmap bitmap) {
252 | mPath1.reset();
253 | mPath1.moveTo(mBezierStart1.x, mBezierStart1.y);
254 | mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);
255 | mPath1.lineTo(mBeziervertex2.x, mBeziervertex2.y);
256 | mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);
257 | mPath1.lineTo(mCornerX, mCornerY);
258 | mPath1.close();
259 |
260 | mDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl1.x
261 | - mCornerX, mBezierControl2.y - mCornerY));
262 | int leftx;
263 | int rightx;
264 | GradientDrawable mBackShadowDrawable;
265 | if (mIsRTandLB) {
266 | leftx = (int) (mBezierStart1.x);
267 | rightx = (int) (mBezierStart1.x + mTouchToCornerDis / 4);
268 | mBackShadowDrawable = mBackShadowDrawableLR;
269 | } else {
270 | leftx = (int) (mBezierStart1.x - mTouchToCornerDis / 4);
271 | rightx = (int) mBezierStart1.x;
272 | mBackShadowDrawable = mBackShadowDrawableRL;
273 | }
274 | canvas.save();
275 | canvas.clipPath(mPath0);
276 | canvas.clipPath(mPath1, Region.Op.INTERSECT);
277 | canvas.drawBitmap(bitmap, 0, 0, null);
278 | canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
279 | mBackShadowDrawable.setBounds(leftx, (int) mBezierStart1.y, rightx,
280 | (int) (mMaxLength + mBezierStart1.y));
281 | mBackShadowDrawable.draw(canvas);
282 | canvas.restore();
283 | }
284 |
285 | public void setBitmaps(Bitmap bm1, Bitmap bm2) {
286 | mCurPageBitmap = bm1;
287 | mNextPageBitmap = bm2;
288 | }
289 |
290 | public void setScreen(int w, int h) {
291 | mWidth = w;
292 | mHeight = h;
293 | }
294 |
295 | public void onDraw(Canvas canvas) {
296 | canvas.drawColor(0xFFAAAAAA);
297 | calcPoints();
298 | drawCurrentPageArea(canvas, mCurPageBitmap, mPath0);
299 | drawNextPageAreaAndShadow(canvas, mNextPageBitmap);
300 | drawCurrentPageShadow(canvas);
301 | drawCurrentBackArea(canvas, mCurPageBitmap);
302 | }
303 |
304 | /**
305 | * 创建阴影的GradientDrawable
306 | */
307 | private void createDrawable() {
308 | int[] color = { 0x333333, 0xb0333333 };
309 | mFolderShadowDrawableRL = new GradientDrawable(
310 | GradientDrawable.Orientation.RIGHT_LEFT, color);
311 | mFolderShadowDrawableRL
312 | .setGradientType(GradientDrawable.LINEAR_GRADIENT);
313 |
314 | mFolderShadowDrawableLR = new GradientDrawable(
315 | GradientDrawable.Orientation.LEFT_RIGHT, color);
316 | mFolderShadowDrawableLR
317 | .setGradientType(GradientDrawable.LINEAR_GRADIENT);
318 |
319 | mBackShadowColors = new int[] { 0xff111111, 0x111111 };
320 | mBackShadowDrawableRL = new GradientDrawable(
321 | GradientDrawable.Orientation.RIGHT_LEFT, mBackShadowColors);
322 | mBackShadowDrawableRL.setGradientType(GradientDrawable.LINEAR_GRADIENT);
323 |
324 | mBackShadowDrawableLR = new GradientDrawable(
325 | GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors);
326 | mBackShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT);
327 |
328 | mFrontShadowColors = new int[] { 0x80111111, 0x111111 };
329 | mFrontShadowDrawableVLR = new GradientDrawable(
330 | GradientDrawable.Orientation.LEFT_RIGHT, mFrontShadowColors);
331 | mFrontShadowDrawableVLR
332 | .setGradientType(GradientDrawable.LINEAR_GRADIENT);
333 | mFrontShadowDrawableVRL = new GradientDrawable(
334 | GradientDrawable.Orientation.RIGHT_LEFT, mFrontShadowColors);
335 | mFrontShadowDrawableVRL
336 | .setGradientType(GradientDrawable.LINEAR_GRADIENT);
337 |
338 | mFrontShadowDrawableHTB = new GradientDrawable(
339 | GradientDrawable.Orientation.TOP_BOTTOM, mFrontShadowColors);
340 | mFrontShadowDrawableHTB
341 | .setGradientType(GradientDrawable.LINEAR_GRADIENT);
342 |
343 | mFrontShadowDrawableHBT = new GradientDrawable(
344 | GradientDrawable.Orientation.BOTTOM_TOP, mFrontShadowColors);
345 | mFrontShadowDrawableHBT
346 | .setGradientType(GradientDrawable.LINEAR_GRADIENT);
347 | }
348 |
349 | /**
350 | * 绘制翻起页的阴影
351 | */
352 | public void drawCurrentPageShadow(Canvas canvas) {
353 | double degree;
354 | if (mIsRTandLB) {
355 | degree = Math.PI
356 | / 4
357 | - Math.atan2(mBezierControl1.y - mTouch.y, mTouch.x
358 | - mBezierControl1.x);
359 | } else {
360 | degree = Math.PI
361 | / 4
362 | - Math.atan2(mTouch.y - mBezierControl1.y, mTouch.x
363 | - mBezierControl1.x);
364 | }
365 | // 翻起页阴影顶点与touch点的距离
366 | double d1 = (float) 25 * 1.414 * Math.cos(degree);
367 | double d2 = (float) 25 * 1.414 * Math.sin(degree);
368 | float x = (float) (mTouch.x + d1);
369 | float y;
370 | if (mIsRTandLB) {
371 | y = (float) (mTouch.y + d2);
372 | } else {
373 | y = (float) (mTouch.y - d2);
374 | }
375 | mPath1.reset();
376 | mPath1.moveTo(x, y);
377 | mPath1.lineTo(mTouch.x, mTouch.y);
378 | mPath1.lineTo(mBezierControl1.x, mBezierControl1.y);
379 | mPath1.lineTo(mBezierStart1.x, mBezierStart1.y);
380 | mPath1.close();
381 | float rotateDegrees;
382 | canvas.save();
383 |
384 | canvas.clipPath(mPath0, Region.Op.XOR);
385 | canvas.clipPath(mPath1, Region.Op.INTERSECT);
386 | int leftx;
387 | int rightx;
388 | GradientDrawable mCurrentPageShadow;
389 | if (mIsRTandLB) {
390 | leftx = (int) (mBezierControl1.x);
391 | rightx = (int) mBezierControl1.x + 25;
392 | mCurrentPageShadow = mFrontShadowDrawableVLR;
393 | } else {
394 | leftx = (int) (mBezierControl1.x - 25);
395 | rightx = (int) mBezierControl1.x + 1;
396 | mCurrentPageShadow = mFrontShadowDrawableVRL;
397 | }
398 |
399 | rotateDegrees = (float) Math.toDegrees(Math.atan2(mTouch.x
400 | - mBezierControl1.x, mBezierControl1.y - mTouch.y));
401 | canvas.rotate(rotateDegrees, mBezierControl1.x, mBezierControl1.y);
402 | mCurrentPageShadow.setBounds(leftx,
403 | (int) (mBezierControl1.y - mMaxLength), rightx,
404 | (int) (mBezierControl1.y));
405 | mCurrentPageShadow.draw(canvas);
406 | canvas.restore();
407 |
408 | mPath1.reset();
409 | mPath1.moveTo(x, y);
410 | mPath1.lineTo(mTouch.x, mTouch.y);
411 | mPath1.lineTo(mBezierControl2.x, mBezierControl2.y);
412 | mPath1.lineTo(mBezierStart2.x, mBezierStart2.y);
413 | mPath1.close();
414 | canvas.save();
415 | canvas.clipPath(mPath0, Region.Op.XOR);
416 | canvas.clipPath(mPath1, Region.Op.INTERSECT);
417 | if (mIsRTandLB) {
418 | leftx = (int) (mBezierControl2.y);
419 | rightx = (int) (mBezierControl2.y + 25);
420 | mCurrentPageShadow = mFrontShadowDrawableHTB;
421 | } else {
422 | leftx = (int) (mBezierControl2.y - 25);
423 | rightx = (int) (mBezierControl2.y + 1);
424 | mCurrentPageShadow = mFrontShadowDrawableHBT;
425 | }
426 | rotateDegrees = (float) Math.toDegrees(Math.atan2(mBezierControl2.y
427 | - mTouch.y, mBezierControl2.x - mTouch.x));
428 | canvas.rotate(rotateDegrees, mBezierControl2.x, mBezierControl2.y);
429 | float temp;
430 | if (mBezierControl2.y < 0)
431 | temp = mBezierControl2.y - mHeight;
432 | else
433 | temp = mBezierControl2.y;
434 |
435 | int hmg = (int) Math.hypot(mBezierControl2.x, temp);
436 | if (hmg > mMaxLength)
437 | mCurrentPageShadow
438 | .setBounds((int) (mBezierControl2.x - 25) - hmg, leftx,
439 | (int) (mBezierControl2.x + mMaxLength) - hmg,
440 | rightx);
441 | else
442 | mCurrentPageShadow.setBounds(
443 | (int) (mBezierControl2.x - mMaxLength), leftx,
444 | (int) (mBezierControl2.x), rightx);
445 |
446 | // Log.i("hmg", "mBezierControl2.x " + mBezierControl2.x
447 | // + " mBezierControl2.y " + mBezierControl2.y);
448 | mCurrentPageShadow.draw(canvas);
449 | canvas.restore();
450 | }
451 |
452 | /**
453 | * 绘制翻起页背面
454 | */
455 | private void drawCurrentBackArea(Canvas canvas, Bitmap bitmap) {
456 | int i = (int) (mBezierStart1.x + mBezierControl1.x) / 2;
457 | float f1 = Math.abs(i - mBezierControl1.x);
458 | int i1 = (int) (mBezierStart2.y + mBezierControl2.y) / 2;
459 | float f2 = Math.abs(i1 - mBezierControl2.y);
460 | float f3 = Math.min(f1, f2);
461 | mPath1.reset();
462 | mPath1.moveTo(mBeziervertex2.x, mBeziervertex2.y);
463 | mPath1.lineTo(mBeziervertex1.x, mBeziervertex1.y);
464 | mPath1.lineTo(mBezierEnd1.x, mBezierEnd1.y);
465 | mPath1.lineTo(mTouch.x, mTouch.y);
466 | mPath1.lineTo(mBezierEnd2.x, mBezierEnd2.y);
467 | mPath1.close();
468 | GradientDrawable mFolderShadowDrawable;
469 | int left;
470 | int right;
471 | if (mIsRTandLB) {
472 | left = (int) (mBezierStart1.x - 1);
473 | right = (int) (mBezierStart1.x + f3 + 1);
474 | mFolderShadowDrawable = mFolderShadowDrawableLR;
475 | } else {
476 | left = (int) (mBezierStart1.x - f3 - 1);
477 | right = (int) (mBezierStart1.x + 1);
478 | mFolderShadowDrawable = mFolderShadowDrawableRL;
479 | }
480 | canvas.save();
481 | canvas.clipPath(mPath0);
482 | canvas.clipPath(mPath1, Region.Op.INTERSECT);
483 |
484 | mPaint.setColorFilter(mColorMatrixFilter);
485 |
486 | float dis = (float) Math.hypot(mCornerX - mBezierControl1.x,
487 | mBezierControl2.y - mCornerY);
488 | float f8 = (mCornerX - mBezierControl1.x) / dis;
489 | float f9 = (mBezierControl2.y - mCornerY) / dis;
490 | mMatrixArray[0] = 1 - 2 * f9 * f9;
491 | mMatrixArray[1] = 2 * f8 * f9;
492 | mMatrixArray[3] = mMatrixArray[1];
493 | mMatrixArray[4] = 1 - 2 * f8 * f8;
494 | mMatrix.reset();
495 | mMatrix.setValues(mMatrixArray);
496 | mMatrix.preTranslate(-mBezierControl1.x, -mBezierControl1.y);
497 | mMatrix.postTranslate(mBezierControl1.x, mBezierControl1.y);
498 | canvas.drawBitmap(bitmap, mMatrix, mPaint);
499 | // canvas.drawBitmap(bitmap, mMatrix, null);
500 | mPaint.setColorFilter(null);
501 | canvas.rotate(mDegrees, mBezierStart1.x, mBezierStart1.y);
502 | mFolderShadowDrawable.setBounds(left, (int) mBezierStart1.y, right,
503 | (int) (mBezierStart1.y + mMaxLength));
504 | mFolderShadowDrawable.draw(canvas);
505 | canvas.restore();
506 | }
507 |
508 | public void computeScroll() {
509 | super.computeScroll();
510 | if (mScroller.computeScrollOffset()) {
511 | float x = mScroller.getCurrX();
512 | float y = mScroller.getCurrY();
513 | mTouch.x = x;
514 | mTouch.y = y;
515 | postInvalidate();
516 | }
517 | }
518 |
519 | private void startAnimation(int delayMillis) {
520 | int dx, dy;
521 | // dx 水平方向滑动的距离,负值会使滚动向左滚动
522 | // dy 垂直方向滑动的距离,负值会使滚动向上滚动
523 | if (mCornerX > 0) {
524 | dx = -(int) (mWidth + mTouch.x);
525 | } else {
526 | dx = (int) (mWidth - mTouch.x + mWidth);
527 | }
528 | if (mCornerY > 0) {
529 | dy = (int) (mHeight - mTouch.y);
530 | } else {
531 | dy = (int) (1 - mTouch.y); // 防止mTouch.y最终变为0
532 | }
533 | mScroller.startScroll((int) mTouch.x, (int) mTouch.y, dx, dy,
534 | delayMillis);
535 | }
536 |
537 | public void abortAnimation() {
538 | if (!mScroller.isFinished()) {
539 | mScroller.abortAnimation();
540 | }
541 | }
542 |
543 | public boolean canDragOver() {
544 | if (mTouchToCornerDis > mWidth / 10)
545 | return true;
546 | return false;
547 | }
548 |
549 | /**
550 | * 是否从左边翻向右边
551 | */
552 | public boolean DragToRight() {
553 | if (mCornerX > 0)
554 | return false;
555 | return true;
556 | }
557 | }
558 |
--------------------------------------------------------------------------------
/src/com/ebook/scansd/BookMark.java:
--------------------------------------------------------------------------------
1 | package com.ebook.scansd;
2 |
3 | import java.io.ByteArrayOutputStream;
4 | import java.io.FileInputStream;
5 | import java.io.FileOutputStream;
6 |
7 | import android.content.Context;
8 |
9 | public class BookMark {
10 |
11 | Context mContext;
12 | String fileName;
13 |
14 | public BookMark(Context context, String filename) {
15 | mContext = context;
16 | this.fileName = filename.substring(0, filename.lastIndexOf(".") + 1) + "mark.txt";
17 | }
18 |
19 | public BookMark(String filename) {
20 | // TODO Auto-generated constructor stub
21 | this.fileName = filename.substring(0, filename.lastIndexOf(".") + 1) + "mark.txt";
22 | }
23 |
24 | public void setContext(Context context) {
25 | mContext = context;
26 | }
27 |
28 | final static String DATA_URL = "/data/data";
29 |
30 | public void saveFile(String string) {
31 | // File file = new File(DATA_URL + FILE_NAME);
32 | try {
33 | // FileOutputStream outputStream = new FileOutputStream(file);
34 | FileOutputStream outputStream = mContext.openFileOutput(fileName,
35 | Context.MODE_WORLD_READABLE);
36 | outputStream.write(string.getBytes());
37 | outputStream.close();
38 | } catch (Exception e) {
39 | // TODO: handle exception
40 | e.printStackTrace();
41 | }
42 | }
43 |
44 | public String loadFile() {
45 |
46 | try {
47 | // File file = new File(DATA_URL + FILE_NAME);
48 | FileInputStream inputStream = mContext.openFileInput(fileName);
49 | ByteArrayOutputStream stream = new ByteArrayOutputStream();
50 | byte[] buffer = new byte[1024];
51 | int length = -1;
52 | while ((length = inputStream.read(buffer)) != -1) {
53 | stream.write(buffer, 0, length);
54 | }
55 | stream.close();
56 | inputStream.close();
57 | return stream.toString();
58 | } catch (Exception e) {
59 | // TODO: handle exception
60 | e.printStackTrace();
61 | }
62 | return null;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/src/com/ebook/scansd/ScanSD.java:
--------------------------------------------------------------------------------
1 | package com.ebook.scansd;
2 |
3 | import java.io.File;
4 | import java.util.ArrayList;
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | public class ScanSD {
9 | String FILE_TYPE = ".txt";
10 | private ArrayList list;
11 |
12 | public ScanSD(String fileType) {
13 | FILE_TYPE = fileType;
14 | list = new ArrayList();
15 | }
16 |
17 | public ScanSD() {
18 | list = new ArrayList();
19 | }
20 |
21 | public ArrayList