package com.lfk.justwetools.View.ClassTable;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import com.lfk.justwetools.R;
import java.util.ArrayList;
import java.util.Arrays;
/**
* 课程表组合控件
* Created by liufengkai on 16/5/21.
*/
public class ClassTableView extends FrameLayout implements View.OnTouchListener, View.OnClickListener {
private Context context;
private RelativeLayout classTableRelative;
// 整体的横向控制
private HorizontalScrollView classTableHorScroll;
// 课表
private ScrollView classTableScroll;
// 上方时间线
private HorizonWeekScrollView classTableWeek;
// 存放横行按钮的容器
private LinearLayout classWeekLineLinear;
private View[] classWeekLineItem = new View[7];
// 存放纵行时间容器
private LinearLayout classTimeLineLinear;
// 纵行时间的数据
private ArrayList<ClassTimeLine> classTimeLines;
// 纵行复用Item
private View[] classTimeLineView = new View[12];
// 填充
private RelativeLayout classTable;
// 切换日期的布局
private LinearLayout.LayoutParams defaultWeekLine = null;
private LinearLayout.LayoutParams defaultCurWeekLine = null;
// 课程信息
private ArrayList<ClassInfo> classInfoList;
// 按钮块信息
private ArrayList<BlockInfo> classButtonList;
// 判断位置
private float x_temp1;
private float x_temp2;
private float pre_x, pre_y;
// 当前周数
private static int selectedWeek;
// 点击事件接口
private ClassTableOnClick classTableOnClick = null;
private ClassTableOnLongClick classTableOnLongClick = null;
// 判断时间
private long downTime;
private long upTime;
private View bashLineView;
public ClassTableView(Context context) {
super(context);
this.context = context;
init();
}
public ClassTableView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init();
}
private void init() {
LayoutInflater.from(context).inflate(R.layout.class_table, this);
initData();
initView();
}
private void initData() {
pre_x = 0;
pre_y = 0;
classInfoList = new ArrayList<>();
classButtonList = new ArrayList<>();
}
private void initView() {
ClassTableDefaultInfo.init(context);
classTableRelative = (RelativeLayout) findViewById(R.id.class_table_info);
classTableRelative.setBackgroundColor(Color.parseColor(ClassTableDefaultInfo.classTableColor));
classTableHorScroll = (HorizontalScrollView) findViewById(R.id.class_table_horizon_scroller);
classTableScroll = (ScrollView) findViewById(R.id.class_table_scroller);
classTableScroll.setBackgroundColor(Color.parseColor(ClassTableDefaultInfo.classTableTimeLineColor));
classTableWeek = (HorizonWeekScrollView) findViewById(R.id.class_table_week);
classTableWeek.setBackgroundColor(Color.parseColor(ClassTableDefaultInfo.classTableWeekColor));
classTimeLineLinear = (LinearLayout) findViewById(R.id.class_timeline_linear);
classTimeLineLinear.setBackgroundColor(Color.parseColor(ClassTableDefaultInfo.classTableTimeLineLinearColor));
classWeekLineLinear = (LinearLayout) findViewById(R.id.class_week_linear);
classTable = (RelativeLayout) findViewById(R.id.class_table_table);
classTableWeek.setOnTouchListener(this);
classTableScroll.setOnTouchListener(this);
classTableHorScroll.setOnTouchListener(this);
// 初始化课程表的布局
LinearLayout.LayoutParams params_relative_week_table =
(LinearLayout.LayoutParams) classTable
.getLayoutParams();
params_relative_week_table.width = ClassTableDefaultInfo.classTableWidth;
params_relative_week_table.height = ClassTableDefaultInfo.classTableHeight;
classTable.setLayoutParams(params_relative_week_table);
initClassLine();
initWeekLine();
initBashLine();
// 加载课表
addClass("刘丰恺哈哈哈", ClassUtils.ClassDay.Friday, ClassUtils.ClassTime.N2Class);
addClassOnTable(ClassTableDefaultInfo.curWeekNum);
}
/**
* 初始化横行列表
*/
private void initWeekLine() {
int month = ClassTableDefaultInfo.nowMonth;
int day = ClassTableDefaultInfo.nowDay;
int week = ClassTableDefaultInfo.nowWeek;
selectedWeek = week;
String date = month + "-" + day;
for (int i = 1; i <= 7; i++) {
View view = getClassWeekItem(null, date, week, i);
classWeekLineLinear.addView(view);
classWeekLineItem[i - 1] = view;
ClassWeekHolder holder = (ClassWeekHolder) view.getTag();
ViewGroup.LayoutParams lp = view.getLayoutParams();
// 添加到View之后设置样式
if (i == selectedWeek) {
lp.width = ClassTableDefaultInfo.defaultCurWeekTimeLineWidth;
holder.wtf.setVisibility(View.VISIBLE);
holder.wtf.setBackgroundColor(Color.parseColor(ClassTableDefaultInfo.defaultCurBackground));
if (defaultCurWeekLine == null)
defaultCurWeekLine = new LinearLayout.LayoutParams(lp);
} else {
lp.width = ClassTableDefaultInfo.defaultWeekTimeLineWidth;
if (defaultWeekLine == null)
defaultWeekLine = new LinearLayout.LayoutParams(lp);
}
}
}
private void initBashLine() {
// 11条虚线
for (int i = 1; i <= 11; i++) {
View bashLine = new View(context);
bashLine.setBackgroundResource(R.drawable.bash_line_shape);
bashLine.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
params.width = ClassTableDefaultInfo.classTableWidth;
params.height = DensityUtil.dip2px(context, 2);
params.setMargins(0, (DensityUtil.dip2px(context,
ClassTableDefaultInfo.defaultTimeHeight
+ ClassTableDefaultInfo.defaultTimeLineMarginTopWidth) * i)
- params.height / 2, 0, 0);
bashLine.setLayoutParams(params);
classTable.addView(bashLine);
}
}
/**
* 初始化纵向列表数据
* 添加TimeLine对象
*/
private void initClassLine() {
classTimeLines = new ArrayList<>();
ClassTimeLine[] line = {new ClassTimeLine(ClassUtils.getHtmlParseTime("8:00", 1)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("8:50", 2)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("10:05", 3)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("10:55", 4)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("13:30", 5)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("14:20", 6)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("15:35", 7)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("16:25", 8)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("18:00", 9)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("18:55", 10)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("19:50", 11)),
new ClassTimeLine(ClassUtils.getHtmlParseTime("20:45", 12))};
classTimeLines.addAll(Arrays.asList(line));
for (int i = 0; i < 12; i++) {
View view = getClassTimeLineItem(null, i);
classTimeLineLinear.addView(view);
classTimeLineView[i] = view;
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) view.getLayoutParams();
lp.topMargin = DensityUtil.dip2px(context, ClassTableDefaultInfo.defaultTimeLineMarginTopWidth);
}
}
/**
* 使用ViewHolder创建横向周列表
*
* @param v 复用组件
* @param date 日期
* @param week 周
* @param position 周几?
* @return WeekLine
*/
private View getClassWeekItem(View v, String date, int week, int position) {
ClassWeekHolder holder;
holder = new ClassWeekHolder();
v = LayoutInflater.from(context).inflate(R.layout.class_week_item, null);
holder.classWeek = (TextView) v.findViewById(R.id.class_week_text);
holder.wtf = v.findViewById(R.id.class_week_line);
holder.classWeek.setText(ClassUtils.getHtmlParseTitle(date, week, position));
holder.classWeek.setTag(ClassUtils.getClassDay(position));
v.setOnClickListener(this);
holder.wtf.setVisibility(View.INVISIBLE);
v.setTag(holder);
return v;
}
/**
* 使用ViewHolder制作的TimeLine
*
* @param v 复用TimeLine
* @param position 位置
* @return 当前位置的控件
*/
private View getClassTimeLineItem(View v, int position) {
ClassTimeLineHolder holder;
holder = new ClassTimeLineHolder();
v = LayoutInflater.from(context).inflate(R.layout.class_timeline_item, null);
holder.classTime = (TextView) v.findViewById(R.id.class_timeline_item);
v.setTag(holder);
ClassTimeLine line = classTimeLines.get(position);
holder.classTime.setText(line.timeline);
return v;
}
/**
* 添加View
*
* @param recentClass 当前课程
*/
private void addViewForTable(ClassInfo recentClass, final int id) {
// 当前是周几 / 不要误会了
int curWeek = ClassTableDefaultInfo.nowWeek;
// 多少节
int counts = recentClass.getClassEndTime() - recentClass.getClassStartTime();
// 计算高度
int height = ClassTableDefaultInfo.courseHeight * counts;
// 这课周几上啊?
int classWeek = recentClass.getClassWeek();
// 控件宽度
int width = classWeek == curWeek
? ClassTableDefaultInfo.defaultCurWeekTimeLineWidth
: ClassTableDefaultInfo.defaultWeekTimeLineWidth;
int marginLeft = classWeek > curWeek
? ClassTableDefaultInfo.defaultWeekTimeLineWidth * (classWeek - 2) + ClassTableDefaultInfo.defaultCurWeekTimeLineWidth
: ClassTableDefaultInfo.defaultWeekTimeLineWidth * (classWeek - 1);
int marginTop = ClassTableDefaultInfo.courseHeight * (recentClass.getClassStartTime() - 1);
// 创建view
int padding = DensityUtil.dip2px(context, ClassTableDefaultInfo.defaultClassTableItemPadding);
int textSize = classWeek == curWeek
? ClassTableDefaultInfo.courseCurTextSize
: ClassTableDefaultInfo.courseTextSize;
Button btForCourse = new Button(context);
btForCourse.setTag(classWeek);
btForCourse.setId(id);
btForCourse.setMaxLines(6);
btForCourse.setGravity(Gravity.LEFT);
// 设定文字
String content = recentClass.getClassName() + "\n@" + recentClass.getClassLocation();
btForCourse.setText(content);
btForCourse.setTextColor(Color.WHITE);
if (recentClass.getBackgroundColor() != 0)
btForCourse.setBackgroundColor(recentClass.getBackgroundColor());
btForCourse.setPadding(padding, padding, padding, padding);
btForCourse.setTextSize(textSize);
// 设置参数
RelativeLayout.LayoutParams btParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
btParams.width = width;
btParams.height = height;
btParams.setMargins(marginLeft, marginTop, 0, 0);
// 将view放到课表中
classTable.addView(btForCourse, btParams);
BlockInfo.BlockInfoBuilder builder = new BlockInfo.BlockInfoBuilder();
builder.addButton(btForCourse)
.addMarginTop(marginTop)
.addClassInfo(recentClass);
// 添加块
classButtonList.add(builder.creator());
}
/**
* 添加课程
*
* @param weekNum 当前的周目
*/
public void addClassOnTable(int weekNum) {
for (int i = 0; i < classInfoList.size(); i++) {
// 拿到对应课程信息
if (classInfoList.get(i).getStartWeek() <= weekNum
&& classInfoList.get(i).getEndWeek() >= weekNum) {
addViewForTable(classInfoList.get(i), i);
}
}
}
@Override
public boolean onTouch(View v, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downTime = System.currentTimeMillis();
x_temp1 = x;
break;
case MotionEvent.ACTION_UP:
pre_x = classTableHorScroll.getScrollX();
pre_y = classTableScroll.getScrollY();
upTime = System.currentTimeMillis();
// 条件成立,单击事件发生
if (upTime - downTime < 100) {
// 发声音
v.playSoundEffect(SoundEffectConstants.CLICK);
setCourseOnClick(x + pre_x, y + pre_y, TouchMode.Click);
// 长按
} else if (upTime - downTime > 400) {
setCourseOnClick(x + pre_x, y + pre_y, TouchMode.LongClick);
}
break;
case MotionEvent.ACTION_MOVE:
x_temp2 = x;
//当出现移动事件的时候只处理课程表的
if (v.getId() == R.id.class_table_scroller) {
classTableHorScroll.smoothScrollTo((int) (pre_x - (x_temp2 - x_temp1)), 0);
classTableWeek.smoothScrollTo((int) (pre_x - (x_temp2 - x_temp1)), 0);
}
break;
case MotionEvent.ACTION_CANCEL:
pre_x = classTableHorScroll.getScrollX();
break;
default:
break;
}
return false;
}
/**
* 进行课程表Item的点击事件
*
* @param x x
* @param y y
* @param mode 模式{Click,LongClick}
*/
private void setCourseOnClick(float x, float y, TouchMode mode) {
for (int i = 0; i < classButtonList.size(); i++) {
BlockInfo info = classButtonList.get(i);
if (contains(info.getBlockButton(), (int) x,
(int) y)) {
if (mode == TouchMode.Click && classTableOnClick != null)
classTableOnClick.onClick(info.getBlockButton(), info);
else if (mode == TouchMode.LongClick && classTableOnLongClick != null) {
classTableOnLongClick.onLongClick(info.getBlockButton(), info);
}
}
}
}
/**
* 设定当前位置 横向滚动条
* 变宽啊,变色啊什么的
*
* @param position 周几?
*/
private void setCurWeekPosition(int position) {
for (int i = 1; i <= classWeekLineItem.length; i++) {
View view = classWeekLineItem[i - 1];
ClassWeekHolder holder = (ClassWeekHolder) view.getTag();
if (i == position) {
view.setLayoutParams(defaultCurWeekLine);
holder.wtf.setVisibility(View.VISIBLE);
} else {
view.setLayoutParams(defaultWeekLine);
holder.wtf.setVisibility(View.INVISIBLE);
}
}
}
/**
* 判断点击事件
*
* @param button 拿到按钮
* @param x 点击的X
* @param y 点击的Y
* @return 是否成功点击
*/
private boolean contains(Button button, int x, int y) {
int offset = ClassTableDefaultInfo.timeLineWidth;
int left = button.getLeft() + offset;
int right = left + button.getWidth();
int top = button.getTop();
int bottom = top + button.getHeight();
return left < right && top < bottom // check for empty first
&& x >= left && x < right && y >= top && y < bottom;
}
/**
* 刷新课标
*/
public void refreshClassTable() {
classButtonList.clear();
addClassOnTable(ClassTableDefaultInfo.curWeekNum);
}
/**
* 刷新课程表
*
* @param weekNum 第几周
*/
public void refreshClassTableWithWeek(int weekNum) {
classButtonList.clear();
addClassOnTable(weekNum);
}
/**
* 动态刷新课表的样式
* 刷新当前课表
*
* @param position 拿到的是点击的当前列
*/
private void setCurTablePosition(int position) {
if (classButtonList.size() > 0) {
for (int i = 0; i < classButtonList.size(); i++) {
BlockInfo info = classButtonList.get(i);
RelativeLayout.LayoutParams btParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
btParams.height = info.getBlockButton().getHeight();
int marginLeft = info.getBlockInfo().getClassWeek() > position
? ClassTableDefaultInfo.defaultWeekTimeLineWidth
* (info.getBlockInfo().getClassWeek() - 2) + ClassTableDefaultInfo.defaultCurWeekTimeLineWidth
: ClassTableDefaultInfo.defaultWeekTimeLineWidth * (info.getBlockInfo().getClassWeek() - 1);
btParams.setMargins(marginLeft, classButtonList.get(i).getMarginTop(), 0, 0);
if (info.getBlockInfo().getClassWeek() == position) {
info.getBlockButton().setWidth(ClassTableDefaultInfo.defaultCurWeekTimeLineWidth);
info.getBlockButton().setTextSize(ClassTableDefaultInfo.courseCurTextSize);
btParams.width = ClassTableDefaultInfo.defaultCurWeekTimeLineWidth;
} else {
info.getBlockButton().setWidth(ClassTableDefaultInfo.defaultWeekTimeLineWidth);
info.getBlockButton().setTextSize(ClassTableDefaultInfo.courseTextSize);
btParams.width = ClassTableDefaultInfo.defaultWeekTimeLineWidth;
}
info.getBlockButton().setLayoutParams(btParams);
}
}
}
/**
* 便携添加函数
*
* @param className 课程名
* @param day 哪天?
* @param time 课程时间 默认单节
*/
public void addClass(String className,
ClassUtils.ClassDay day,
ClassUtils.ClassTime time) {
addClass(className, ClassTableDefaultInfo.curWeekNum,
ClassTableDefaultInfo.curWeekNum,
day, time, ClassUtils.getClassTime(time.value + 1));
}
/**
* 便携添加函数
*
* @param className 课程名
* @param weekFrom 从第几周开始
* @param weekTo 到第几周
* @param day 哪天
* @param from 从第几节
* @param to 到第几节
*/
public void addClass(String className,
int weekFrom, int weekTo,
ClassUtils.ClassDay day,
ClassUtils.ClassTime from,
ClassUtils.ClassTime to) {
addClass(className, weekFrom, weekTo, day, from, to, "", "");
}
/**
* 通过课程信息进行添加课程
*
* @param info 课程信息 通过Builder进行初始化
*/
public void addClass(ClassInfo info) {
classInfoList.add(info);
}
/**
* 添加一门课可能是最长的构造函数
*
* @param className 课程名
* @param weekFrom 从第几周开始
* @param weekTo 到第几周
* @param day 那天上课?
* @param from 第几节?
* @param to 到第几节?
* @param content 课的内容
* @param color 颜色?
*/
public void addClass(String className,
int weekFrom,
int weekTo,
ClassUtils.ClassDay day,
ClassUtils.ClassTime from,
ClassUtils.ClassTime to,
String content,
String color) {
ClassInfo.ClassBuilder builder = new ClassInfo.ClassBuilder();
if (color.equals("")) color = ClassTableDefaultInfo.defaultCurBackground;
builder.addBackgroundColor(Color.parseColor(color))
.addClassEndTime(to.value)
.addClassStartTime(from.value)
.addClassName(className)
.addStartWeek(weekFrom)
.addEndWeek(weekTo)
.addClassWeek(day.value)
.addContent(content);
addClass(builder.creator());
}
/**
* 设置课程表Item的点击事件
*
* @param classTableOnClick 点击事件的接口
*/
public void setClassTableOnClick(ClassTableOnClick classTableOnClick) {
this.classTableOnClick = classTableOnClick;
}
/**
* 设置课程表的Item的长按事件
*
* @param classTableOnLongClick 长按时间的接口
*/
public void setClassTableOnLongClick(ClassTableOnLongClick classTableOnLongClick) {
this.classTableOnLongClick = classTableOnLongClick;
}
/**
* 点击事件 是课程表选择周几的点击事件
*
* @param v WeekView
*/
@Override
public void onClick(View v) {
int value = ((ClassUtils.ClassDay)
(((ClassWeekHolder) v.getTag())
.classWeek.getTag())).value;
setCurWeekPosition(value);
setCurTablePosition(value);
selectedWeek = value;
}
}