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