手记

℃江让您从精通到入门:写诗APP的制作流程详解

一款类备忘录形式的记事本:写诗APP。


首先看一下目录结构如下:

演示效果如图如下:


做这个APP的目的完全是为了练手,目前也已经在线上跑着,最近也没时间优化,可是在这个过程中,我发现,实现的效果还不错。所以就接着做了。下面进行分步讲解:
源码地址:
链接:http://pan.baidu.com/s/1mipzdm4 密码:49d1

  • 1、首先用到一定要用到Android Studio,当然了,做这个小案例,你不需要导入任何的包,你只需要知道,Android Studio导包方式与ADT不同就好了。
  • 2、Android用到的是自己的数据库,叫做SQLite,总结下来,简单,好用,高效。
  • 3、当然了,在做这个项目之前,你先要知道自己在做什么,那就是数据库的增删改查,写诗嘛!顾名思义,你要有Title,有Content,id主要是为了在做删除和修改时有区分,在这里一定要注意一下。所以你要写一个实体类在vo目录下:“Poem”类中的代码如下:
package com.example.mypoem.vo;

/**
 * Created by Dujiang0311 on 2017/1/9.
 */

public class Poem {
    private int id;
    private String title;
    private String content;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}
  • 4、实体类写好了,就是数据库的工具类的书写了,在这里你要完成建表,以及新增数据列的操作,“SQLIiteHelper”具体实现代码如下:
package com.example.mypoem.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * Created by Dujiang0311 on 2017/2/9.
 */

public class SQLiteHelper extends SQLiteOpenHelper {

    /*SQLiteHelper的四个参数,上下文,数据库名字,null,版本号(任意数字)*/
    public SQLiteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    /*上面那个太过复杂,所以需要重载一个简单的方法:通过构造方法,完成数据库的创建*/
    public SQLiteHelper(Context context){
        super(context,"mydb",null,1);
    }
    //当sqliteOpenHelper中新添加了execSQL语句的时候一定要注意,将之前已经运行的MyWealth进行卸载
    /*通过OnCreate方法,实现数据表的创建*/
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table poem (id integer primary key autoincrement,title varchar2(20),content varchar2(50))");
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

    }
}
  • 5、接下来数据的操作类了,也就是所谓的dao层,里面包含了对于数据库的增删改查。“FileDao”代码如下:
package com.example.mypoem.dao;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.example.mypoem.sqlite.SQLiteHelper;
import com.example.mypoem.vo.Poem;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Dujiang0311 on 2017/2/9.
 */

public class FileDao {
    private SQLiteHelper sqLiteHelper;

    private SQLiteDatabase db;

    public FileDao(Context context) {
        sqLiteHelper = new SQLiteHelper(context);

    }

    //新增我的诗篇删除功能
    public int poemDelete(Integer id) {
        db = sqLiteHelper.getWritableDatabase();
        return db.delete("poem", "id = ?", new String[]{String.valueOf(id)});
    }
    //新增我的诗篇修改功能
    public int poemUpdate(int id, String title, String content) {
        db = sqLiteHelper.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("id",id);
        cv.put("title", title);
        cv.put("content", content);
        return db.update("poem", cv, "id = ?", new String[]{String.valueOf(id)});
    }

    //新增我的诗篇查询功能
    public List<Poem> myPoems() {
        List<Poem> list = new ArrayList<Poem>();
        db = sqLiteHelper.getReadableDatabase();
        Cursor cursor = db.query("poem", new String[]{"id","title", "content"}, null, null, null, null, null);
        while (cursor.moveToNext()) {
            Poem poem = new Poem();
            poem.setId(cursor.getInt(0));
            poem.setTitle(cursor.getString(1));
            poem.setContent(cursor.getString(2));
            list.add(poem);
        }
        return list;
    }
    //新增我的诗篇新增功能
    public Long addPoem(Poem poem){
        /*由于当前需要实现的是添加功能,所以我们需要调用getWritableDatabase()*/
        db = sqLiteHelper.getWritableDatabase();
        /*创建ContentValues对象*/
        ContentValues cv = new ContentValues();
        cv.put("title", poem.getTitle());
        cv.put("content",poem.getContent());
        return db.insert("poem",null,cv);
    }
}
  • 6、当然,有的人代码潦草,随便把它写在该用的地方,也是没问题的,不过小项目还好,大项目还是规矩点的好。
  • 7、接下来就是UI的实现了,MainActivity主要是个载体,用来向AddPoemActivity和MyPoemActivity用Intent跳转的。其中MainActivity中代码如下:
