Android应用-备忘录实现重点

前言

最近在做一个题目,是关于备忘录的实现。由于时间比较紧迫,所以只花了两天半左右时间完成,实现了日历的显示、日程的记录、数据的存储与读取以及解锁控件等功能,本文文末会附上源码下载地址,欢迎下载查看。文章不对全项目分析,只解析部分重点实现方式。

功能

(1)显示出日历
(2)进行行程的记录、删除、查看、分享、修改功能
(3)保存行程数据/读取行程数据
(4)可对App设置图案密码

效果图


开发工具

Android Studio

开发环境

1)JDK(Java Development Kit)JDK是Java语言的软件开发工具包,主要用于移动设备、嵌入设备上的java应用程序。

2)SDK(software development kit) SDK是软件开发工具包。 被软件开发工程师用于为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件的开发工具的集合

实现过程重点解析

(1)日历的自定义

Android实际上是提供了日历这个控件的,但是如果能自定义View也许会更完美。那么,第一步当然是要自定义日历控件。我们首先需要定义一个NewCalender类继承于线性布局,在类中实现对布局的引入等操作。当然,在此之前,要自定义一个日历xml布局
代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" 
    android:layout_width="match_parent"
    android:layout_height="match_parent">
<RelativeLayout
    android:id="@+id/calender_header"
    android:layout_width="match_parent"
    android:layout_height="30dp">
    <ImageView
        android:id="@+id/btnPrev"
        android:background="@mipmap/last"
        android:layout_width="30dp"
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="100dp"
        android:layout_height="30dp" />
    <ImageView
        android:id="@+id/btnNext"
        android:layout_width="30dp"
 android:layout_alignParentRight="true"
        android:layout_marginRight="100dp"
        android:background="@mipmap/next"
        android:layout_height="30dp" />
    <TextView
        android:text="2017 10"
        android:gravity="center"
        android:layout_width="wrap_content"
        android:layout_centerVertical="true"
        android:layout_height="match_parent" 
        android:layout_toRightOf="@id/btnPrev"
        android:layout_toLeftOf="@id/btnNext"
        android:id="@+id/txtDate"/>
</RelativeLayout>
    <LinearLayout
        android:layout_marginTop="2dp"
        android:orientation="horizontal"
        android:id="@+id/calender_week_header"
        android:layout_width="match_parent"
        android:layout_height="40dp">
        <TextView
            android:text="星期日"
            android:textSize="15dp"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            />
        <TextView
            android:textSize="15dp"
            android:text="星期一"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
        <TextView
            android:text="星期二"
            android:textSize="15dp"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
        <TextView
            android:text="星期三"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:textSize="15dp"
            android:layout_height="match_parent" />
        <TextView
            android:text="星期四"
            android:textSize="15dp"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
        <TextView
            android:text="星期五"
            android:textSize="15dp"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
        <TextView
            android:text="星期六"
            android:textSize="15dp"
            android:layout_gravity="center_horizontal"
            android:layout_weight="1"
            android:layout_width="0dp"
            android:layout_height="match_parent" />
    </LinearLayout>
    <GridView
        android:layout_width="match_parent"
        android:numColumns="7"
        android:id="@+id/calender_grid"
        android:layout_height="match_parent"/>
</LinearLayout>
public class NewCalender extends LinearLayout {
    private ImageView btnPrev;
    private ImageView btnNext;
    private TextView txtDate;
    private GridView grid;
    public  ArrayList<Date> cells=new ArrayList<>();
    public NewCalendarListener newCalendarListener;
    private Calendar curDate=Calendar.getInstance();  //minsdk api:24
    public NewCalender(Context context) {
        super(context);
    }

    public NewCalender(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initControl(context);
        bindControlEvent();
        renderCalendar();
    }

