傳送門:Android+Sqlite 實現古詩閱讀應用(一)html
Hi,又回來了,最近接到不少熱情洋溢的小夥伴們的來信,吼開心哈,我會繼續努力的=-=!java
上回的東西咱們作到了有個textview能隨機選擇詩來進行顯示,這也是我作這個東西的初衷,我想找我到底有哪些古詩沒有讀過,更想感覺一下風吹哪頁看哪頁的閒適(扯遠了=-=!),因此功能如今差很少算是結束了,android
不過一個古詩應用這麼醜可不行,還有就是,我找到了我要的詩我也得能收藏啊,要是下次忘了可怎麼辦啊,因此這裏面還有一些知識點,咱們能從接下來的功能中學到:正則表達式
打開數據庫,隨着數據庫的增大會有一點卡頓,咱們加個界面來過渡緩解一下:sql
1 package com.lfk.poem; 2 import android.app.Activity; 3 import android.content.Intent; 4 import android.os.Bundle; 5 import android.util.Log; 6 import android.view.View; 7 import android.view.animation.AlphaAnimation; 8 import android.view.animation.Animation; 9 10 /** 11 * Created by Administrator on 2015/4/11. 12 */ 13 public class Opening extends Activity { 14 @Override 15 public void onCreate(Bundle savedInstanceState) { 16 super.onCreate(savedInstanceState); 17 final View view = View.inflate(this, R.layout.activity_opening, null); 18 setContentView(view); 19 //漸變展現啓動屏 20 AlphaAnimation start = new AlphaAnimation(0.3f,1.0f); 21 start.setDuration(2000); 22 view.startAnimation(start); 23 start.setAnimationListener(new Animation.AnimationListener() 24 { 25 @Override 26 public void onAnimationEnd(Animation arg0) { 27 Log.e("linc", "---start!"); 28 try{ 29 Intent intent = new Intent(); 30 intent.setClass(Opening.this,MainActivity.class); 31 Opening.this.startActivity(intent); 32 Opening.this.finish(); 33 } 34 catch(Exception e) 35 { 36 e.printStackTrace(); 37 } 38 } 39 @Override 40 public void onAnimationRepeat(Animation animation) {} 41 @Override 42 public void onAnimationStart(Animation animation) {} 43 }); 44 45 46 } 47 }
這是作過的樣子:數據庫
上次爲了測試咱們只導入了5首古詩做爲測試,這回用正則表達式調整了格式,導入了唐詩三百首。app
將txt作成了這種格式,而後倒入數據庫管理軟件。dom
數據庫裏的格式就是這樣的了,而後替換數據庫就行了,想要現成的可找我要。ide
天然不用說添加本身喜歡的古風背景就好。函數
刷新我不用Button了,改用google的下拉刷新,我在這個博文裏寫過:http://www.cnblogs.com/lfk-dsk/p/4433319.html
每次刷新一下就會從新找一首詩。
1 package com.lfk.poem; 2 3 import android.app.Activity; 4 import android.content.Intent; 5 import android.database.Cursor; 6 import android.database.sqlite.SQLiteDatabase; 7 import android.graphics.Typeface; 8 import android.os.Bundle; 9 import android.os.Environment; 10 import android.os.Handler; 11 import android.support.v4.widget.SwipeRefreshLayout; 12 import android.util.Log; 13 import android.view.Menu; 14 import android.view.MenuInflater; 15 import android.view.MenuItem; 16 import android.widget.RelativeLayout; 17 import android.widget.TextView; 18 import android.widget.Toast; 19 20 import java.io.File; 21 import java.io.FileNotFoundException; 22 import java.io.FileOutputStream; 23 import java.io.IOException; 24 import java.io.InputStream; 25 26 27 public class MainActivity extends Activity { 28 private final int BUFFER_SIZE = 400000; 29 public static final String DB_NAME = "poem_all.db"; //保存的數據庫文件名 30 public static final String DB_USER_NAME = "poem_user.db"; 31 public static final String PACKAGE_NAME = "com.lfk.poem";// 應用的包名 32 public static final String DB_PATH = "/data" 33 + Environment.getDataDirectory().getAbsolutePath() +"/" 34 + PACKAGE_NAME+ "/databases"; // 在手機裏存放數據庫的位置 35 private SwipeRefreshLayout swipeLayout; 36 private RelativeLayout main_layout; 37 private TextView textView; 38 private static int ID = 0; 39 private String NAME; 40 private String POEM; 41 @Override 42 protected void onCreate(Bundle savedInstanceState) { 43 super.onCreate(savedInstanceState); 44 setContentView(R.layout.activity_main); 45 46 Typeface typeface = Typeface.createFromAsset(getAssets(),"fonts/font_ksj.ttf"); 47 textView = (TextView)findViewById(R.id.text_view); 48 textView.setTypeface(typeface); 49 50 main_layout = (RelativeLayout)findViewById(R.id.main_layout); 51 ChangeBackground(); 52 FindaPoem(); 53 swipeLayout = (SwipeRefreshLayout) this.findViewById(R.id.swipe_refresh); 54 swipeLayout.setColorScheme(R.color.haah); 55 swipeLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { 56 @Override 57 public void onRefresh() { 58 new Handler().postDelayed(new Runnable() {//延遲跳轉=-= 59 public void run() { 60 swipeLayout.setRefreshing(true); 61 FindaPoem(); 62 swipeLayout.setRefreshing(false); 63 } 64 }, 500); 65 } 66 }); 67 } 68 private void FindaPoem() { 69 int ll = (int) (1 + Math.random() * (59170)); 70 ID = ll; 71 SQLiteDatabase database = openDatabase(); 72 Cursor cursor = database.rawQuery("Select * From poem Where _id = " + ll, null); 73 cursor.moveToFirst(); 74 String poem = cursor.getString(1)+"\n"+"\n"+cursor.getString(2)+"\n"+"\n"+cursor.getString(13); 75 NAME = cursor.getString(2)+": "+cursor.getString(1); 76 POEM = cursor.getString(13); 77 Log.e(poem, "================"); 78 textView.setText(poem); 79 cursor.close(); 80 database.close(); 81 } 82 private void ChangeBackground(){ 83 int ln = (int) (1 + Math.random() * (5)); 84 switch (ln){ 85 case 1: 86 main_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.detail_bg)); 87 break; 88 case 2: 89 main_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.navigation_1)); 90 break; 91 case 3: 92 main_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.navigation_2)); 93 break; 94 case 4: 95 main_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.navigation_3)); 96 break; 97 case 5: 98 main_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.navigation_4)); 99 break; 100 } 101 } 102 public SQLiteDatabase openDatabase() { 103 try { 104 File myDataPath = new File(DB_PATH); 105 if (!myDataPath.exists()) 106 { 107 myDataPath.mkdirs();// 若是沒有這個目錄,則建立 108 } 109 String dbfile = myDataPath+"/"+DB_NAME; 110 if (!(new File(dbfile).exists())) {// 判斷數據庫文件是否存在,若不存在則執行導入,不然直接打開數據庫 111 InputStream is; 112 is = this.getResources().openRawResource(R.raw.poem_all); // 欲導入的數據庫 113 FileOutputStream fos = new FileOutputStream(dbfile); 114 byte[] buffer = new byte[BUFFER_SIZE]; 115 int count = 0 ; 116 while ((count = is.read(buffer)) > 0) { 117 fos.write(buffer, 0, count); 118 } 119 fos.close(); 120 is.close(); 121 } 122 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbfile, null); 123 Log.e("=======================","get it ======================"); 124 return db; 125 } catch (FileNotFoundException e) { 126 Log.e("Database", "File not found"); 127 e.printStackTrace(); 128 } catch (IOException e) { 129 Log.e("Database", "IO exception"); 130 e.printStackTrace(); 131 } 132 return null; 133 } 134 void AddaPoemToCollect(){ 135 File myDataPath = new File(DB_PATH); 136 String dbfile = myDataPath+"/"+DB_USER_NAME; 137 SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbfile, null); 138 //ContentValues contentValues = new ContentValues(); 139 db.execSQL("UPDATE poem SET ticai = 1 WHERE _id ="+ID); 140 //db.insert("book", null, contentValues); 141 db.close(); 142 Toast.makeText(getApplicationContext(), 143 "Collect succeed", 144 Toast.LENGTH_SHORT).show(); 145 //ID++; 146 } 147 @Override 148 public boolean onCreateOptionsMenu(Menu menu) { 149 // Inflate the menu; this adds items to the action bar if it is present. 150 MenuInflater inflater = getMenuInflater(); 151 inflater.inflate(R.menu.menu_main, menu); 152 return super.onCreateOptionsMenu(menu); 153 } 154 155 @Override 156 public boolean onOptionsItemSelected(MenuItem item) { 157 // Handle action bar item clicks here. The action bar will 158 // automatically handle clicks on the Home/Up button, so long 159 // as you specify a parent activity in AndroidManifest.xml. 160 int id = item.getItemId(); 161 switch(id){ 162 case R.id.collect: 163 Intent intent = new Intent(this,Collect.class); 164 startActivity(intent); 165 break; 166 case R.id.like: 167 AddaPoemToCollect(); 168 break; 169 } 170 171 return super.onOptionsItemSelected(item); 172 } 173 }
這是修改過的主活動。
1.首先更換了字體放在assets文件夾內,在res裏面,沒有的請新建。
1 Typeface typeface = Typeface.createFromAsset(getAssets(),"fonts/font_ksj.ttf"); 2 textView = (TextView)findViewById(R.id.text_view); 3 textView.setTypeface(typeface);
獲取了字體資源,註冊了一個textview,把字體設置爲textview。
這是修改過的效果,纖細的字體很適合咱們的古詩!
2.
1 private void ChangeBackground(){ 2 int ln = (int) (1 + Math.random() * (5)); 3 switch (ln){ 4 case 1: 5 main_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.detail_bg)); 6 break; 7 case 2: 8 main_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.navigation_1)); 9 break; 10 case 3: 11 main_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.navigation_2)); 12 break; 13 case 4: 14 main_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.navigation_3)); 15 break; 16 case 5: 17 main_layout.setBackgroundDrawable(getResources().getDrawable(R.drawable.navigation_4)); 18 break; 19 } 20 }
添加了一個修改背景的函數,每次進入會隨機選擇背景,這樣咱們每次進入就有可能看到不同的背景了。
3.
1 private void FindaPoem() { 2 int ll = (int) (1 + Math.random() * (59170)); 3 ID = ll; 4 SQLiteDatabase database = openDatabase(); 5 Cursor cursor = database.rawQuery("Select * From poem Where _id = " + ll, null); 6 cursor.moveToFirst(); 7 String poem = cursor.getString(1)+"\n"+"\n"+cursor.getString(2)+"\n"+"\n"+cursor.getString(13); 8 NAME = cursor.getString(2)+": "+cursor.getString(1); 9 POEM = cursor.getString(13); 10 Log.e(poem, "================"); 11 textView.setText(poem); 12 cursor.close(); 13 database.close(); 14 }
從數據庫裏隨即一個數(我數據庫裏有59170首詩,=-=!)而後打開數據庫,找到ID爲此項的詩,而後獲取詩的內容,getString的號碼要按照你本身的數據庫須要選擇不一樣的欄位,
好比0位就是ID的欄位,我這裏面做者古詩名和古詩內容是分開存放的,並且加入了很多我要用的數據,因此欄位增長到了13個之多,本身作的話只須要三個欄位就好,一個id,一個古詩內容,
一個收藏標記位(用0和1來標記)
因此我對dbhelper的數據庫生成類進行了一些修改:
1 package com.lfk.poem; 2 3 import android.content.Context; 4 import android.database.sqlite.SQLiteDatabase; 5 import android.database.sqlite.SQLiteOpenHelper; 6 import android.widget.Toast; 7 8 /** 9 * Created by Administrator on 2015/5/8. 10 */ 11 public class DBhelper extends SQLiteOpenHelper { 12 private static final String CREAT_DB = "create table book (" 13 + "id integer primary key autoincrement," 14 + "collect int," 15 + "poem text)"; 16 private Context mcontext; 17 18 public DBhelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { 19 super(context, name, factory, version); 20 mcontext = context; 21 } 22 23 @Override 24 public void onCreate(SQLiteDatabase db) { 25 db.execSQL(CREAT_DB); 26 Toast.makeText(mcontext,"succeed collect!",Toast.LENGTH_SHORT).show(); 27 } 28 29 @Override 30 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 31 } 32 }
這樣生成的數據庫就能成功的應用收藏功能了,上一步所說的修改數據庫也就能實現了。
我在寫這篇博文以前曾經寫過兩次關於收藏的內容,第一次的方法比較蠢,我又開了一個用戶的數據庫,而後把要收藏的東西複製進用戶數據庫中,不過這種方法比較麻煩,
首先是開兩個數據庫增長了系統的無謂開銷,增長了對系統資源的消耗,並且在傳入新的數據庫中,id會發生變化,寫入和傳值會很是的不便利,因此我放棄了那種方法,改用
在數據庫設置標誌欄位的方法來解決問題。
1 package com.lfk.poem; 2 3 import android.app.Activity; 4 import android.content.Intent; 5 import android.database.Cursor; 6 import android.database.sqlite.SQLiteDatabase; 7 import android.os.Bundle; 8 import android.os.Environment; 9 import android.util.Log; 10 import android.view.View; 11 import android.widget.AdapterView; 12 import android.widget.ArrayAdapter; 13 import android.widget.ListView; 14 import android.widget.TextView; 15 import android.widget.Toast; 16 17 import java.io.File; 18 19 20 public class Collect extends Activity { 21 private DBhelper dBhelper; 22 private ListView listView; 23 public static ArrayAdapter<String> mArrayAdapter; 24 public static final String DB_NAME = "poem_all.db"; //保存的數據庫文件名 25 public static final String PACKAGE_NAME = "com.lfk.poem";// 應用的包名 26 public static final String DB_PATH = "/data" 27 + Environment.getDataDirectory().getAbsolutePath() +"/" 28 + PACKAGE_NAME+ "/databases"; // 在手機裏存放數據庫的位置 29 @Override 30 protected void onCreate(Bundle savedInstanceState) { 31 super.onCreate(savedInstanceState); 32 setContentView(R.layout.activity_collect); 33 String[] data = new String[0]; 34 //dBhelper = new DBhelper(this,"poem_all.db",null,1); 35 listView = (ListView)findViewById(R.id.list_view); 36 mArrayAdapter = new ArrayAdapter<String>(this,R.layout.list_item); 37 listView.setAdapter(mArrayAdapter); 38 FindyourCollect(); 39 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 40 @Override 41 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, 42 long arg3) { 43 System.out.println(arg2); 44 String temp = (String)((TextView)arg1).getText(); 45 Intent intent = new Intent(); 46 intent.putExtra("title",temp); 47 System.out.println(arg2); 48 intent.setClass(Collect.this, Collect_item.class); 49 startActivity(intent); 50 Toast.makeText(getApplicationContext(), 51 "Opening " + arg2, 52 Toast.LENGTH_SHORT).show(); 53 mArrayAdapter.notifyDataSetChanged(); 54 } 55 }); 56 } 57 58 59 // @Override 60 // public boolean onCreateOptionsMenu(Menu menu) { 61 // // Inflate the menu; this adds items to the action bar if it is present. 62 // getMenuInflater().inflate(R.menu.menu_collect, menu); 63 // return true; 64 // } 65 // 66 // @Override 67 // public boolean onOptionsItemSelected(MenuItem item) { 68 // // Handle action bar item clicks here. The action bar will 69 // // automatically handle clicks on the Home/Up button, so long 70 // // as you specify a parent activity in AndroidManifest.xml. 71 // int id = item.getItemId(); 72 // 73 // //noinspection SimplifiableIfStatement 74 // if (id == R.id.action_settings) { 75 // return true; 76 // } 77 // 78 // return super.onOptionsItemSelected(item); 79 // } 80 void FindyourCollect(){ 81 File myDataPath = new File(DB_PATH); 82 String dbfile = myDataPath+"/"+DB_NAME; 83 SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(dbfile, null); 84 Cursor cursor = database.rawQuery("Select * From poem where ticai = 1", null); 85 Log.e("===================", "================"); 86 if(cursor.moveToFirst()) { 87 Log.e("===================", "================"); 88 do { 89 String title = cursor.getString(cursor.getColumnIndex("mingcheng")); 90 mArrayAdapter.add(title); 91 Log.e(title, "================"); 92 }while (cursor.moveToNext()); 93 } 94 cursor.close(); 95 database.close(); 96 } 97 @Override 98 protected void onRestart(){ 99 super.onRestart(); 100 mArrayAdapter.clear(); 101 FindyourCollect(); 102 mArrayAdapter.notifyDataSetChanged(); 103 } 104 }
這是Collect的活動的代碼,代碼中用了一個系統自帶的簡易的listview(主要是也不須要太多的功能),進入以後運行FindyourCollect()方法用Select * From poem where ticai = 1語法,
尋找標誌位,而後把全部找到的東西加入listview中去,而後設置item的響應打開。
1 package com.lfk.poem; 2 3 import android.app.Activity; 4 import android.content.Intent; 5 import android.database.Cursor; 6 import android.database.sqlite.SQLiteDatabase; 7 import android.graphics.Typeface; 8 import android.os.Bundle; 9 import android.util.Log; 10 import android.view.Menu; 11 import android.view.MenuItem; 12 import android.widget.TextView; 13 import android.widget.Toast; 14 15 16 public class Collect_item extends Activity { 17 private DBhelper dBhelper; 18 private String ID; 19 @Override 20 protected void onCreate(Bundle savedInstanceState) { 21 super.onCreate(savedInstanceState); 22 setContentView(R.layout.activity_collect_item); 23 Intent intent = getIntent(); 24 String title = intent.getStringExtra("title"); 25 //System.out.println(id+"================="); 26 TextView textView = (TextView)findViewById(R.id.poem_item); 27 Typeface typeface = Typeface.createFromAsset(getAssets(),"fonts/font_ksj.ttf"); 28 textView.setTypeface(typeface); 29 dBhelper = new DBhelper(this,"poem_all.db",null,1); 30 SQLiteDatabase database = dBhelper.getWritableDatabase(); 31 Cursor cursor = database.rawQuery("Select * From poem where mingcheng="+"\""+title+"\"", null); 32 cursor.moveToFirst(); 33 ID = cursor.getString(cursor.getColumnIndex("_id")); 34 String poem = cursor.getString(1)+"\n"+"\n"+cursor.getString(2)+"\n"+"\n"+cursor.getString(13); 35 textView.setText(poem); 36 Log.e("===================", "================"); 37 cursor.close(); 38 database.close(); 39 } 40 41 @Override 42 public boolean onCreateOptionsMenu(Menu menu) { 43 // Inflate the menu; this adds items to the action bar if it is present. 44 getMenuInflater().inflate(R.menu.menu_collect_item, menu); 45 return true; 46 } 47 48 @Override 49 public boolean onOptionsItemSelected(MenuItem item) { 50 // Handle action bar item clicks here. The action bar will 51 // automatically handle clicks on the Home/Up button, so long 52 // as you specify a parent activity in AndroidManifest.xml. 53 int id = item.getItemId(); 54 55 if(id == R.id.dislike_collect){ 56 SQLiteDatabase db = dBhelper.getWritableDatabase(); 57 db.execSQL("UPDATE poem SET ticai = 0 WHERE _id ="+ID); 58 db.close(); 59 Toast.makeText(getApplicationContext(), 60 "Collect Delete", 61 Toast.LENGTH_SHORT).show(); 62 } 63 64 return super.onOptionsItemSelected(item); 65 } 66 67 }
打開後的方法比較簡單和主活動基本同樣,接受傳入的題目,而後根據題目找到咱們須要的詩,設置字體而後textview中顯示出來。
而後就是加入收藏了,爲了方便,我把加入收藏寫進了meau中以方便使用:
1 void AddaPoemToCollect(){ 2 //File myDataPath = new File(DB_PATH); 3 //String dbfile = myDataPath+"/"+DB_USER_NAME; 4 SQLiteDatabase db = openDatabase(); 5 //ContentValues contentValues = new ContentValues(); 6 db.execSQL("UPDATE poem SET ticai = 1 WHERE _id ="+ID); 7 //db.insert("book", null, contentValues); 8 db.close(); 9 Toast.makeText(getApplicationContext(), 10 "Collect succeed", 11 Toast.LENGTH_SHORT).show(); 12 //ID++; 13 } 14 void deleteAPoemFromCollect(){ 15 SQLiteDatabase db = openDatabase(); 16 17 db.execSQL("UPDATE poem SET ticai = 0 WHERE _id ="+ID); 18 19 db.close(); 20 21 Toast.makeText(getApplicationContext(), 22 "Collect Delete", 23 Toast.LENGTH_SHORT).show(); 24 }
這個就是加入收藏和刪除收藏的方法所在了,我在主活動和收藏的內容活動中都爲meau添加了這個方法,而且設置了一個全局變量ID用於刪除和加入收藏的時候尋址。
到此爲止咱們初期的功能就都開發完了,放出新的界面,圖片仍是暫時借用了別人的成例,我已經找UI幫我作更好看的界面了:
好了這一篇就說這麼多吧,應該還會有一些新的有意思的功能要嘗試,因此應該還會有後續吧!
麼麼噠,喜歡就點贊吧!!!