編輯:關於Android編程
Filter閱讀是我最近寫的一個Android的閱讀器,用於看英文的書(中文暫時不支持,會亂碼,下一版再改).
在這裡開源給大家(Android studio的)
源碼下載地址:http://pan.baidu.com/s/1bpvAzIv
apk下載地址:http://shouji.baidu.com/software/9736272.html
vcrpvK7OxLz+tcS12Na3LjxiciAvPg0K1eLA79PQ0ru149Do0qrXotLiLs2ouf3OxLz+udzA7cb3u/HIobW9tcS12Na3ysdGaWxlOi8vLyu12Na3uPHKvbXELtDo0qrO0sPHvdjIodK7z8IuyLu6877NtcO1vcHL1f3It7XEzsS8/rXY1rc8L3A+DQo8cD7Iu7rzvs3Kx73izvbOxLz+xNrI3SzV4sDvztLTw7XEysdGaWxlQ2hhbm5lbMDgLNKyvs3Kx87EvP7NqLXAwOAuPC9wPg0KPHA+SmF2YSBOSU/W0LXERmlsZUNoYW5uZWzKx9K7uPbBrL3Ttb3OxLz+tcTNqLXAoaO/ydLUzai5/c7EvP7NqLXAtsHQtM7EvP6hozwvcD4NCjxwPtXiuPbA4LXEusO0psrH0KfCyrjfLNW808PJ2Sy2+MfS1+6087bByKG1pbj2zsS8/r/J0tS1vTJHLLu509C+zcrHxNzX1NPJtcS+9raotNPExMDvv6rKvLbByKEo1eK+zb3ivvbBy7zH16HJz7TOtsHK6c671sO6zcz416q1xM7KzOIpLsv50tTO0sPH08PV4rj2wOA8L3A+DQo8cD6+38zltPrC68jnz8I6PC9wPg0KPHByZSBjbGFzcz0="brush:java;"> public class AnalysisTXTBook extends AnalysisBook { private RandomAccessFile aFile; private FileChannel fc; private MappedByteBuffer out; public AnalysisTXTBook(String path) { try { // 這個類是隨機讀取文件的類 可以從任意位置讀文件 aFile = new RandomAccessFile(path, "rw"); // 文件通道 直接強行把存儲內的文件放到內存中 效率高 最大單個文件能達到2G fc = aFile.getChannel(); //獲取所讀文件的字符數 bookLength = aFile.length(); //映射到MappedByteBuffer上 out = fc.map(FileChannel.MapMode.READ_WRITE, 0, aFile.length()); Logger.d("aFile.length():" + aFile.length()); // 一定要關上 fc.close(); aFile.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public String getBookContent(int start, int lenth) { String s = ""; //開始位置不能小於0 if (start < 0) { start = 0; } int end; //判斷所要的長度是否超出文字總數 如果超出就給他到最後一個字的 if (bookLength >= start + lenth) { end = start + lenth; } else { end = (int) bookLength; } //這樣請求到最後發現返回值是空的話 就知道已經結束了 if (start >= end) { return ""; } // Logger.d("out.array().length" + out.array().length); for (int i = start; i < end; i++) { // System.out.print((char) out.get(i)); s = s + (char) out.get(i); } return s; } @Override public long getBookLength() { return bookLength; } }
以上那個類所繼承的類的代碼如下:
public abstract class AnalysisBook { public long bookLength;// 書總字數 public abstract String getBookContent(int start, int lenth); public abstract long getBookLength(); }
這個是典型的工廠模式,因為我目前這版僅支持txt格式 後續會增加epub,pdf,mobi等格式,到時候新增格式的時候直接繼承這個類並實現這兩個方法即可,保證了開閉原則.
這樣,只要在需要讀取書籍內容的地方根據書的格式new出這個類
if (Globle.nowBookPath.contains(".txt") || Globle.nowBookPath.contains(".TXT")) { ab = new AnalysisTXTBook(Globle.nowBookPath); }
然後在通過這種方式獲取到指定開始和結束位置的內容即可
nextContent = ab.getBookContent(nextPosition, ReadView.WORD_COUNT);
2,點擊單詞選擇並翻譯
點擊選擇單詞我是參考這篇文章做的
http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%B1%87/25528.shtml
不過這篇文章中僅適用於文章中是根據空格分割單詞的,適用性太差,我做了一些改進
private Integer[] getUnLetterPosition(String s) { Listindices = new ArrayList (); Pattern p; Matcher m; p = Pattern.compile("[a-zA-Z]"); m = p.matcher(s); // 嘗試在目標字符串裡查找下一個匹配子串。 int lastOnePosition = -1; while (m.find()) { // 獲取到匹配字符的結束點 if (m.start() - lastOnePosition != 1) { // 獲取的m.start是每個符合正則表達式的字符的位置 // 而我想要的是不符合的位置 而斷掉的位置就必然是不符合的位置 indices.add(lastOnePosition + 1); } lastOnePosition = m.start(); } return (Integer[]) indices.toArray(new Integer[0]); }
我這裡通過正則的方法獲取到所有非字母的位置,然後通過非字母的位置分割單詞
public void getEachWord() { // 先把從textview中得到的文字轉成Spannable Spannable spans = (Spannable) getText(); // 獲取到每個空格的位置 // Integer[] indices = getIndices(textView.getText().toString().trim(), // ' '); Integer[] indices = getUnLetterPosition(getText().toString()); int start = 0; int end = 0; // to cater last/only word loop will run equal to the length of // indices.length // ClickableSpan clickSpan; for (int i = 0; i <= indices.length; i++) { // 給每個單詞一個點擊事件 clickSpan = getClickableSpan(); // 末尾不能超出文本 end = (i < indices.length ? indices[i] : spans.length()); // 循環給每個單詞設置clickspan spans.setSpan(clickSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); start = end + 1;//+1表示只允許有一個非字母間隔 否則就會把別的東西加進去 } // 改變選中文本的高亮顏色 setHighlightColor(getResources().getColor(R.color.top_bar)); }
但是同時又有一個新問題,就是當出現這樣的情況 “or create a new1個以上repository on the command line”
就是當非字母多於1個時,會導致repository這個單詞被分割成”個以上repository”具體原因很簡單 因為獲取的時候是從第n個非字母位置到第n個+1非字母位置.所以造成的這種結果.
我試過,直接記錄真實的位置的方法,但是那樣的效率太低,極大的影響性能.於是我想到了另一種笨辦法.就是在用戶點擊單詞的時候把那些非字母替換掉.
private String getWordAgain(String s) { String str = s.replaceAll("[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~!@#¥%……&;*()——+|{}【】\"‘;:”“’。,、?|-]", ""); str = str.replaceAll("\n", ""); str = str.replaceAll("\r", ""); str = str.replaceAll("\\s", ""); return str; }
但是這個方法有一個問題,就是不能去掉中文,誰要是有更好的辦法 希望能指出,謝謝
3,文件的分頁和記錄上次的位置
解決分頁問題的關鍵是,得知道一頁可以放下多少個字符,然後下一頁就以上一頁結束的位置開始.
關於得到一頁有多少字符,我是參照這個來的
http://my.oschina.net/gotax/blog/136860
這個方法有個問題,就是必須得先給textview settext,文中作者實際上兩次settext.
我稍微改了一下
我首先設了一個常量值
//要設置的總字數,一個固定值 只要保證大於view能顯示的下的數量就行了
public static int WORD_COUNT = 1800;
如注釋所說,這個值大於屏幕能顯示的數量就行了,盡量接近,但是一定要大於.
獲取下一頁內容:
然後剛開始打開書的時候先給當前的textview設上文字,然後就可以得到最後一個字符的位置,然後就能獲取到下一頁的起始位置(結束位置不需要獲取,直接還是按上邊的那個常量值設置,反正超出去的也看不見)這樣下一頁的內容就獲取到了.
獲取上一頁內容:
獲取上一頁內容就不太容易了,我的方法很不好,誰有好方法希望能說一下.
我的方法簡單來說就是先給textview設上當前頁開始位置減去WORD_COUNT的位置為起始設WORD_COUNT 這麼多個字符.然後再獲取到當前頁顯示了多少個字符,然後再以當前頁起始點減去這個可見字符數,以此為起點到WORD_COUNT 這麼多字符,即為前一頁的內容.說起來很繞,我直接貼上代碼吧
//必須先給V2設置了文字 且通過V2才能得知下一頁開始的位置 這裡雖然設置了文字 但是並不為了顯示
read2View.setText(ab.getBookContent(nowPosition - ReadView.WORD_COUNT, ReadView.WORD_COUNT));
//這個東西得等V onlayout完成之後才能調用 否則的話會空指針 previsousPosition = read2View.getPreviousStartPosition(nowPosition); previsousContent = ab.getBookContent(previsousPosition, ReadView.WORD_COUNT);
/** * 獲取前一頁的首字符位置 */ public int getPreviousStartPosition(int currentStartPosition) { int res = 0; res = currentStartPosition - getVisibleWordAmount(); return res; }
其他要說的:
因為我這種獲取前後內容的方式是階段式的,所以很難用viewpager顯示,於是我自定義了一個viewgroup,這個viewgroup操作兩個readview,readview是繼承自textview的類,實現了獲取末尾字符位置的方法.其中一個readview是真正用戶看到的,我成他為rv1,另一個readview主要是為了翻頁動畫和獲取上一頁內容二次存在的,我叫他rv2.
這個viewgroup監聽觸摸滑動事件(以下簡稱vg).左右滑是翻頁,上下滑是調出和收起選項卡.
但是後來遇到一個問題,就是觸摸事件的傳遞問題.readview的點擊單詞事件會搶走整個觸摸事件,導致vg不能翻頁. 於是我這裡寫了這麼個方法處理觸摸事件的分發.
在vg中繼承這個方法
@Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: //在這裡初始化 觸摸事件 initDrag(ev); break; case MotionEvent.ACTION_MOVE: if (Math.abs(ev.getX() - firstDownX) > INTERCEPT_THRESHOLD || Math.abs(ev.getY() - firstDownY) > INTERCEPT_THRESHOLD) { //發現是滑動事件 就自己處理了 return true; } else { //發現不是自己處理,該給誰給誰 return false; } case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: //其實這裡是多余的 // getParent().requestDisallowInterceptTouchEvent(false); } return super.onInterceptTouchEvent(ev); }
這樣就成功的分發了觸摸事件.
忘了說了,翻譯用的是有道接口,很簡單 直接查下有道的API就可以了.
另外有道詞典會監測用戶復制單詞的行為,所以在我這個應用中每次查詞我都會復制一遍單詞,所以如果這時候有道詞典app處於打開狀態,有道詞典就會彈出一個窗口.顯示單詞釋義並提供發音.因為有道提供的接口並不提供發音,所以這個功能還是挺實用的.
over
Android藍牙串口通訊 閒著無聊玩起了Android藍牙模塊與單片機藍牙模塊的通信,簡單思路就是要手機通過藍牙發送控制指令給單片機,並作簡單的控制應用。單片機的藍牙
我們知道,android自第一代發布以來,它的版本更新迭代的速度可以說是非常快的,但是android又是一個移動操作系統,是面對所有的用戶的,並不是一個行業專用的系統,這
一. Mac OS X(10.11.4)編譯環境設置1.1 創建大小寫敏感的磁盤鏡像可以通過磁盤管理工具進行設置,也可以通過以下命令生成70g的鏡像文件sudo hdiu
本文實例講述了Android實現將一個Activity設置成窗口樣式的方法。分享給大家供大家參考,具體如下:1.在res/value文件夾下的style.xml文件中加入