    public NewCalender(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initControl(context);
    }
    private void initControl(Context context)
    {
        bindControl(context);
    }
    //绑定各控件
    private void bindControl(Context context)
    {
        LayoutInflater inflater=LayoutInflater.from(context);
        inflater.inflate(R.layout.calender_view,this);
        btnPrev=(ImageView)findViewById(R.id.btnPrev);
        btnNext=(ImageView)findViewById(R.id.btnNext);
        txtDate=(TextView)findViewById(R.id.txtDate);
        grid=(GridView)findViewById(R.id.calender_grid);
    }
    //设置前后按钮监听事件
    //便于日历月份的变化处理
    private void bindControlEvent()
    {
        btnPrev.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                    curDate.add(Calendar.MONTH,-1);
                  renderCalendar();
            }
        });
        btnNext.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                curDate.add(Calendar.MONTH,+1);
                renderCalendar();
            }
        });
    }
    //渲染函数 对日历控件进行渲染
    private  void renderCalendar()
    {
        SimpleDateFormat sdf=new SimpleDateFormat("MMM YYYY");
        txtDate.setText(sdf.format(curDate.getTime()));
        Calendar calendar=(Calendar) curDate.clone();  //复制一个curDate
        calendar.set(Calendar.DAY_OF_MONTH,1);
        int preDays=calendar.get(Calendar.DAY_OF_WEEK)-1;
        calendar.add(Calendar.DAY_OF_MONTH,-preDays);
        int maxCellCount=6*7;
        cells.clear();
        while(cells.size()<maxCellCount)
        {
            cells.add(calendar.getTime());
            calendar.add(Calendar.DAY_OF_MONTH,1);
        }
        grid.setAdapter(new CalendarAdapter(getContext(),cells));
        grid.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                 newCalendarListener.onItemPress((Date)adapterView.getItemAtPosition(i),i);
            }
        });

    }
    private class CalendarAdapter extends ArrayAdapter<Date>
    {
           LayoutInflater inflater;
        public CalendarAdapter(@NonNull Context context, ArrayList<Date> days) {
            super(context,R.layout.calendar_day,days);
            inflater=LayoutInflater.from(context);
        }
        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            Date date=getItem(position);
            if(convertView==null)
            {
                convertView = inflater.inflate(R.layout.calendar_day, parent, false);
            }
            int day=date.getDate();
            ((TextView)convertView).setText(String.valueOf(day));
            //设置字体颜色
            Date now=new Date();
            Calendar calendar=(Calendar) curDate.clone();
            calendar.set(Calendar.DAY_OF_MONTH,1);
            boolean isTheSameMonth=false;
            if(now.getMonth()==date.getMonth())
            {
                isTheSameMonth=true;
            }
            if(isTheSameMonth)
            {
                ((Calendar_text_view)convertView).setTextColor(Color.parseColor("#000000"));
            }else
            {
                ((Calendar_text_view)convertView).setTextColor(Color.parseColor("#666666"));
            }

            if(now.getDate()==date.getDate()&&now.getMonth()==date.getMonth()
                    &&now.getYear()==date.getYear())
            {
                ((Calendar_text_view)convertView).setTextColor(Color.parseColor("#ff0000"));
                ((Calendar_text_view)convertView).isToday=true;
            }
             return convertView;
        }
    }
    //自定义接口 在主活动中可调用
    //设置了position参数 便于对所选日期位置进行记录
    //方便日程的保存
    public  interface  NewCalendarListener
    {
        void onItemPress(Date day,int position);
    }
}

其中,Calendar_text_view类是自定义的文本显示框,当日日期将会显示红色圆边框。

public class Calendar_text_view extends android.support.v7.widget.AppCompatTextView {
    public  boolean isToday=false;
    public Paint paint;
    @Override
    public int getSystemUiVisibility() {
        return super.getSystemUiVisibility();
    }

    public Calendar_text_view(Context context) {
        super(context);
    }

    public Calendar_text_view(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initControl();
    }

    public Calendar_text_view(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initControl();
    }
    private void initControl()
    {   paint=new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.parseColor("#FF0000"));
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(isToday)
        {  canvas.translate(getWidth()/2,getHeight()/2);
           canvas.drawCircle(0,0,getWidth()/2,paint);
        }
    }
}

(2)日程点击事件

当我们点击日期时,下方将会有一个ListView用于显示当天的行程,那么点击行程后,我们可以进行行程的修改、删除、分享、查看等功能。这里我将选项放置在了ChooseActivity中,利startActivityForResult将选择的结果以判断值的形式返回给主活动,主活动根据判断值的不同作出不同的响应,这样的做法使得程序思路较为清晰。