package com.example.mypoem;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    private ImageView iv_add_poem;
    private ImageView iv_select_poem;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        iv_add_poem = (ImageView) findViewById(R.id.iv_add_poem);
        iv_add_poem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intentIn = new Intent(MainActivity.this,AddPoemActivity.class);
                startActivity(intentIn);
            }
        });

        iv_select_poem = (ImageView) findViewById(R.id.iv_select_poem);
        iv_select_poem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intentMyPoem = new Intent(MainActivity.this,MyPoemActivity.class);
                startActivity(intentMyPoem);
            }
        });
    }
}
  • 8、下面是诗篇的新增功能,通过调用FileDao中的addPoem的方法实现数据的保存。AddPoemActivity代码如下:
package com.example.mypoem;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.example.mypoem.dao.FileDao;
import com.example.mypoem.vo.Poem;

public class AddPoemActivity extends AppCompatActivity {

    private EditText et_title, et_content;
    private Poem poem;
    private Button btn_save, btn_cacel;
    private FileDao fileDao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_poem);
        fileDao = new FileDao(this);

        //获取控件

        et_title = (EditText) findViewById(R.id.et_title);
        et_content = (EditText) findViewById(R.id.et_content);
        btn_save = (Button) findViewById(R.id.btn_save);
        btn_cacel = (Button) findViewById(R.id.btn_cancel);

        btn_save.setOnClickListener(new OnClick());
        btn_cacel.setOnClickListener(new OnClick());

    }

    private class OnClick implements View.OnClickListener {

        @Override
        public void onClick(View view) {

            switch (view.getId()) {
                case R.id.btn_save:
                    Poem poem = new Poem();
                    poem.setTitle(et_title.getText().toString().trim());
                    poem.setContent(et_content.getText().toString().trim());
                   if (fileDao.addPoem(poem) < 0) {
                        Toast.makeText(AddPoemActivity.this, "没有成功添加...", Toast.LENGTH_LONG).show();
                    } else {
                        Toast.makeText(AddPoemActivity.this, "已经成功添加...", Toast.LENGTH_LONG).show();
                        Intent intent = new Intent(AddPoemActivity.this, MainActivity.class);
                        startActivity(intent);
                    }
                    break;
                case R.id.btn_cancel:
                    finish();
                    break;
            }

        }
    }

}
  • 9、诗篇的查询功能的实现,在这里核心操作同样是调用封装好的方法myPoem() ,在这里为了显示多条数据,需要用到适配器SimpleAdapter,这里我没有封装,因为只在着一个地方用到了,不至于封装。但是在这里强调一下,适配器最好单独写一个类。目前笔者现在遇到的,ListView和GridView都需要适配器。,MyPoemActivity中的代码如下:
package com.example.mypoem;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;

import com.example.mypoem.dao.FileDao;
import com.example.mypoem.vo.Poem;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MyPoemActivity extends AppCompatActivity {

    private ListView lv_my_poem;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_poem);

        lv_my_poem = (ListView) findViewById(R.id.lv_my_poem);

        FileDao dao = new FileDao(this);
        List<Poem> list0 = dao.myPoems();
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

        final SimpleAdapter adapter ;
        for (Poem poem :list0){
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("id",poem.getId());
            map.put("title",poem.getTitle());
            map.put("content",poem.getContent());
            list.add(map);
        }

        adapter = new SimpleAdapter(this,list,R.layout.activity_my_poem_lv,
                new String[]{"id","title","content"},
                new int[]{R.id.tv_my_poem_lv_id,R.id.tv_my_poem_lv_title,R.id.tv_my_poem_lv_content});

        lv_my_poem.setAdapter(adapter);
        lv_my_poem.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long id1) {
                Map<String,Object> map = (Map<String, Object>) adapter.getItem(position);
                Integer id = Integer.valueOf(map.get("id").toString());
                String title = map.get("title").toString();
                String content = map.get("content").toString();

                Intent intent = new Intent(MyPoemActivity.this,ManageMyPoemActivity.class);
                intent.putExtra("id",id);
                intent.putExtra("title",title);
                intent.putExtra("content",content);
                startActivity(intent);
            }
        });

    }
}
  • 10、修改和删除,笔者写到了一个Activity,都是调用封装好的方法操作。但是注意一点,删除时按照id删除,如果是按照标题或内容删除,很容易把有着同样标题诗篇删除,这也是我在后期调试的时候发现的,所以按照id删除,不会删错。修改那里,在MyPoemActivity和ManageMyPoemActivity之间,需要用到Intent传递一个Key和Value。ManageMyPoemActivity的代码如下:
package com.example.mypoem;

import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import com.example.mypoem.dao.FileDao;

public class ManageMyPoemActivity extends AppCompatActivity {

