华南理工大学无线电爱好者协会软件小组

Android应用-备忘录实现重点

2017-10-14  本文已影响72人  3a7e0b22a5df

前言

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

功能

(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
下载前私信告知一声哦。

上一篇下一篇

猜你喜欢

热点阅读