public class chooseActivity extends Activity implements View.OnClickListener{
    public Button btnLook;
    public Button btndelete;
    public Button btnmodify;
    public Button btnshare;
    public Button btnAlarm;
    /*
    *此活动时通过startActivityforresult启动的
    * 故只会根据用户的选择返回不同的判断值
    * 然后具体在逻辑处理仍旧时在MainActivity中处理
    */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_choose);
        btnLook=(Button)findViewById(R.id.look);
        btndelete=(Button)findViewById(R.id.delete);
        btnmodify=(Button)findViewById(R.id.modify);
        btnshare=(Button)findViewById(R.id.share);
        btnAlarm=(Button)findViewById(R.id.alarm_set);
        btnAlarm.setOnClickListener(this);
        btndelete.setOnClickListener(this);
        btnmodify.setOnClickListener(this);
        btnLook.setOnClickListener(this);
        btnshare.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        Intent intent=new Intent();
        switch (view.getId())
        {
            case R.id.look:
                //返回判断值1
                intent.putExtra("judge",1);
                setResult(RESULT_OK,intent);
                finish();
                break;
            case R.id.delete:
                //返回判断值2
                intent.putExtra("judge",2);
                setResult(RESULT_OK,intent);
                finish();
                break;
            case R.id.modify:
                //返回判断值3
                intent.putExtra("judge",3);
                setResult(RESULT_OK,intent);
                finish();
                break;
            case R.id.share:
                Intent intent1=new Intent(Intent.ACTION_SEND);
                intent1.setType("text/plain");
                //分享文本内容
                intent1.putExtra(Intent.EXTRA_TEXT,getIntent().getStringExtra("content"));
                intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(Intent.createChooser(intent1,getTitle()));
                break;
            case R.id.alarm_set:
                intent.putExtra("judge",4);
                setResult(RESULT_OK,intent);
                finish();
                break;


        }
    }

主活动处理:

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode)
        {
            case 1:if(resultCode==RESULT_OK&&data.getStringExtra("judge")!="cancel")
            {
                Bundle bundle=data.getBundleExtra("add");
                sch.add((schedule)bundle.getSerializable("add_data"));
                saveData(mPosition);
                sch_view.setVisibility(View.VISIBLE);
                nullSch.setVisibility(View.GONE);
                schAdapter adapter=new schAdapter(sch,this);
                sch_view.setAdapter(adapter);
            }
                if(resultCode==2)
                {
                    Bundle bundle=data.getBundleExtra("add");
                    sch.remove(lvPosition);
                    sch.add((schedule)bundle.getSerializable("add_data"));
                    saveData(mPosition);
                    sch_view.setVisibility(View.VISIBLE);
                    nullSch.setVisibility(View.GONE);
                    schAdapter adapter=new schAdapter(sch,this);
                    sch_view.setAdapter(adapter);
                }
                break;
            case 2:if(resultCode==RESULT_OK)
            {
                int judge=data.getIntExtra("judge",0);
                switch (judge)
                {
                    case 1:Intent intent=new Intent(MainActivity.this,lookActivity.class);
                        intent.putExtra("time",curDay+sch.get(lvPosition).time);
                        intent.putExtra("content",sch.get(lvPosition).content);
                        startActivity(intent);
                        break;
                    case 2: sch.remove(lvPosition);
                        saveData(mPosition);
                        schAdapter adapter=new schAdapter(sch,this);
                        sch_view.setAdapter(adapter);
                        break;
                    //修改日程
                    case 3:
                        Intent intent1=new Intent(MainActivity.this,addActivity.class);
                        String [] a=sch.get(lvPosition).time.split(":");
                        intent1.putExtra("hour",a[0]);
                        intent1.putExtra("min",a[1]);
                        intent1.putExtra("content",sch.get(lvPosition).content);
                        startActivityForResult(intent1,1);
                        break;
                    //闹钟设置
                    case 4:
                         setalarm();
                        break;
                }
            }
                break;
        }
    }

其中,修改、查看均为Acitivity,将由主活动跳转.

(3)解锁控件的应用

本应用添加了锁定功能,用于保护隐私。使用的时开源控件PatternLockView,使用前,我们需要在gradle中添加以下依赖:

  compile 'com.andrognito.patternlockview:patternlockview:1.0.0'

之后可以设置按钮,点击后跳转到设置密码的Activity,在活动中再对密码进行处理与保存等操作。
patternlockview监听器提供了以下方法。

public void onStarted();
public void onProgress(List<PatternLockView.Dot> progressPattern);
public void onComplete(List<PatternLockView.Dot> pattern);
public void onCleared();

在第三个函数中实现密码的处理操作即可。

可拓展功能

实现闹钟提醒,UI美化等

总结

本文重点在日定义的实现代码部分,代码也有部分注释,理解代码可能需要一定的android基础,由于本人写简书的经验不足,难以做到浅显易懂,见谅。如果能对你有所帮助,当然最好。如果你也想实现一个备忘录,有问题也可私信交流。谢谢阅读。文末附上源码。
https://pan.baidu.com/s/1o8OIivC
密码:x6t4
下载前私信告知一声哦。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容