    //声明控件
    private EditText et_manage_title,et_manage_content,et_manage_id;
    private Button btn_delete, btn_update, btn_cancel;
    private FileDao dao;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_manage_my_poem);

        //获取控件
        et_manage_title  = (EditText) findViewById(R.id.et_manage_title);
        et_manage_content = (EditText) findViewById(R.id.et_manage_content);
        et_manage_id = (EditText) findViewById(R.id.et_manage_id);

        dao = new FileDao(this);

        btn_cancel = (Button) findViewById(R.id.btn_manage_cancel);
        btn_delete = (Button) findViewById(R.id.btn_manage_delete);
        btn_update = (Button) findViewById(R.id.btn_manage_update);

        //接收从前面传递过来的值
        //接收上面传递过来的值
        Intent intent = getIntent();
        et_manage_id.setId(intent.getIntExtra("id",1));
        et_manage_title.setText(intent.getStringExtra("title"));
        et_manage_content.setText(intent.getStringExtra("content"));

        //点击“取消”按钮
        btn_cancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finish();
            }
        });
        btn_delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                //创建一个对话框
                AlertDialog.Builder builder = new AlertDialog.Builder(ManageMyPoemActivity.this);
                builder.setTitle("删除Poem");
                builder.setMessage("你确定要删除你的灵感吗?");
                builder.setPositiveButton("删除", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        if (dao.poemDelete(Integer.valueOf(et_manage_id.getId())) > 0) {
                            Toast.makeText(ManageMyPoemActivity.this, "删除成功!!!", Toast.LENGTH_SHORT).show();
                            Intent intent2 = new Intent(ManageMyPoemActivity.this, MainActivity.class);
                            startActivity(intent2);
                        } else {
                            Toast.makeText(ManageMyPoemActivity.this, "删除失败!!!", Toast.LENGTH_SHORT).show();
                        }
                    }
                });
                builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {

                    }
                });

                builder.create().show();
            }
        });
        btn_update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //第三步、注意数据顺序不能错位
                //String time, String type, String address, String other, Double money
                if (dao.poemUpdate(et_manage_id.getId(),
                        et_manage_title.getText().toString(),
                        et_manage_content.getText().toString())> 0) {
                    Toast.makeText(ManageMyPoemActivity.this, "修改成功!!!", Toast.LENGTH_SHORT).show();
                    Intent intent1 = new Intent(ManageMyPoemActivity.this, MainActivity.class);
                    startActivity(intent1);
                } else {
                    Toast.makeText(ManageMyPoemActivity.this, "修改失败", Toast.LENGTH_SHORT).show();
                }

            }
        });
    }
}
  • 11、闪屏页面的话,最大的特色就是倒计时功能,实现代码如下:
package com.example.mypoem;

import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

import android.widget.Button;
import android.widget.TextView;

public class SplashActivity extends AppCompatActivity {

    //倒计时控件声明

    private TextView textView ;

    private int count = 5 ;

    private Animation animation ;
   // private Button btnGoLogin;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);

        textView = (TextView) findViewById(R.id.tv_adv);

        //先声明Handler,再书写下面的延迟。

        handler.sendEmptyMessageDelayed(0,1000) ;

        animation= AnimationUtils.loadAnimation(this,R.anim.animation_text);

        new Handler().sendEmptyMessageDelayed(0,1000);
        //5秒钟自动进入登录界面
        /*new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                Intent intent = new Intent();
                intent.setClass(FirstActivity.this, LoginActivity.class);
                startActivity(intent);
                finish();
            }
        }, 3000);*/

       /* this.btnGoLogin = (Button) findViewById(R.id.btn_go_login);

        this.btnGoLogin.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent();
                // 设置跳转参数
                intent.setClass(SplashActivity.this, MainActivity.class);
                // 进行跳转
                startActivity(intent);
                // 销毁当前Activity
                finish();
            }
        });*/
         /*   @Override
            public void onClick(View v) {
               // String msg = "你好呀";
                // 跳转到主界面
                // 实例化意图
                Intent intent = new Intent();
                // 设置跳转参数
                intent.setClass(FirstActivity.this, LoginActivity.class);

                // 放置传递的数据
               // intent.putExtra("message",msg);

                // 进行跳转
                startActivity(intent);
                // 销毁当前Activity
                finish();
            }
        });*/
    }
    private int getCount(){
        count-- ;
        if (count == 0){
            Intent intent = new Intent();
            intent.setClass(this, MainActivity.class);
            startActivity(intent);
            finish();
        }
        return count;
    }
    private Handler handler = new Handler(){
        public void handleMessage(android.os.Message msg){
            if (msg.what == 0){
                textView.setText(getCount()+"");
                handler.sendEmptyMessageDelayed(0,1000) ;
                animation.reset();
                textView.startAnimation(animation);
            }
        }
    };
}
  • 12、布局文件不太难,大家就在源码里面看好了,指得注意的是圆形按键的实现,是调用了btn_circle.xml文件实现,在drawable目录下。
  • 13、大家如果想看APP的具体实现效果,可以去下载,apk地址如下:http://shouji.baidu.com/software/10937287.html
5人推荐
随时随地看视频
慕课网APP