目錄
一、測試環境說明
二、項目簡介
三、項目演示
四、部設計詳情(部分)
登錄頁
首頁
五、項目源碼?
一、測試環境說明
電腦環境
Windows 11
編寫語言
JAVA
開發軟件
Android Studio ?(2020)
開發軟件只要大于等于測試版本即可(近幾年官網直接下載也可以),若是版本低于測試版本請自行測試。項目需要根據你的軟件自行適配
二、項目簡介
該項目簡介來自網絡,具體內容需要自行測試
該項目使用Android Studio軟件Java語言SQLite數據庫完成開發的新聞App,主要功能包括新聞列表展示、分類搜索、新聞詳情查看以及本地記錄存儲。
App采用了SQLite數據庫實現瀏覽記錄和收藏功能的本地存儲,界面方面使用了RecyclerView、ViewPager、TabLayout等控件實現流暢的交互體驗。
并通過Retrofit框架處理網絡請求和JSON數據解析。額外實現了登錄注冊頁面和自定義字體等增強用戶體驗的功能。
該項目由編程樂學團隊介入,優化布局完善功能
三、項目演示
網絡資源模板--基于Android studio 新聞App
四、部設計詳情(部分)
登錄頁
1. 頁面的結構
該登錄頁面采用垂直線性布局,整體結構清晰簡潔。頂部顯示"華清聞新"藝術字標題,中間是半透明背景的登錄表單區,包含用戶名輸入框、密碼輸入框、登錄按鈕和注冊按鈕。
底部顯示版權信息。所有元素居中排列,背景使用圖片填充,整體設計注重視覺層次和用戶體驗,通過合理的邊距和間距營造舒適的視覺效果,色彩搭配以白色和藍色為主,保持界面清爽美觀。
2. 使用到的技術
該頁面運用了多種Android開發技術:通過SQLite數據庫實現用戶信息存儲和驗證功能;使用Intent實現頁面跳轉至注冊和歡迎頁面;
采用Typeface自定義藝術字體增強視覺效果;通過Toast提示用戶操作反饋;利用EditText和Button等基礎控件構建交互界面。
布局方面采用透明度設置和背景色調營造現代感界面,同時通過elevation屬性添加陰影效果提升立體感。
3. 頁面詳細介紹
這是一個標準的移動端登錄頁面,主要功能包括用戶身份驗證和注冊跳轉。頁面啟動時隱藏ActionBar以獲得更大顯示空間。
用戶輸入用戶名密碼后,系統會查詢數據庫進行驗證,成功則跳轉至歡迎頁,失敗則提示錯誤。
注冊按鈕可跳轉至注冊頁面。界面設計上注重用戶體驗,輸入框有明確提示文字,密碼字段自動隱藏,按鈕有明確的視覺反饋。
整體風格簡約現代,半透明元素和精心選擇的配色方案使界面既美觀又不失功能性。
/*建立登錄頁面*/
package com.example.news.signup;import androidx.appcompat.app.AppCompatActivity;import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.database.sqlite.SQLiteDatabase;
import android.widget.Button;
import android.widget.EditText;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
import android.graphics.Typeface;import com.example.news.R;public class LogIn extends AppCompatActivity {private EditText inf,passwd;private Button loginbtn,regbtn;private MyDatabaseHelper myDatabaseHelper;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login);//隱藏 ActionBargetSupportActionBar().hide();/*建立用戶名輸入框*/inf=(EditText) findViewById(R.id.name);/*建立密碼輸入框*/passwd=(EditText) findViewById(R.id.pwd);/*建立登錄按鈕*/loginbtn=(Button) findViewById(R.id.login);/*建立注冊按鈕*/regbtn=(Button) findViewById(R.id.reg);/*啟動數據庫*/myDatabaseHelper =new MyDatabaseHelper(this,"UserDB.db",null,1);/*按動注冊鍵*/regbtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {registerClicked(view);}});loginbtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {String username=inf.getText().toString();String userpassword=passwd.getText().toString();SQLiteDatabase db= myDatabaseHelper.getWritableDatabase();Cursor cursor = db.rawQuery("select * from User where name=?", new String[]{username});if (cursor.getCount() == 0) {Toast.makeText(LogIn.this, "用戶名不存在!", Toast.LENGTH_SHORT).show();} else {if (cursor.moveToFirst()) {String userpassword_db = cursor.getString(cursor.getColumnIndexOrThrow("password"));if (userpassword.equals(userpassword_db)) {Toast.makeText(LogIn.this,"登錄成功",Toast.LENGTH_SHORT).show();Intent intent = new Intent(LogIn.this, Welcome.class);startActivity(intent);finish();} else {Toast.makeText(LogIn.this, "密碼錯誤,請重新登錄", Toast.LENGTH_SHORT).show();}}}cursor.close();db.close();}});/*設定藝術字*/TextView title=findViewById(R.id.tit);TextView ps1=findViewById(R.id.ps);Typeface typeface = Typeface.createFromAsset(getAssets(), "character.ttf");title.setTypeface(typeface);ps1.setTypeface(typeface);}public void registerClicked(View view){Intent intent=new Intent(LogIn.this, Register.class);startActivity(intent);}
}
首頁
1. 頁面結構
該頁面采用CoordinatorLayout作為根布局,整體分為頂部標題欄和內容區域兩部分。頂部標題欄包含搜索按鈕、分類選擇區域和滑動標簽欄,采用藍色背景和白色文字形成鮮明對比。
內容區域使用ViewPager承載不同分類的新聞片段,實現左右滑動切換。頁面結構層次分明,頂部固定導航區與下方可滑動內容區相結合,既保證了功能完整性,又確保了操作便捷性。色彩搭配以藍白為主,符合新聞類應用的簡潔風格。
2. 使用技術
該頁面運用了多種高級技術:通過SlidingTabLayout實現可滑動的分類標簽欄;
使用ViewPager配合FragmentPagerAdapter管理多個新聞分類頁面;采用Fragment間通信機制實現分類數據的傳遞和更新;
利用CoordinatorLayout協調滾動行為;通過自定義FixedPager解決滑動沖突問題。界面交互方面實現了點擊下拉選擇分類、搜索跳轉等功能,整體技術方案既保證了性能又提供了流暢的用戶體驗。
3. 功能詳解
這是一個新聞應用首頁,核心功能包括新聞分類展示和內容瀏覽。頂部搜索框可跳轉至搜索頁面,右側按鈕展開分類選擇彈窗。
滑動標簽欄展示當前選中的新聞分類,左右滑動可切換不同分類內容。
頁面采用懶加載優化性能,通過setOffscreenPageLimit控制預加載數量。分類管理功能允許用戶自定義顯示的分類和順序,變更后會實時更新界面。
整體設計注重實用性和交互體驗,色彩和布局符合Material Design規范,操作反饋及時明確。
package com.example.news.Fragment;import android.content.Intent;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.fragment.app.FragmentTransaction;
import androidx.viewpager.widget.ViewPager;import com.flyco.tablayout.SlidingTabLayout;
import com.example.news.R;
import com.example.news.SearchActivity;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;public class HomeFragment extends Fragment implements CategoriesFragment.DL{private ArrayList<Fragment> fragments = new ArrayList<>();private List<String> myup=new ArrayList<>();private List<String> mydown=new ArrayList<>();private ViewPager viewPager;private SlidingTabLayout slidingTabLayout;private ImageButton imageButton;private Button search;private MyPagerAdapter myPagerAdapter;@Overridepublic void DC(List<String> TitlesOn, List<String> TitlesOff) {FragmentTransaction ft = getChildFragmentManager().beginTransaction();for (int i=0;i<fragments.size();i++) {ft.remove(fragments.get(i));}ft.commitNow();fragments.clear();for(int i=0;i<myup.size();i++){fragments.add(NewsFragment.newInstance(myup.get(i)));}viewPager.setAdapter(myPagerAdapter);slidingTabLayout.notifyDataSetChanged();slidingTabLayout.onPageSelected(0);}public static HomeFragment newInstance() {HomeFragment fragment = new HomeFragment();String[] title = {"頭條", "娛樂", "軍事", "教育", "文化","健康", "財經", "體育", "汽車", "科技", "社會"};Collections.addAll(fragment.myup,title);return fragment;}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View v = inflater.inflate(R.layout.fragment_home, container, false);initview(v);return v;}@Overridepublic void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);for(String title : myup){fragments.add(NewsFragment.newInstance(title));}viewPager.setOffscreenPageLimit(fragments.size());myPagerAdapter = new MyPagerAdapter(getChildFragmentManager());viewPager.setAdapter(myPagerAdapter);slidingTabLayout.setViewPager(viewPager);search.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Intent intent=new Intent(getActivity(), SearchActivity.class);startActivity(intent);}});imageButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {transformdata();}});}private class MyPagerAdapter extends FragmentPagerAdapter {public MyPagerAdapter(FragmentManager fm) {super(fm);}@Overridepublic int getCount() {return fragments.size();}@Overridepublic CharSequence getPageTitle(int position) {return myup.get(position);}@Overridepublic Fragment getItem(int position) {return fragments.get(position);}}public void transformdata(){CategoriesFragment mBottomCategory = CategoriesFragment.newInstance(myup,mydown);View _view = getLayoutInflater().inflate(R.layout.fragment_category, null);mBottomCategory.setDataChangeListener(HomeFragment.this);mBottomCategory.show(getActivity().getSupportFragmentManager(), "bottom_category");}public void initview(View view){viewPager = view.findViewById(R.id.vp);slidingTabLayout = view.findViewById(R.id.SlidingTabLayout);search=view.findViewById(R.id.search_btn);imageButton=view.findViewById(R.id.ib);imageButton.setImageResource(R.drawable.copy);TextView title=view.findViewById(R.id.headtitle);Typeface typeface = Typeface.createFromAsset(getContext().getAssets(), "character.ttf");title.setTypeface(typeface);}
}
五、項目源碼?
👇👇👇👇👇快捷方式👇👇👇👇👇