pxf_branch
parent
ba125b98e3
commit
139a2237fa
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest package="com.ldf.mi.calendar">
|
||||
|
||||
</manifest>
|
@ -0,0 +1,11 @@
|
||||
package com.ldf.calendar;
|
||||
|
||||
// 这个类定义了一些常量,用于日历视图的布局和设定
|
||||
public class Const {
|
||||
// 表示日历视图的总列数
|
||||
public final static int TOTAL_COL = 7;
|
||||
// 表示日历视图的总行数
|
||||
public final static int TOTAL_ROW = 6;
|
||||
// 表示当前的页面索引,用于日历视图的显示
|
||||
public final static int CURRENT_PAGER_INDEX = 1000;
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package com.ldf.calendar.component;
|
||||
|
||||
/**
|
||||
* 日历属性类
|
||||
*/
|
||||
|
||||
public class CalendarAttr {
|
||||
|
||||
// 周起始类型
|
||||
private WeekArrayType weekArrayType;
|
||||
|
||||
// 日历类型
|
||||
private CalendarType calendarType;
|
||||
|
||||
// 单元格高度
|
||||
private int cellHeight;
|
||||
|
||||
// 单元格宽度
|
||||
private int cellWidth;
|
||||
|
||||
public WeekArrayType getWeekArrayType() {
|
||||
return weekArrayType;
|
||||
}
|
||||
|
||||
public void setWeekArrayType(WeekArrayType weekArrayType) {
|
||||
this.weekArrayType = weekArrayType;
|
||||
}
|
||||
|
||||
public CalendarType getCalendarType() {
|
||||
return calendarType;
|
||||
}
|
||||
|
||||
public void setCalendarType(CalendarType calendarType) {
|
||||
this.calendarType = calendarType;
|
||||
}
|
||||
|
||||
public int getCellHeight() {
|
||||
return cellHeight;
|
||||
}
|
||||
|
||||
public void setCellHeight(int cellHeight) {
|
||||
this.cellHeight = cellHeight;
|
||||
}
|
||||
|
||||
public int getCellWidth() {
|
||||
return cellWidth;
|
||||
}
|
||||
|
||||
public void setCellWidth(int cellWidth) {
|
||||
this.cellWidth = cellWidth;
|
||||
}
|
||||
|
||||
// 周起始类型枚举
|
||||
public enum WeekArrayType {
|
||||
Sunday, Monday
|
||||
}
|
||||
|
||||
// 日历类型枚举
|
||||
public enum CalendarType {
|
||||
WEEK, MONTH
|
||||
}
|
||||
}
|
@ -0,0 +1,318 @@
|
||||
package com.ldf.calendar.component;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.util.Log;
|
||||
|
||||
import com.ldf.calendar.Const;
|
||||
import com.ldf.calendar.Utils;
|
||||
import com.ldf.calendar.interf.IDayRenderer;
|
||||
import com.ldf.calendar.interf.OnSelectDateListener;
|
||||
import com.ldf.calendar.model.CalendarDate;
|
||||
import com.ldf.calendar.view.Calendar;
|
||||
import com.ldf.calendar.view.Day;
|
||||
import com.ldf.calendar.view.Week;
|
||||
|
||||
public class CalendarRenderer {
|
||||
// 用于存储每行的日期数据,数组长度为总行数
|
||||
private Week[] weeks = new Week[Const.TOTAL_ROW];
|
||||
private Calendar calendar;// 日历对象
|
||||
private CalendarAttr attr;// 日历属性
|
||||
private IDayRenderer dayRenderer;// 日期渲染器接口
|
||||
private Context context;// 上下文
|
||||
private OnSelectDateListener onSelectDateListener;// 单元格点击回调事件
|
||||
private CalendarDate seedDate; //种子日期
|
||||
private CalendarDate selectedDate; //被选中的日期
|
||||
private int selectedRowIndex = 0;
|
||||
|
||||
public CalendarRenderer(Calendar calendar, CalendarAttr attr, Context context) {
|
||||
this.calendar = calendar;
|
||||
this.attr = attr;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
// 绘制日历
|
||||
public void draw(Canvas canvas) {
|
||||
for (int row = 0; row < Const.TOTAL_ROW; row++) {
|
||||
if (weeks[row] != null) {
|
||||
for (int col = 0; col < Const.TOTAL_COL; col++) {
|
||||
if (weeks[row].days[col] != null) {
|
||||
// 调用日期渲染器接口绘制日期
|
||||
dayRenderer.drawDay(canvas, weeks[row].days[col]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理日期点击事件
|
||||
public void onClickDate(int col, int row) {
|
||||
if (col >= Const.TOTAL_COL || row >= Const.TOTAL_ROW)
|
||||
return;
|
||||
if (weeks[row] != null) {
|
||||
if (attr.getCalendarType() == CalendarAttr.CalendarType.MONTH) {
|
||||
if (weeks[row].days[col].getState() == State.CURRENT_MONTH) {
|
||||
// 如果点击的日期是当月日期,则设置为选中状态,并触发选中日期回调事件
|
||||
weeks[row].days[col].setState(State.SELECT);
|
||||
selectedDate = weeks[row].days[col].getDate();
|
||||
CalendarViewAdapter.saveSelectedDate(selectedDate);
|
||||
onSelectDateListener.onSelectDate(selectedDate);
|
||||
seedDate = selectedDate;
|
||||
} else if (weeks[row].days[col].getState() == State.PAST_MONTH) {
|
||||
// 如果点击的日期是上个月的日期,则保存选中的日期并触发选中其他月份日期回调事件
|
||||
selectedDate = weeks[row].days[col].getDate();
|
||||
CalendarViewAdapter.saveSelectedDate(selectedDate);
|
||||
onSelectDateListener.onSelectOtherMonth(-1);
|
||||
onSelectDateListener.onSelectDate(selectedDate);
|
||||
} else if (weeks[row].days[col].getState() == State.NEXT_MONTH) {
|
||||
// 如果点击的日期是下个月的日期,则保存选中的日期并触发选中其他月份日期回调事件
|
||||
selectedDate = weeks[row].days[col].getDate();
|
||||
CalendarViewAdapter.saveSelectedDate(selectedDate);
|
||||
onSelectDateListener.onSelectOtherMonth(1);
|
||||
onSelectDateListener.onSelectDate(selectedDate);
|
||||
}
|
||||
} else {
|
||||
// 如果日历类型不是月视图,则直接设置点击的日期为选中状态,并触发选中日期回调事件
|
||||
weeks[row].days[col].setState(State.SELECT);
|
||||
selectedDate = weeks[row].days[col].getDate();
|
||||
CalendarViewAdapter.saveSelectedDate(selectedDate);
|
||||
onSelectDateListener.onSelectDate(selectedDate);
|
||||
seedDate = selectedDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void updateWeek(int rowIndex) {
|
||||
CalendarDate currentWeekLastDay;
|
||||
if (attr.getWeekArrayType() == CalendarAttr.WeekArrayType.Sunday) {
|
||||
// 如果一周的起始是星期天,则当前周的最后一天是星期六
|
||||
currentWeekLastDay = Utils.getSaturday(seedDate);
|
||||
} else {
|
||||
// 如果一周的起始是星期一,则当前周的最后一天是星期天
|
||||
currentWeekLastDay = Utils.getSunday(seedDate);
|
||||
}
|
||||
int day = currentWeekLastDay.day;
|
||||
for (int i = Const.TOTAL_COL - 1; i >= 0; i--) {
|
||||
// 逐个填充当前周的日期数据
|
||||
CalendarDate date = currentWeekLastDay.modifyDay(day);
|
||||
if (weeks[rowIndex] == null) {
|
||||
weeks[rowIndex] = new Week(rowIndex);
|
||||
}
|
||||
if (weeks[rowIndex].days[i] != null) {
|
||||
// 如果日期数据已存在,则更新状态和日期
|
||||
if (date.equals(CalendarViewAdapter.loadSelectedDate())) {
|
||||
weeks[rowIndex].days[i].setState(State.SELECT);
|
||||
weeks[rowIndex].days[i].setDate(date);
|
||||
} else {
|
||||
weeks[rowIndex].days[i].setState(State.CURRENT_MONTH);
|
||||
weeks[rowIndex].days[i].setDate(date);
|
||||
}
|
||||
} else {
|
||||
// 如果日期数据不存在,则创建新的日期对象
|
||||
if (date.equals(CalendarViewAdapter.loadSelectedDate())) {
|
||||
weeks[rowIndex].days[i] = new Day(State.SELECT, date, rowIndex, i);
|
||||
} else {
|
||||
weeks[rowIndex].days[i] = new Day(State.CURRENT_MONTH, date, rowIndex, i);
|
||||
}
|
||||
}
|
||||
day--;
|
||||
}
|
||||
}
|
||||
|
||||
private void instantiateMonth() {
|
||||
// 上个月的天数
|
||||
int lastMonthDays = Utils.getMonthDays(seedDate.year, seedDate.month - 1);
|
||||
// 当前月的天数
|
||||
int currentMonthDays = Utils.getMonthDays(seedDate.year, seedDate.month);
|
||||
int firstDayPosition = Utils.getFirstDayWeekPosition(
|
||||
seedDate.year,
|
||||
seedDate.month,
|
||||
attr.getWeekArrayType());
|
||||
Log.e("ldf", "firstDayPosition = " + firstDayPosition);
|
||||
|
||||
int day = 0;
|
||||
for (int row = 0; row < Const.TOTAL_ROW; row++) {
|
||||
day = fillWeek(lastMonthDays, currentMonthDays, firstDayPosition, day, row);
|
||||
}
|
||||
}
|
||||
|
||||
private int fillWeek(int lastMonthDays,
|
||||
int currentMonthDays,
|
||||
int firstDayWeek,
|
||||
int day,
|
||||
int row) {
|
||||
for (int col = 0; col < Const.TOTAL_COL; col++) {
|
||||
int position = col + row * Const.TOTAL_COL;// 单元格位置
|
||||
if (position >= firstDayWeek && position < firstDayWeek + currentMonthDays) {
|
||||
day++;
|
||||
fillCurrentMonthDate(day, row, col);
|
||||
} else if (position < firstDayWeek) {
|
||||
instantiateLastMonth(lastMonthDays, firstDayWeek, row, col, position);
|
||||
} else if (position >= firstDayWeek + currentMonthDays) {
|
||||
instantiateNextMonth(currentMonthDays, firstDayWeek, row, col, position);
|
||||
}
|
||||
}
|
||||
return day;
|
||||
}
|
||||
|
||||
private void fillCurrentMonthDate(int day, int row, int col) {
|
||||
// 填充当前月的日期数据
|
||||
CalendarDate date = seedDate.modifyDay(day);
|
||||
if (weeks[row] == null) {
|
||||
weeks[row] = new Week(row);
|
||||
}
|
||||
if (weeks[row].days[col] != null) {
|
||||
if (date.equals(CalendarViewAdapter.loadSelectedDate())) {
|
||||
weeks[row].days[col].setDate(date);
|
||||
weeks[row].days[col].setState(State.SELECT);
|
||||
} else {
|
||||
weeks[row].days[col].setDate(date);
|
||||
weeks[row].days[col].setState(State.CURRENT_MONTH);
|
||||
}
|
||||
} else {
|
||||
if (date.equals(CalendarViewAdapter.loadSelectedDate())) {
|
||||
weeks[row].days[col] = new Day(State.SELECT, date, row, col);
|
||||
} else {
|
||||
weeks[row].days[col] = new Day(State.CURRENT_MONTH, date, row, col);
|
||||
}
|
||||
}
|
||||
if (date.equals(seedDate)) {
|
||||
selectedRowIndex = row;
|
||||
}
|
||||
}
|
||||
|
||||
private void instantiateNextMonth(int currentMonthDays,
|
||||
int firstDayWeek,
|
||||
int row,
|
||||
int col,
|
||||
int position) {
|
||||
// 创建下一个月的日期对象
|
||||
CalendarDate date = new CalendarDate(
|
||||
seedDate.year,
|
||||
seedDate.month + 1,
|
||||
position - firstDayWeek - currentMonthDays + 1);
|
||||
// 如果当前行的周对象为空,则创建新的周对象
|
||||
if (weeks[row] == null) {
|
||||
weeks[row] = new Week(row);
|
||||
}
|
||||
// 如果当前行的日对象不为空,则设置日期和状态;
|
||||
if (weeks[row].days[col] != null) {
|
||||
weeks[row].days[col].setDate(date);
|
||||
weeks[row].days[col].setState(State.NEXT_MONTH);
|
||||
}
|
||||
//否则创建新的日对象并设置日期和状态
|
||||
else {
|
||||
weeks[row].days[col] = new Day(State.NEXT_MONTH, date, row, col);
|
||||
}
|
||||
}
|
||||
|
||||
// 为当前日期视图创建上一个月的日期对象并设置相关状态,同上
|
||||
private void instantiateLastMonth(int lastMonthDays, int firstDayWeek, int row, int col, int position) {
|
||||
CalendarDate date = new CalendarDate(
|
||||
seedDate.year,
|
||||
seedDate.month - 1,
|
||||
lastMonthDays - (firstDayWeek - position - 1));
|
||||
if (weeks[row] == null) {
|
||||
weeks[row] = new Week(row);
|
||||
}
|
||||
if (weeks[row].days[col] != null) {
|
||||
weeks[row].days[col].setDate(date);
|
||||
weeks[row].days[col].setState(State.PAST_MONTH);
|
||||
} else {
|
||||
weeks[row].days[col] = new Day(State.PAST_MONTH, date, row, col);
|
||||
}
|
||||
}
|
||||
|
||||
// 设置要显示的日期
|
||||
public void showDate(CalendarDate seedDate) {
|
||||
if (seedDate != null) {
|
||||
this.seedDate = seedDate;
|
||||
} else {
|
||||
this.seedDate = new CalendarDate();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
// 更新日期视图
|
||||
public void update() {
|
||||
// 实例化月份并使日历失效以便重新绘制
|
||||
instantiateMonth();
|
||||
calendar.invalidate();
|
||||
}
|
||||
|
||||
// 获取当前日期
|
||||
public CalendarDate getSeedDate() {
|
||||
return this.seedDate;
|
||||
}
|
||||
|
||||
// 取消选中日期的状态
|
||||
public void cancelSelectState() {
|
||||
// 遍历所有日期,将选中状态的日期重置为当前月状态并重置选中行索引
|
||||
for (int i = 0; i < Const.TOTAL_ROW; i++) {
|
||||
if (weeks[i] != null) {
|
||||
for (int j = 0; j < Const.TOTAL_COL; j++) {
|
||||
if (weeks[i].days[j].getState() == State.SELECT) {
|
||||
weeks[i].days[j].setState(State.CURRENT_MONTH);
|
||||
resetSelectedRowIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 重置选中行索引
|
||||
public void resetSelectedRowIndex() {
|
||||
selectedRowIndex = 0;
|
||||
}
|
||||
|
||||
// 获取选中行索引
|
||||
public int getSelectedRowIndex() {
|
||||
return selectedRowIndex;
|
||||
}
|
||||
|
||||
// 设置选中行索引
|
||||
public void setSelectedRowIndex(int selectedRowIndex) {
|
||||
this.selectedRowIndex = selectedRowIndex;
|
||||
}
|
||||
|
||||
// 获取日历对象
|
||||
public Calendar getCalendar() {
|
||||
return calendar;
|
||||
}
|
||||
|
||||
// 设置日历对象
|
||||
public void setCalendar(Calendar calendar) {
|
||||
this.calendar = calendar;
|
||||
}
|
||||
|
||||
// 获取日期属性
|
||||
public CalendarAttr getAttr() {
|
||||
return attr;
|
||||
}
|
||||
|
||||
// 设置日期属性
|
||||
public void setAttr(CalendarAttr attr) {
|
||||
this.attr = attr;
|
||||
}
|
||||
|
||||
// 获取上下文对象
|
||||
public Context getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
// 设置上下文对象
|
||||
public void setContext(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
// 设置日期选择监听器
|
||||
public void setOnSelectDateListener(OnSelectDateListener onSelectDateListener) {
|
||||
this.onSelectDateListener = onSelectDateListener;
|
||||
}
|
||||
|
||||
// 设置日期渲染器
|
||||
public void setDayRenderer(IDayRenderer dayRenderer) {
|
||||
this.dayRenderer = dayRenderer;
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.ldf.calendar.component;
|
||||
|
||||
/**
|
||||
* 日历状态枚举
|
||||
*/
|
||||
public enum State {
|
||||
CURRENT_MONTH, // 当前月
|
||||
PAST_MONTH, // 过去的月份
|
||||
NEXT_MONTH, // 下一个月
|
||||
SELECT // 选中状态
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.ldf.calendar.interf;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
|
||||
import com.ldf.calendar.view.Day;
|
||||
|
||||
/**
|
||||
* 日历每日单元渲染接口
|
||||
*/
|
||||
public interface IDayRenderer {
|
||||
//刷新内容
|
||||
void refreshContent();
|
||||
|
||||
//绘制单个日期
|
||||
void drawDay(Canvas canvas, Day day);
|
||||
|
||||
//复制日历渲染器
|
||||
IDayRenderer copy();
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.ldf.calendar.interf;
|
||||
|
||||
// 定义了一个接口 OnAdapterSelectListener
|
||||
public interface OnAdapterSelectListener {
|
||||
|
||||
// 取消选择状态的方法声明
|
||||
void cancelSelectState();
|
||||
|
||||
// 更新选择状态的方法声明
|
||||
void updateSelectState();
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.ldf.calendar.interf;
|
||||
|
||||
import com.ldf.calendar.model.CalendarDate;
|
||||
|
||||
// 定义了一个接口 OnSelectDateListener
|
||||
public interface OnSelectDateListener {
|
||||
|
||||
// 选中日期的方法声明,接收一个 CalendarDate 对象作为参数
|
||||
void onSelectDate(CalendarDate date);
|
||||
|
||||
// 选中其它月份日期的方法声明,接收表示月份偏移量的整数作为参数
|
||||
void onSelectOtherMonth(int offset);
|
||||
}
|
@ -0,0 +1,151 @@
|
||||
package com.ldf.calendar.model;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.ldf.calendar.Utils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Calendar;
|
||||
|
||||
public class CalendarDate implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public int year;
|
||||
public int month; //1~12
|
||||
public int day;
|
||||
// 构造方法,用指定的年、月、日来初始化对象
|
||||
public CalendarDate(int year, int month, int day) {
|
||||
if (month > 12) {
|
||||
month = 1;
|
||||
year++;
|
||||
} else if (month < 1) {
|
||||
month = 12;
|
||||
year--;
|
||||
}
|
||||
this.year = year;
|
||||
this.month = month;
|
||||
this.day = day;
|
||||
}
|
||||
// 无参构造方法,默认使用当前系统日期来初始化对象
|
||||
public CalendarDate() {
|
||||
this.year = Utils.getYear();
|
||||
this.month = Utils.getMonth();
|
||||
this.day = Utils.getDay();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过修改当前Date对象的天数返回一个修改后的Date
|
||||
*
|
||||
* @return CalendarDate 修改后的日期
|
||||
*/
|
||||
public CalendarDate modifyDay(int day) {
|
||||
int lastMonthDays = Utils.getMonthDays(this.year, this.month - 1);
|
||||
int currentMonthDays = Utils.getMonthDays(this.year, this.month);
|
||||
|
||||
CalendarDate modifyDate;
|
||||
if (day > currentMonthDays) {
|
||||
modifyDate = new CalendarDate(this.year, this.month, this.day);
|
||||
Log.e("ldf", "移动天数过大");
|
||||
} else if (day > 0) {
|
||||
modifyDate = new CalendarDate(this.year, this.month, day);
|
||||
} else if (day > 0 - lastMonthDays) {
|
||||
modifyDate = new CalendarDate(this.year, this.month - 1, lastMonthDays + day);
|
||||
} else {
|
||||
modifyDate = new CalendarDate(this.year, this.month, this.day);
|
||||
Log.e("ldf", "移动天数过大");
|
||||
}
|
||||
return modifyDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过修改当前Date对象的所在周返回一个修改后的Date
|
||||
*
|
||||
* @return CalendarDate 修改后的日期
|
||||
*/
|
||||
public CalendarDate modifyWeek(int offset) {
|
||||
CalendarDate result = new CalendarDate();
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.set(Calendar.YEAR, year);
|
||||
c.set(Calendar.MONTH, month - 1);
|
||||
c.set(Calendar.DAY_OF_MONTH, day);
|
||||
c.add(Calendar.DATE, offset * 7);
|
||||
result.setYear(c.get(Calendar.YEAR));
|
||||
result.setMonth(c.get(Calendar.MONTH) + 1);
|
||||
result.setDay(c.get(Calendar.DATE));
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过修改当前Date对象的所在月返回一个修改后的Date
|
||||
*
|
||||
* @return CalendarDate 修改后的日期
|
||||
*/
|
||||
public CalendarDate modifyMonth(int offset) {
|
||||
CalendarDate result = new CalendarDate();
|
||||
int addToMonth = this.month + offset;
|
||||
if (offset > 0) {
|
||||
if (addToMonth > 12) {
|
||||
result.setYear(this.year + (addToMonth - 1) / 12);
|
||||
result.setMonth(addToMonth % 12 == 0 ? 12 : addToMonth % 12);
|
||||
} else {
|
||||
result.setYear(this.year);
|
||||
result.setMonth(addToMonth);
|
||||
}
|
||||
} else {
|
||||
if (addToMonth == 0) {
|
||||
result.setYear(this.year - 1);
|
||||
result.setMonth(12);
|
||||
} else if (addToMonth < 0) {
|
||||
result.setYear(this.year + addToMonth / 12 - 1);
|
||||
int month = 12 - Math.abs(addToMonth) % 12;
|
||||
result.setMonth(month == 0 ? 12 : month);
|
||||
} else {
|
||||
result.setYear(this.year);
|
||||
result.setMonth(addToMonth == 0 ? 12 : addToMonth);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return year + "-" + month + "-" + day;
|
||||
}
|
||||
// 下面是获取、设置年、月、日
|
||||
public int getYear() {
|
||||
return year;
|
||||
}
|
||||
|
||||
public void setYear(int year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public int getMonth() {
|
||||
return month;
|
||||
}
|
||||
|
||||
public void setMonth(int month) {
|
||||
this.month = month;
|
||||
}
|
||||
|
||||
public int getDay() {
|
||||
return day;
|
||||
}
|
||||
|
||||
public void setDay(int day) {
|
||||
this.day = day;
|
||||
}
|
||||
// 比较两个日期是否相等
|
||||
public boolean equals(CalendarDate date) {
|
||||
if (date == null) {
|
||||
return false;
|
||||
}
|
||||
return this.getYear() == date.getYear()
|
||||
&& this.getMonth() == date.getMonth()
|
||||
&& this.getDay() == date.getDay();
|
||||
}
|
||||
// 克隆当前日期对象
|
||||
public CalendarDate cloneSelf() {
|
||||
return new CalendarDate(year, month, day);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,152 @@
|
||||
package com.ldf.calendar.view;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.ldf.calendar.Const;
|
||||
import com.ldf.calendar.Utils;
|
||||
import com.ldf.calendar.component.CalendarAttr;
|
||||
import com.ldf.calendar.component.CalendarRenderer;
|
||||
import com.ldf.calendar.interf.IDayRenderer;
|
||||
import com.ldf.calendar.interf.OnAdapterSelectListener;
|
||||
import com.ldf.calendar.interf.OnSelectDateListener;
|
||||
import com.ldf.calendar.model.CalendarDate;
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
public class Calendar extends View {
|
||||
/**
|
||||
* 日历列数
|
||||
*/
|
||||
private CalendarAttr.CalendarType calendarType;// 日历类型
|
||||
private int cellHeight; // 单元格高度
|
||||
private int cellWidth; // 单元格宽度
|
||||
|
||||
private OnSelectDateListener onSelectDateListener; // 单元格点击回调事件
|
||||
private Context context;// 上下文
|
||||
private CalendarAttr calendarAttr;// 日历属性
|
||||
private CalendarRenderer renderer;// 日历渲染器
|
||||
|
||||
private OnAdapterSelectListener onAdapterSelectListener;// 适配器选择监听器
|
||||
private float touchSlop; // 触摸阈值
|
||||
private float posX = 0;// 点击位置X坐标
|
||||
private float posY = 0;// 点击位置Y坐标
|
||||
// 构造函数
|
||||
public Calendar(Context context,
|
||||
OnSelectDateListener onSelectDateListener,
|
||||
CalendarAttr attr) {
|
||||
super(context);
|
||||
this.onSelectDateListener = onSelectDateListener;
|
||||
calendarAttr = attr;
|
||||
init(context);
|
||||
}
|
||||
// 初始化方法
|
||||
private void init(Context context) {
|
||||
this.context = context;
|
||||
touchSlop = Utils.getTouchSlop(context); // 获取触摸阈值
|
||||
initAttrAndRenderer();
|
||||
}
|
||||
// 初始化属性和渲染器
|
||||
private void initAttrAndRenderer() {
|
||||
renderer = new CalendarRenderer(this, calendarAttr, context);
|
||||
renderer.setOnSelectDateListener(onSelectDateListener);
|
||||
}
|
||||
// 绘制方法
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
renderer.draw(canvas);
|
||||
}
|
||||
// 大小改变时调用
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldW, int oldH) {
|
||||
super.onSizeChanged(w, h, oldW, oldH);
|
||||
cellHeight = h / Const.TOTAL_ROW;// 计算单元格高度
|
||||
cellWidth = w / Const.TOTAL_COL;// 计算单元格宽度
|
||||
calendarAttr.setCellHeight(cellHeight);
|
||||
calendarAttr.setCellWidth(cellWidth);
|
||||
renderer.setAttr(calendarAttr);
|
||||
}
|
||||
|
||||
/*
|
||||
* 触摸事件为了确定点击的位置日期
|
||||
*/
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
posX = event.getX();
|
||||
posY = event.getY();
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
float disX = event.getX() - posX;
|
||||
float disY = event.getY() - posY;
|
||||
if (Math.abs(disX) < touchSlop && Math.abs(disY) < touchSlop) {
|
||||
int col = (int) (posX / cellWidth);// 计算列索引
|
||||
int row = (int) (posY / cellHeight);// 计算行索引
|
||||
onAdapterSelectListener.cancelSelectState();
|
||||
renderer.onClickDate(col, row);// 调用渲染器处理点击事件
|
||||
onAdapterSelectListener.updateSelectState();
|
||||
invalidate();
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 获取日历类型
|
||||
public CalendarAttr.CalendarType getCalendarType() {
|
||||
return calendarAttr.getCalendarType();
|
||||
}
|
||||
// 切换日历类型
|
||||
public void switchCalendarType(CalendarAttr.CalendarType calendarType) {
|
||||
calendarAttr.setCalendarType(calendarType);
|
||||
renderer.setAttr(calendarAttr);
|
||||
}
|
||||
// 获取单元格高度
|
||||
public int getCellHeight() {
|
||||
return cellHeight;
|
||||
}
|
||||
// 重置选中的行索引
|
||||
public void resetSelectedRowIndex() {
|
||||
renderer.resetSelectedRowIndex();
|
||||
}
|
||||
// 获取选中的行索引
|
||||
public int getSelectedRowIndex() {
|
||||
return renderer.getSelectedRowIndex();
|
||||
}
|
||||
// 设置选中的行索引
|
||||
public void setSelectedRowIndex(int selectedRowIndex) {
|
||||
renderer.setSelectedRowIndex(selectedRowIndex);
|
||||
}
|
||||
// 设置适配器选择监听器
|
||||
public void setOnAdapterSelectListener(OnAdapterSelectListener onAdapterSelectListener) {
|
||||
this.onAdapterSelectListener = onAdapterSelectListener;
|
||||
}
|
||||
// 显示指定日期
|
||||
public void showDate(CalendarDate current) {
|
||||
renderer.showDate(current);
|
||||
}
|
||||
// 更新星期数
|
||||
public void updateWeek(int rowCount) {
|
||||
renderer.updateWeek(rowCount);
|
||||
invalidate();
|
||||
}
|
||||
// 更新日历
|
||||
public void update() {
|
||||
renderer.update();
|
||||
}
|
||||
// 取消选中状态
|
||||
public void cancelSelectState() {
|
||||
renderer.cancelSelectState();
|
||||
}
|
||||
// 获取种子日期
|
||||
public CalendarDate getSeedDate() {
|
||||
return renderer.getSeedDate();
|
||||
}
|
||||
// 设置日期渲染器
|
||||
public void setDayRenderer(IDayRenderer dayRenderer) {
|
||||
renderer.setDayRenderer(dayRenderer);
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package com.ldf.calendar.view;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import com.ldf.calendar.component.State;
|
||||
import com.ldf.calendar.model.CalendarDate;
|
||||
|
||||
/**
|
||||
* 表示日历中的某一天的状态和位置信息的类
|
||||
*/
|
||||
|
||||
public class Day implements Parcelable {
|
||||
public static final Parcelable.Creator<Day> CREATOR = new Parcelable.Creator<Day>() {
|
||||
@Override
|
||||
public Day createFromParcel(Parcel source) {
|
||||
return new Day(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Day[] newArray(int size) {
|
||||
return new Day[size];
|
||||
}
|
||||
};
|
||||
private State state;// 日期的状态
|
||||
private CalendarDate date;// 日期信息
|
||||
private int posRow;// 在日历中的行位置
|
||||
private int posCol;// 在日历中的列位置
|
||||
// 构造方法
|
||||
public Day(State state, CalendarDate date, int posRow, int posCol) {
|
||||
this.state = state;
|
||||
this.date = date;
|
||||
this.posRow = posRow;
|
||||
this.posCol = posCol;
|
||||
}
|
||||
// 从Parcel对象中读取数据以恢复Day对象的状态的构造方法
|
||||
protected Day(Parcel in) {
|
||||
int tmpState = in.readInt();
|
||||
this.state = tmpState == -1 ? null : State.values()[tmpState];
|
||||
this.date = (CalendarDate) in.readSerializable();
|
||||
this.posRow = in.readInt();
|
||||
this.posCol = in.readInt();
|
||||
}
|
||||
//获取和设置日期的状态、日期的信息,行列位置
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
public CalendarDate getDate() {
|
||||
return date;
|
||||
}
|
||||
public void setDate(CalendarDate date) {
|
||||
this.date = date;
|
||||
}
|
||||
public int getPosRow() {
|
||||
return posRow;
|
||||
}
|
||||
public void setPosRow(int posRow) {
|
||||
this.posRow = posRow;
|
||||
}
|
||||
public int getPosCol() {
|
||||
return posCol;
|
||||
}
|
||||
public void setPosCol(int posCol) {
|
||||
this.posCol = posCol;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.state == null ? -1 : this.state.ordinal());
|
||||
dest.writeSerializable(this.date);
|
||||
dest.writeInt(this.posRow);
|
||||
dest.writeInt(this.posCol);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.shihoo.daemon" >
|
||||
|
||||
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
||||
|
||||
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
>
|
||||
<receiver
|
||||
android:name="com.shihoo.daemon.WakeUpReceiver"
|
||||
android:process=":watch">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.USER_PRESENT"/>
|
||||
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
|
||||
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:name="com.shihoo.daemon.AbsWorkService$WorkNotificationService"/>
|
||||
|
||||
<!-- 广播接收者 receiver 进程-->
|
||||
<receiver
|
||||
android:name="com.shihoo.daemon.WakeUpReceiver$WakeUpAutoStartReceiver"
|
||||
android:process=":receiver">
|
||||
<!-- 手机启动 -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
|
||||
</intent-filter>
|
||||
<!-- 软件安装卸载-->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.PACKAGE_ADDED"/>
|
||||
<action android:name="android.intent.action.PACKAGE_REMOVED"/>
|
||||
<data android:scheme="package"/>
|
||||
</intent-filter>
|
||||
<!-- 网络监听 -->
|
||||
<intent-filter>
|
||||
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/>
|
||||
<action android:name="android.net.wifi.WIFI_STATE_CJANGED"/>
|
||||
<action android:name="android.net.wifi.STATE_CHANGE"/>
|
||||
</intent-filter>
|
||||
<!-- 文件挂载 -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MEDIA_EJECT"/>
|
||||
<action android:name="android.intent.action.MEDIA_MOUNTED"/>
|
||||
<data android:scheme="file"/>
|
||||
</intent-filter>
|
||||
|
||||
</receiver>
|
||||
|
||||
|
||||
|
||||
<!-- 守护进程 watch -->
|
||||
<service
|
||||
android:name="com.shihoo.daemon.JobSchedulerService"
|
||||
android:permission="android.permission.BIND_JOB_SERVICE"
|
||||
android:enabled="true"
|
||||
android:exported="true"
|
||||
android:process=":watch"/>
|
||||
|
||||
<service
|
||||
android:name="com.shihoo.daemon.WatchDogService"
|
||||
android:process=":watch"/>
|
||||
|
||||
<service
|
||||
android:name="com.shihoo.daemon.WatchDogService$WatchDogNotificationService"
|
||||
android:process=":watch"/>
|
||||
|
||||
<activity
|
||||
android:name="com.shihoo.daemon.singlepixel.SinglePixelActivity"
|
||||
android:configChanges="keyboardHidden|orientation|screenSize|navigation|keyboard"
|
||||
android:excludeFromRecents="true"
|
||||
android:finishOnTaskLaunch="false"
|
||||
android:launchMode="singleInstance"
|
||||
android:theme="@style/SingleActivityStyle"
|
||||
android:process=":watch"/>
|
||||
|
||||
<service android:name=".PlayMusicService"
|
||||
android:process=":watch"/>
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
@ -0,0 +1,32 @@
|
||||
package com.shihoo.daemon;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
|
||||
// 抽象类,用于定义服务连接的行为
|
||||
abstract class AbsServiceConnection implements ServiceConnection {
|
||||
|
||||
// 当前绑定的状态
|
||||
boolean mConnectedState = false;
|
||||
|
||||
// 当服务成功连接时调用
|
||||
@Override
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mConnectedState = true;
|
||||
}
|
||||
// 当服务断开连接时调用
|
||||
@Override
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mConnectedState = false;
|
||||
onDisconnected(name);
|
||||
}
|
||||
|
||||
// 当绑定的服务死掉时调用,此时视为服务断开连接
|
||||
@Override
|
||||
public void onBindingDied(ComponentName name) {
|
||||
onServiceDisconnected(name);
|
||||
}
|
||||
// 子类必须实现的方法,用于处理服务断开连接的逻辑
|
||||
public abstract void onDisconnected(ComponentName name);
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package com.shihoo.daemon;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Created by shihoo ON 2018/12/13.
|
||||
* Email shihu.wang@bodyplus.cc 451082005@qq.com
|
||||
*
|
||||
* 后台播放无声音乐
|
||||
*/
|
||||
public class PlayMusicService extends Service {
|
||||
|
||||
private boolean mNeedStop = false; //控制是否播放音频
|
||||
private MediaPlayer mMediaPlayer;
|
||||
private StopBroadcastReceiver stopBroadcastReceiver;
|
||||
|
||||
// private IBinder mIBinder;
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
// return mIBinder;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
// mIBinder = new Messenger(new Handler()).getBinder();
|
||||
|
||||
startRegisterReceiver();
|
||||
mMediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.no_notice);
|
||||
mMediaPlayer.setLooping(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
startPlayMusic();
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
private void startPlayMusic(){
|
||||
if (mMediaPlayer!=null && !mMediaPlayer.isPlaying() && !mNeedStop) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Log.d("wsh-daemon", "开始后台播放音乐");
|
||||
mMediaPlayer.start();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
private void stopPlayMusic() {
|
||||
if (mMediaPlayer != null) {
|
||||
Log.d("wsh-daemon", "关闭后台播放音乐");
|
||||
mMediaPlayer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
stopPlayMusic();
|
||||
Log.d("wsh-daemon", "----> stopPlayMusic ,停止服务");
|
||||
// 重启自己
|
||||
if (!mNeedStop) {
|
||||
Log.d("wsh-daemon", "----> PlayMusic ,重启服务");
|
||||
Intent intent = new Intent(getApplicationContext(), PlayMusicService.class);
|
||||
if (Build.VERSION.SDK_INT>Build.VERSION_CODES.O)startForegroundService(intent);
|
||||
else startService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void startRegisterReceiver(){
|
||||
if (stopBroadcastReceiver == null){
|
||||
stopBroadcastReceiver = new StopBroadcastReceiver();
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(DaemonEnv.ACTION_CANCEL_JOB_ALARM_SUB);
|
||||
registerReceiver(stopBroadcastReceiver,intentFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private void startUnRegisterReceiver(){
|
||||
if (stopBroadcastReceiver != null){
|
||||
unregisterReceiver(stopBroadcastReceiver);
|
||||
stopBroadcastReceiver = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止自己
|
||||
*/
|
||||
private void stopService(){
|
||||
mNeedStop = true;
|
||||
startUnRegisterReceiver();
|
||||
stopSelf();
|
||||
}
|
||||
|
||||
class StopBroadcastReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
stopService();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package com.shihoo.daemon;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* WakeUpReceiver 是用于接收系统唤醒广播的接收器类。
|
||||
*/
|
||||
public class WakeUpReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
// 当接收到系统唤醒广播时,启动 WatchDogService 服务
|
||||
DaemonEnv.startServiceSafely(context, WatchDogService.class,
|
||||
!WatchProcessPrefHelper.getIsStartDaemon(context));
|
||||
}
|
||||
|
||||
/**
|
||||
* WakeUpAutoStartReceiver 用于在应用启动时检查是否需要启动守护服务的接收器类。
|
||||
*/
|
||||
public static class WakeUpAutoStartReceiver extends BroadcastReceiver {
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
// 在应用启动时检查是否需要启动守护服务,并启动 WatchDogService 服务
|
||||
DaemonEnv.startServiceSafely(context, WatchDogService.class,
|
||||
!WatchProcessPrefHelper.getIsStartDaemon(context));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
package com.shihoo.daemon.sync;
|
||||
|
||||
import android.accounts.AbstractAccountAuthenticator;
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountAuthenticatorResponse;
|
||||
import android.accounts.AccountManager;
|
||||
import android.accounts.NetworkErrorException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class Authenticator extends AbstractAccountAuthenticator {
|
||||
|
||||
final Context context;
|
||||
|
||||
public Authenticator(Context context) {
|
||||
super(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
// 添加账户
|
||||
@Override
|
||||
public Bundle addAccount(AccountAuthenticatorResponse response,
|
||||
String accountType, String authTokenType,
|
||||
String[] requiredFeatures, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE,
|
||||
response);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelable(AccountManager.KEY_INTENT, intent);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
// 确认凭据
|
||||
@Override
|
||||
public Bundle confirmCredentials(AccountAuthenticatorResponse response,
|
||||
Account account, Bundle options) throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 编辑属性
|
||||
@Override
|
||||
public Bundle editProperties(AccountAuthenticatorResponse response,
|
||||
String accountType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取访问令牌
|
||||
@Override
|
||||
public Bundle getAuthToken(AccountAuthenticatorResponse response,
|
||||
Account account, String authTokenType, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取访问令牌标签
|
||||
@Override
|
||||
public String getAuthTokenLabel(String authTokenType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 是否具有指定特性
|
||||
@Override
|
||||
public Bundle hasFeatures(AccountAuthenticatorResponse response,
|
||||
Account account, String[] features)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 更新凭据
|
||||
@Override
|
||||
public Bundle updateCredentials(AccountAuthenticatorResponse response,
|
||||
Account account, String authTokenType, Bundle options)
|
||||
throws NetworkErrorException {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.shihoo.daemon.sync;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class SyncService extends Service {
|
||||
// 静态的同步适配器对象
|
||||
private static SyncAdapter sSyncAdapter = null;
|
||||
// 同步锁对象
|
||||
private static final Object sSyncAdapterLock = new Object();
|
||||
|
||||
public SyncService() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
synchronized (sSyncAdapterLock) {
|
||||
// 在服务创建时,实例化同步适配器对象并进行同步操作
|
||||
sSyncAdapter = new SyncAdapter(getApplicationContext(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
// 返回同步适配器的 Binder 对象
|
||||
return sSyncAdapter.getSyncAdapterBinder();
|
||||
}
|
||||
}
|
Binary file not shown.
@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">deamon</string>
|
||||
</resources>
|
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="SingleActivityStyle" parent="android:Theme.Holo.Light.NoActionBar">
|
||||
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<item name="android:windowFrame">@null</item>
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowIsFloating">true</item>
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<item name="android:backgroundDimEnabled">false</item>
|
||||
<item name="android:windowAnimationStyle">@null</item>
|
||||
<item name="android:windowDisablePreview">true</item>
|
||||
<item name="android:windowNoDisplay">false</item>
|
||||
|
||||
</style>
|
||||
</resources>
|
Loading…
Reference in new issue