一、前言:
本項目主要是通過 SQLite 數據庫和 ListView 組件實現的一個關於查看新聞信息的 app,關於相關的知識,如果有不瞭解的小夥伴可以先學習一下。
二、項目流程圖:
三、項目效果圖:
1、首頁:
2、新聞信息頁:
3、信息詳情頁:
四、代碼展示:
SQLiteDBHelper.java – 加載數據庫信息
package com.example.newsqlite;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import androidx.annotation.Nullable;
/**
* A helper class to manage database creation and version management.
*
* 既然父類是一個幫助類,子類至少也是一個幫助類,而且更加強大
*
* */
public class SQLiteDBHelper extends SQLiteOpenHelper {
// 創建數據庫
static final String CREATE_SQL[] = {
"CREATE TABLE news (" +
"_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
"title varchar," +
"content varchar," +
"keyword varchar," +
"category varchar," +
"author INTEGER," +
"publish_time varchar" +
")",
"CREATE TABLE user (" +
"_id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT," +
"name varchar," +
"password varchar," +
"email varchar," +
"phone varchar," +
"address varcher" +
")",
"INSERT INTO user VALUES (1,'admin',123,'[email protected]',123,'洛陽')",
"INSERT INTO user VALUES (2,'zhangsan',123,'[email protected]',123,'北京')",
"INSERT INTO user VALUES (3,'lisi',123,'[email protected]',123,'上海')",
"INSERT INTO user VALUES (4,'wangwu',123,'[email protected]',123,'深圳')"
};
// 調用父類的構造方法(便於之後進行初始化賦值)
public SQLiteDBHelper(@Nullable Context context, @Nullable String name, int version) {
super(context, name, null, version);
}
/**
* Called when the database is created for the first time. This is where the
* creation of tables and the initial population of the tables should happen.
*
* @param db The database.
*/
@Override
public void onCreate(SQLiteDatabase db) {
// 創建數據庫
Log.i("sqlite_____", "create Database");
// 執行 SQL 語句
for (int i = 0; i < CREATE_SQL.length; i++) {
db.execSQL(CREATE_SQL[i]);
}
// 完成數據庫的創建
Log.i("sqlite_____", "Finished Database");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
SQLiteLoginActivity.java – 登錄
package com.example.newsqlite;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.example.newsqlite.R;
import com.example.newsqlite.SQLiteDBHelper;
import com.example.newsqlite.SQLiteListActivity;
/**
* 用戶登錄校驗:
* 1、登錄成功則跳轉到 SQLiteListActivity。
* 2、登錄失敗則重新登錄。
*
* */
public class SQLiteLoginActivity extends AppCompatActivity {
SQLiteDBHelper dbHelper;
EditText etUsername;
EditText etPassword;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sqlite_login);
// 創建 SQLiteDBHelper 對象,利用構造方法進行初始化賦值
dbHelper = new SQLiteDBHelper(this,"sqlite.db",1);
// 通過 id 找到 佈局管理器中的 相關屬性
etUsername = findViewById(R.id.etUsername);
etPassword = findViewById(R.id.etPassword);
}
// 當用戶點擊提交按鈕時,就會到這裏(單擊事件)
public void onClick(View view) {
// 獲取用戶的用戶名和密碼進行驗證
String username = etUsername.getText().toString();
String password = etPassword.getText().toString();
/**
* Create and/or open a database.
* */
SQLiteDatabase db = dbHelper.getReadableDatabase();
/**
*
* 查詢用戶信息,放回值是一個遊標(結果集,遍歷結果集)
*
* */
Cursor cursor = db.query("user",new String[]{"name","password"}, "name=?",new String[]{username},null,null,null,"0,1");
// 遊標移動進行校驗
if(cursor.moveToNext()) {
// 從數據庫獲取密碼進行校驗
String dbPassword = cursor.getString(cursor.getColumnIndex("password"));
// 關閉遊標
cursor.close();
if(password.equals(dbPassword)) {
// 校驗成功則跳轉到 ListViewSampleAdapterActivity
Intent intent = new Intent(this, ListViewSampleAdapterActivity.class);
// 啓動
startActivity(intent);
return;
}
}
// 跳轉失敗也要進行關閉
cursor.close();
// 跳轉失敗就提示用戶相關的錯誤信息
Toast.makeText(this,"奧利給不足,輸入信息有誤!",Toast.LENGTH_LONG).show();
}
@Override
public void onDestroy() {
super.onDestroy();
dbHelper.close();
}
}
activity_sqlite_login.xml – 登錄佈局管理器
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SQLiteLoginActivity">
<LinearLayout
android:background="@drawable/button_background"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:gravity="center_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="歡迎登錄"
android:textSize="32sp"
android:padding="10dp"
android:textColor="#fff"
/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="150dp">
<EditText
android:id="@+id/etUsername"
android:hint="用戶名/郵箱/手機號"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/edit_background"
android:padding="20dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"/>
<EditText
android:id="@+id/etPassword"
android:hint="密碼"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:background="@drawable/edit_background"
android:padding="20dp"
android:layout_margin="20dp"/>
<Button
android:textSize="18sp"
android:text="登錄"
android:textColor="#fff"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:background="@drawable/button_background"
android:padding="20dp"
android:layout_margin="20dp"/>
<RelativeLayout
android:paddingTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:text="手機快速註冊"
android:textSize="20sp"
android:layout_marginLeft="10dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:text="忘記密碼"
android:textSize="20sp"
android:layout_marginRight="10dp"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
ListViewSampleAdapterActivity.java – 新聞首頁
package com.example.newsqlite;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ListViewSampleAdapterActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview);
// 準備適配器中的數據
final List<Map<String,Object>> data = new ArrayList<>();
Map<String,Object> line1 = new HashMap<>();
line1.put("time","10月20日");
line1.put("description","我的項目用例圖");
line1.put("langIcon",R.mipmap.u33);
data.add(line1);
Map<String,Object> line2 = new HashMap<>();
line2.put("time","10月15日");
line2.put("description","難忘清秋,心靈的旅行");
line2.put("langIcon",R.mipmap.u39);
data.add(line2);
Map<String,Object> line3 = new HashMap<>();
line3.put("time","10月2日");
line3.put("description","好喫的水煮肉,美好的記憶");
line3.put("langIcon",R.mipmap.u45);
data.add(line3);
ListView listView01 = findViewById(R.id.listView01);
// 適配器,將信息放到自定義佈局管理器上上
SimpleAdapter adapter = new SimpleAdapter(
this, // 上下文
data, // 數據
R.layout.list_item_layout, // 適配器
new String[]{"time","description","langIcon"}, // 相應的屬性
new int[]{R.id.time,R.id.description,R.id.langIcon} // 佈局管理器對應的位置
);
// 放置適配器中的內容到 ListView 中
listView01.setAdapter(adapter);
// 根據點擊的信息跳轉到相應的詳情頁
final HashMap<String,Integer> map = new HashMap<>();
map.put("10月20日",0);
map.put("10月15日",1);
map.put("10月2日",2);
// 時間監聽器,當用戶點擊某條新聞時就進行相應的跳轉
listView01.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Map<String, Object> line = data.get(position);
find(map.get(line.get("time").toString())); //頁面跳轉函數參數爲模擬
}
});
}
// key 作爲每條信息的標識進行跳轉到指定的頁面
public void find(int key) {
Intent intent = new Intent(this,ContentDetailActivity.class);
Bundle bundle = new Bundle();
bundle.putInt("key",key);
intent.putExtras(bundle);
startActivity(intent);
}
}
list_item_layout.xml --適配器中的佈局管理器
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="20dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:paddingBottom="20dp">
<ImageView
android:id="@+id/langIcon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:adjustViewBounds="true"
android:src="@mipmap/ocs" />
<RelativeLayout
android:paddingTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:text="語言名字"
android:textSize="24sp" />
<ImageView
android:id="@+id/langIco"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_marginTop="0dp"
android:layout_marginRight="10dp"
android:adjustViewBounds="true"
android:src="@mipmap/u35" />
</RelativeLayout>
<TextView
android:id="@+id/description"
android:textSize="24sp"
android:text="語言介紹"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
/>
</LinearLayout>
listview.xml – 放置適配器中列表項的佈局管理器
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ListViewSampleAdapterActivity"
android:background="#fff">
<TextView
android:paddingTop="20dp"
android:text="小潘同學的獨家新聞"
android:gravity="center"
android:background="#F0B2AF"
android:textSize="30dp"
android:textColor="#000000"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ListView
android:id="@+id/listView01"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
ContentDetailActivity.java – 內容詳情頁
package com.example.newsqlite;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// 內容詳情
public class ContentDetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_content_detail);
// 獲取上一個頁面的信息
Bundle bundle = this.getIntent().getExtras();
Integer key = bundle.getInt("key");
// 根據 key 來加載新聞的詳情信息
Map<String,Object> map = load(key);
// 獲取各個組件在佈局管理器中位置,然後進行填充
ImageView langIcon = findViewById(R.id.langIcon);
TextView type = findViewById(R.id.type);
TextView mood = findViewById(R.id.mood);
TextView caption = findViewById(R.id.caption);
TextView viewById = findViewById(R.id.content);
// 將對應的組件放到特定的位置
langIcon.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), (Integer) map.get("langIcons")));
type.setText((String) map.get("types"));
mood.setText((String) map.get("moods"));
caption.setText((String) map.get("captions"));
viewById.setText((String) map.get("viewByIds"));
}
public Map<String,Object> load(int key) {
List<Map<String,Object>> data = new ArrayList<>();
Map<String,Object> line1 = new HashMap<>();
line1.put("langIcons",R.mipmap.u33);
line1.put("types","項目");
line1.put("moods","By 小潘同學");
line1.put("captions","項目用例圖");
line1.put("viewByIds"," 又過深秋,枯瘦的空氣裏總是流淌着稍許蕭瑟的味道。在這個靜謐且肆意的季節裏,我的思緒仿若這秋季光華里被吵醒的落葉,揉着惺忪的睡眼在風的紋絡裏茫然地漂浮着。\n" +
" 一首落葉的禮讚,一座城市的淪落。\n" +
" 在北方這座城市裏,如果仔細觀察,是可以看得見季節的轉換的。匆忙的路人、街角的乞討者、穿梭不停的車流、燈火輝煌的繁華夜景,它們即使佔據了城市獨有的風貌,我們也可以在擡頭的瞬間,尋找到秋天的身影:一片秋高氣爽的天空、一縷藏在城市溫暖氣流裏的清冷空氣、一街泛着枯容卻又繁花似錦的落葉,這些都像是秋天帶給我們的特色菜餚,被時光煮進了城市這口精美的大鍋裏。");
data.add(line1);
Map<String,Object> line2 = new HashMap<>();
line2.put("langIcons",R.mipmap.u39);
line2.put("types","風景");
line2.put("moods","By 小潘");
line2.put("captions","難忘清秋,心靈的旅行");
line2.put("viewByIds"," 又過深秋,枯瘦的空氣裏總是流淌着稍許蕭瑟的味道。在這個靜謐且肆意的季節裏,我的思緒仿若這秋季光華里被吵醒的落葉,揉着惺忪的睡眼在風的紋絡裏茫然地漂浮着。\n" +
" 一首落葉的禮讚,一座城市的淪落。\n" +
" 在北方這座城市裏,如果仔細觀察,是可以看得見季節的轉換的。匆忙的路人、街角的乞討者、穿梭不停的車流、燈火輝煌的繁華夜景,它們即使佔據了城市獨有的風貌,我們也可以在擡頭的瞬間,尋找到秋天的身影:一片秋高氣爽的天空、一縷藏在城市溫暖氣流裏的清冷空氣、一街泛着枯容卻又繁花似錦的落葉,這些都像是秋天帶給我們的特色菜餚,被時光煮進了城市這口精美的大鍋裏。");
data.add(line2);
Map<String,Object> line3 = new HashMap<>();
line3.put("langIcons",R.mipmap.u45);
line3.put("types","美食");
line3.put("moods","By 小潘同學");
line3.put("captions","好喫的水煮肉,美好的記憶");
line3.put("viewByIds"," 又過深秋,枯瘦的空氣裏總是流淌着稍許蕭瑟的味道。在這個靜謐且肆意的季節裏,我的思緒仿若這秋季光華里被吵醒的落葉,揉着惺忪的睡眼在風的紋絡裏茫然地漂浮着。\n" +
" 一首落葉的禮讚,一座城市的淪落。\n" +
" 在北方這座城市裏,如果仔細觀察,是可以看得見季節的轉換的。匆忙的路人、街角的乞討者、穿梭不停的車流、燈火輝煌的繁華夜景,它們即使佔據了城市獨有的風貌,我們也可以在擡頭的瞬間,尋找到秋天的身影:一片秋高氣爽的天空、一縷藏在城市溫暖氣流裏的清冷空氣、一街泛着枯容卻又繁花似錦的落葉,這些都像是秋天帶給我們的特色菜餚,被時光煮進了城市這口精美的大鍋裏。");
data.add(line3);
// 將相應的信息進行傳遞
Map<String,Object> map = data.get(key);
return map;
}
}
activity_content_detail.xml – 內容詳情頁對應的佈局管理器
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".ContentDetailActivity"
android:scrollbars="none"
android:background="#fff"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="@+id/langIcon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@mipmap/ocs" />
<RelativeLayout
android:paddingTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:paddingRight="10dp">
<TextView
android:id="@+id/type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:text="風景"
android:textSize="24sp" />
<TextView
android:id="@+id/mood"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:textColor="#000000"
android:text="By 小潘同學"
android:textSize="24sp" />
</RelativeLayout>
<TextView
android:id="@+id/caption"
android:paddingTop="20dp"
android:text="難忘今秋"
android:gravity="center"
android:textSize="25dp"
android:textStyle="bold"
android:textColor="#000000"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/content"
android:padding="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#504B50"
android:singleLine = "false"
android:textScaleX="1.2"
android:lineSpacingExtra="5dp"
android:text="又過深秋,枯瘦的空氣裏總是流淌着稍許蕭瑟的味道。在這個靜謐且肆意的季節裏,我的思緒仿若這秋季光華里被吵醒的落葉,揉着惺忪的睡眼在風的紋絡裏茫然地漂浮着。
一首落葉的禮讚,一座城市的淪落。
在北方這座城市裏,如果仔細觀察,是可以看得見季節的轉換的。匆忙的路人、街角的乞討者、穿梭不停的車流、燈火輝煌的繁華夜景,它們即使佔據了城市獨有的風貌,我們也可以在擡頭的瞬間,尋找到秋天的身影:一片秋高氣爽的天空、一縷藏在城市溫暖氣流裏的清冷空氣、一街泛着枯容卻又繁花似錦的落葉,這些都像是秋天帶給我們的特色菜餚,被時光煮進了城市這口精美的大鍋裏。"
android:textSize="18sp" />
</LinearLayout>
</ScrollView>
五、後記:
到此,一個簡單的新聞APP就完成了,其中也還存在一些不足的地方 ,如果路過的小夥伴有疑問,或者上面的代碼不夠清晰,歡迎到評論區留言或者私信我,
創作不易,如果對您有幫助,可以點個贊,點個關注哦,感謝感謝!