通过软件开发的实践训练,使学生进一步掌握软件工程的方法和技术,提高软件开发的实际能力,培养工程设计能力和综合分析、解决问题的能力。
具体如下:
学习和实践在分析和设计计算机应用系统所需要的知识,包括面向对象的系统分析与设计,编码和测试方面的知识;熟悉自动化的软件开发工具 AndroidStudio3,并将其运用于软件开发的全过程;进一步加强和提高软件工程文档的编写能力;
随着网络信息的发展,网络在人们生活中的应用越来越广泛。人们分享自己的生活。但生活的任务繁重,人们在繁忙的工作生活中分享花的生活带来了很大的麻烦,该“花艺”应用 App,提供给喜爱花植物的用户一个分享平台,用户可以分享自己的插花作品,分享自己精美的图片内容。
“花艺”应用 App,提供给喜爱花植物的用户一个分享平台,用户可以分享自己的插花作品,分享自己精美的图片内容。同时该平台还是提供给用户分享好看的花签小卡片,卡片里记录可以记录日常或者记录记录学习内容以及花艺作品心得,打造一个花类植物的知识信息以及花艺共享平台。同时使用了隐式意图调用手机相机和相册,以及基本逻辑功能实现。
a) 操作系统: Windows10
b) 使用软件:
代码编写:AndroidStudio3
数据库:MySQL
文档编写:Microsoft Word 2007.
c) 开发语言:Java
花艺 App 是一款手机应用软件,提供服务主要为:花艺学堂,每日推出原创插花,为花艺爱好者提供美学指导;原创精美壁纸,每日更新,自动匹配适应手机屏幕;花艺研究社,为爱花人事和从业者提供系统的花艺教程。较为灵活的文章管理功能。
根据应用的具体情况,系统的主要功能包括:
用户功能 :
功能:登录、退出、个人管理
花签日历卡:浏览花钱内容和管理
个人花签管理:查看花签、修改花签、删除花签,增加花签
知乎新闻:热点专题和其他专题
管理员功能:
登录、退出、个人管理
花签管理:查看花签、修改花签、删除花签,增加花签
知乎新闻:热点专题和其他专题
管理者用例:
1.登录:管理员登录。
图表 a.1 管理者登录用例图
图表 1 管理员管理花签
客户用例图
1.登录:用户登录。
图表 b.1 客户登录用例图
图表 2 用户管理花签
系统模块图:
具体代码已打包
登录界面、
李宁宁.《基于 Android Studio 的应用程序开发教程》
郭霖. 《第一行代码》
package com.example.liuyi;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Menu;
import android.widget.ImageView;
import android.widget.Toast;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.navigation.NavigationView;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import org.xutils.common.Callback;
import org.xutils.http.RequestParams;
import org.xutils.x;
import java.util.HashMap;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private AppBarConfiguration mAppBarConfiguration;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_gallery, R.id.nav_home, R.id.nav_slideshow,R.id.nav_share)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
}
// private void getPirture(final String result, View view) {
// final ImageView imageView = view.findViewById(R.id.imageView);
//
// imageView.setOnClickListener(new View.OnClickListener() {
// @Override
// public void onClick(View v) {
// Glide.with(MainActivity.this).load(result)
// .fitCenter()
// .centerCrop()//会裁减图片填充布局
// .diskCacheStrategy(DiskCacheStrategy.ALL)
// .placeholder(R.drawable.hua_daisy).into(imageView);
// }
// });
//
//
// }
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onSupportNavigateUp() {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.navigateUp(navController, mAppBarConfiguration)
|| super.onSupportNavigateUp();
}
}
package com.example.liuyi;
import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import com.example.liuyi.ui.footerView.BaseFooterView;
import com.example.liuyi.ui.footerView.SimpleFooterView;
/**
* @auther deadline
* @time 2016/10/22
* SwipeRefreshLayout + recyclerView
*/
public class SwipeRecyclerView extends FrameLayout
implements SwipeRefreshLayout.OnRefreshListener{
private View mEmptyView;
private BaseFooterView mFootView;
private RecyclerView recyclerView;
private SwipeRefreshLayout mRefreshLayout;
private RecyclerView.LayoutManager mLayoutManager;
private OnLoadListener mListener;
private GridLayoutManager.SpanSizeLookup mSpanSizeLookup;
private DataObserver mDataObserver;
private WrapperAdapter mWrapperAdapter;
private boolean isEmptyViewShowing;
private boolean isLoadingMore;
private boolean isLoadMoreEnable;
private boolean isRefreshEnable;
private int lastVisiablePosition = 0;
public SwipeRecyclerView(Context context) {
this(context, null);
}
public SwipeRecyclerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public SwipeRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setupSwipeRecyclerView();
}
private void setupSwipeRecyclerView() {
isEmptyViewShowing = false;
isRefreshEnable = true;
isLoadingMore = false;
isLoadMoreEnable = true;
mFootView = new SimpleFooterView(getContext());
View view = LayoutInflater.from(getContext()).inflate(R.layout.layout_swipe_recyclerview, this);
mRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.SwipeRefreshLayout);
recyclerView = (RecyclerView) view.findViewById(R.id.RecyclerView);
mLayoutManager = recyclerView.getLayoutManager();
mRefreshLayout.setOnRefreshListener(this);
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// do nothing if load more is not enable or refreshing or loading more
if(!isLoadMoreEnable || isRefreshing() || isLoadingMore){
return;
}
//get the lastVisiablePosition
mLayoutManager = recyclerView.getLayoutManager();
if(mLayoutManager instanceof LinearLayoutManager){
lastVisiablePosition = ((LinearLayoutManager)mLayoutManager).findLastVisibleItemPosition();
}else if(mLayoutManager instanceof GridLayoutManager){
lastVisiablePosition = ((GridLayoutManager)mLayoutManager).findLastCompletelyVisibleItemPosition();
}else if(mLayoutManager instanceof StaggeredGridLayoutManager){
int[] into = new int[((StaggeredGridLayoutManager) mLayoutManager).getSpanCount()];
((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(into);
lastVisiablePosition = findMax(into);
}
int childCount = mWrapperAdapter == null ? 0 : mWrapperAdapter.getItemCount();
if(childCount > 1 && lastVisiablePosition == childCount - 1){
if(mListener != null){
isLoadingMore = true;
mListener.onLoadMore();
}
}
}
});
}
private int findMax(int[] lastPositions) {
int max = lastPositions[0];
for (int value : lastPositions) {
if (value > max) {
max = value;
}
}
return max;
}
/**
* set is enable pull to refresh
* @param refreshEnable
*/
public void setRefreshEnable(boolean refreshEnable){
isRefreshEnable = refreshEnable;
mRefreshLayout.setEnabled(isRefreshEnable);
}
public boolean getRefreshEnable(){
return isRefreshEnable;
}
/**
* set is loading more enable
* @param loadMoreEnable
* if true when recyclerView scroll to bottom load more action will be trigger
*/
public void setLoadMoreEnable(boolean loadMoreEnable) {
if(!loadMoreEnable){
stopLoadingMore();
}
isLoadMoreEnable = loadMoreEnable;
}
public boolean getLoadMoreEnable(){
return isLoadMoreEnable;
}
/**
* get is refreshing
* @return
*/
public boolean isRefreshing(){
return mRefreshLayout.isRefreshing();
}
/**
* get is loading more
* @return
*/
public boolean isLoadingMore(){
return isLoadingMore;
}
/**
* is empty view showing
* @return
*/
public boolean isEmptyViewShowing(){
return isEmptyViewShowing;
}
/**
* you may need set some other attributes of swipeRefreshLayout
* @return
* swipeRefreshLayout
*/
public SwipeRefreshLayout getSwipeRefreshLayout(){
return mRefreshLayout;
}
/**
* you may need set some other attributes of RecyclerView
* @return
* RecyclerView
*/
public RecyclerView getRecyclerView(){
return recyclerView;
}
/**
* set load more listener
* @param listener
*/
public void setOnLoadListener(OnLoadListener listener){
mListener = listener;
}
/**
* support for GridLayoutManager
* @param spanSizeLookup
*/
public void setSpanSizeLookup(GridLayoutManager.SpanSizeLookup spanSizeLookup){
this.mSpanSizeLookup = spanSizeLookup;
}
/**
* set the footer view
* @param footerView
* the view to be showing when pull up
*/
public void setFooterView(BaseFooterView footerView){
if(footerView != null) {
this.mFootView = footerView;
}
}
/**
* set a empty view like listview
* @param emptyView
* the view to be showing when the data set size is zero
*/
public void setEmptyView(View emptyView){
if(mEmptyView != null){
removeView(mEmptyView);
}
this.mEmptyView = emptyView;
if(mDataObserver != null) {
mDataObserver.onChanged();
}
}
/**
* set adapter to recyclerView
* @param adapter
*/
public void setAdapter(RecyclerView.Adapter adapter){
if(adapter != null) {
if(mDataObserver == null){
mDataObserver = new DataObserver();
}
mWrapperAdapter = new WrapperAdapter(adapter);
recyclerView.setAdapter(mWrapperAdapter);
adapter.registerAdapterDataObserver(mDataObserver);
mDataObserver.onChanged();
}
}
/**
* refresh or load more completed
*/
public void complete(){
mRefreshLayout.setRefreshing(false);
stopLoadingMore();
}
/**
* set refreshing
* if you want load data when first in, you can setRefreshing(true)
* after {@link #setOnLoadListener(OnLoadListener)}
* @param refreshing
*/
public void setRefreshing(boolean refreshing){
mRefreshLayout.setRefreshing(refreshing);
if(refreshing && !isLoadingMore && mListener != null){
mListener.onRefresh();
}
}
/**
* stop loading more without animation
*/
public void stopLoadingMore(){
isLoadingMore = false;
if(mWrapperAdapter != null) {
mWrapperAdapter.notifyItemRemoved(mWrapperAdapter.getItemCount());
}
}
/**
* call method {@link OnLoadListener#onRefresh()}
*/
@Override
public void onRefresh() {
if(mListener != null){
//reset footer view status loading
if(mFootView != null){
mFootView.onLoadingMore();
}
mListener.onRefresh();
}
}
public void onNetChange(boolean isAvailable) {
if(mFootView != null){
mFootView.onNetChange(isAvailable);
}
}
public void onLoadingMore() {
if(mFootView != null){
mFootView.onLoadingMore();
}
}
public void onNoMore(CharSequence message) {
if(mFootView != null){
mFootView.onNoMore(message);
}
}
public void onError(CharSequence message) {
if(mFootView != null){
mFootView.onError(message);
}
}
private class WrapperAdapter extends RecyclerView.Adapter{
public static final int TYPE_FOOTER = 0x100;
RecyclerView.Adapter mInnerAdapter;
public WrapperAdapter(RecyclerView.Adapter adapter){
this.mInnerAdapter = adapter;
}
public boolean isLoadMoreItem(int position){
return isLoadMoreEnable && position == getItemCount() - 1;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(TYPE_FOOTER == viewType){
return new FooterViewHolder(mFootView);
}
return mInnerAdapter.onCreateViewHolder(parent, viewType);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if(isLoadMoreItem(position)){
return;
}
mInnerAdapter.onBindViewHolder(holder, position);
}
@Override
public int getItemViewType(int position) {
if(isLoadMoreItem(position)){
return TYPE_FOOTER;
}else{
return mInnerAdapter.getItemViewType(position);
}
}
@Override
public int getItemCount() {
int count = mInnerAdapter == null ? 0 : mInnerAdapter.getItemCount();
//without loadingMore when adapter size is zero
if(count == 0){
return 0;
}
return isLoadMoreEnable ? count + 1 : count;
}
@Override
public long getItemId(int position) {
return mInnerAdapter.getItemId(position);
}
@Override
public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) {
ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
if (lp != null
&& lp instanceof StaggeredGridLayoutManager.LayoutParams
&& isLoadMoreItem(holder.getLayoutPosition()))
{
StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp;
p.setFullSpan(true);
}
mInnerAdapter.onViewAttachedToWindow(holder);
}
@Override
public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) {
mInnerAdapter.onViewDetachedFromWindow(holder);
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
if (manager instanceof GridLayoutManager) {
final GridLayoutManager gridManager = ((GridLayoutManager) manager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
boolean isLoadMore = isLoadMoreItem(position);
if(mSpanSizeLookup != null && !isLoadMore){
return mSpanSizeLookup.getSpanSize(position);
}
return isLoadMore ? gridManager.getSpanCount() : 1;
}
});
}
mInnerAdapter.onAttachedToRecyclerView(recyclerView);
}
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
mInnerAdapter.onDetachedFromRecyclerView(recyclerView);
}
@Override
public boolean onFailedToRecycleView(RecyclerView.ViewHolder holder) {
return mInnerAdapter.onFailedToRecycleView(holder);
}
@Override
public void registerAdapterDataObserver(RecyclerView.AdapterDataObserver observer) {
mInnerAdapter.registerAdapterDataObserver(observer);
}
@Override
public void unregisterAdapterDataObserver(RecyclerView.AdapterDataObserver observer) {
mInnerAdapter.unregisterAdapterDataObserver(observer);
}
@Override
public void onViewRecycled(RecyclerView.ViewHolder holder) {
mInnerAdapter.onViewRecycled(holder);
}
}
/**
* ViewHolder of footerView
*/
private class FooterViewHolder extends RecyclerView.ViewHolder {
public FooterViewHolder(View itemView) {
super(itemView);
}
}
/**
* a inner class used to monitor the dataSet change
*
* because wrapperAdapter do not know when wrapperAdapter.mInnerAdapter
*
* dataSet changed, these method are final
*/
class DataObserver extends RecyclerView.AdapterDataObserver{
@Override
public void onChanged() {
super.onChanged();
RecyclerView.Adapter adapter = recyclerView.getAdapter();
if(adapter != null && mEmptyView != null){
int count = 0;
if(isLoadMoreEnable && adapter.getItemCount() != 0){
count ++;
}
if(adapter.getItemCount() == count){
isEmptyViewShowing = true;
if(mEmptyView.getParent() == null){
LayoutParams params = new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER;
addView(mEmptyView, params);
}
recyclerView.setVisibility(GONE);
mEmptyView.setVisibility(VISIBLE);
}else{
isEmptyViewShowing = false;
mEmptyView.setVisibility(GONE);
recyclerView.setVisibility(VISIBLE);
}
}
mWrapperAdapter.notifyDataSetChanged();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
super.onItemRangeChanged(positionStart, itemCount);
mWrapperAdapter.notifyItemRangeChanged(positionStart, itemCount);
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
super.onItemRangeChanged(positionStart, itemCount, payload);
mWrapperAdapter.notifyItemRangeChanged(positionStart, itemCount, payload);
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
mWrapperAdapter.notifyItemRangeInserted(positionStart, itemCount);
}
@Override
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
super.onItemRangeMoved(fromPosition, toPosition, itemCount);
mWrapperAdapter.notifyItemRangeRemoved(fromPosition, itemCount);
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
super.onItemRangeRemoved(positionStart, itemCount);
mWrapperAdapter.notifyItemRangeRemoved(positionStart, itemCount);
}
}
public interface OnLoadListener {
void onRefresh();
void onLoadMore();
}
}
大小: 15.9MB
➡️ 资源下载:https://download.csdn.net/download/s1t16/87404181