-
Notifications
You must be signed in to change notification settings - Fork 106
v2.0.1文档
本文中的功能介绍、控件用法均针对
v2.0.0
以及v2.0.1
,它并不是最新的,你可以在 ChangeLog 查看本控件的开发进展,作者联系方式1193600556@qq.com
TimetableView是一款开源的Android课程表控件。
- 支持xml设置属性、数据源
- 提供了默认的周次选择栏(超级课程表效果),支持自定义
- 提供了默认的日期栏,支持自定义
- 多项侧边栏配置项,可设置时间的显示与否,支持自定义
- 多项课程项配置项,可拦截、可修改弧度、可设置非本周是否显示
- 课程颜色管理:使用颜色池来管理颜色,操作灵活
- 高效灵活:切换周次高效率、一个样式文件实现了多种课程项样式效果
- 可替换滚动布局:不将该控件绑死在固有的ScrollView中
- 无界面操作:你可以使用工具类对课程进行模拟分配颜色、获取有课的课程等
在开始使用控件之前,你需要准备好数据源,数据可以从网上获取或者使用本地数据,为了方便演示,使用本地的JSON字符串,然后再将其解析为需要的格式
本节你将掌握如何使用本控件搭建自己的课表界面。这里使用的版本为
2.0.1
Gradle
compile 'com.zhuangfei:TimetableView:2.0.1'
Maven
<dependency>
<groupId>com.zhuangfei</groupId>
<artifactId>TimetableView</artifactId>
<version>2.0.1</version>
<type>pom</type>
</dependency>
该控件包含的基础组件有日期栏、侧边栏、课表视图,在布局文件中加入如下代码后会包含这三个基础组件
<com.zhuangfei.timetable.TimetableView
android:id="@+id/id_timetableView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.zhuangfei.timetable.TimetableView>
使用如下方式获取到控件
TimetableView mTimetableView = findViewById(R.id.id_timetableView);
属性的设置分为两类:与课程项构建有关的、与全局有关的,前者的配置在ScheduleManager
对象中,后者的配置在TimetableView
中,所有配置信息需要在showView()
调用前完成,否则无效
以下代码用来监听课程项点击事件:
mTimetableView.getScheduleManager()
.setOnItemClickListener(new ISchedule.OnItemClickListener() {
@Override
public void onItemClick(View v, List<Schedule> scheduleList) {
display(scheduleList);
}
});
然后设置它的一些全局属性,最后调用showView()
用来创建和显示课表视图,代码如下:
mTimetableView.setSource(mySubjects)
.setCurWeek(1)
.setCurTerm("大三下学期")
.showView();
至此,课表已经可以显示在视图上了,你可能会问:设置数据源时mySubjects
是什么?不要着急,继续看...
数据源的设置方式有两种,以下分别来介绍:
方法1:使用指定的格式List<Schedule>
,Schedule
是控件提供的课程实体类,你可以将自己的数据封装为指定格式,然后进行如下配置即可
mTimetableView.setData(scheduleList)
.setCurWeek(1)
.setCurTerm("大三下学期")
.showView();
方法2:方法1在很多场景下都满足不了需求,往往需要定义自己的课程实体类,你可以跟随以下几个步骤来使用它
- 创建自定义的实体类并实现
ScheduleEnable
接口
public class MySubject implements ScheduleEnable {
//省略属性、setter、getter、构造函数
@Override
public Schedule getSchedule() {
Schedule schedule=new Schedule();
schedule.setDay(getDay());
schedule.setName(getName());
schedule.setRoom(getRoom());
schedule.setStart(getStart());
schedule.setStep(getStep());
schedule.setTeacher(getTeacher());
schedule.setWeekList(getWeekList());
schedule.setColorRandom(2);
return schedule;
}
}
- 使用
setSource()
设置
//模拟获取课程数据:自定义格式
List<MySubject> mySubjects = SubjectRepertory.loadDefaultSubjects();
//设置数据源并显示
mTimetableView.setSource(mySubjects)
.setCurWeek(1)
.setCurTerm("大三下学期")
.showView();
可见,上述那个例子使用的是方法2,我个人也建议使用方法2:比较灵活,可根据具体情况选择。简单几步,课表界面就可以显示出来了,是不是有点小激动呀。
/**
* 删除课程
* 内部使用集合维护课程数据,操作集合的方法来操作它即可
* 最后更新一下视图(全局更新)
*/
protected void deleteSubject() {
int size = mTimetableView.getDataSource().size();
int pos = (int) (Math.random() * size);
if (size > 0) {
mTimetableView.getDataSource().remove(pos);
mTimetableView.updateView();
}
}
/**
* 添加课程
* 内部使用集合维护课程数据,操作集合的方法来操作它即可
* 最后更新一下视图(全局更新)
*/
protected void addSubject() {
int size = mTimetableView.getDataSource().size();
if (size > 0) {
Schedule schedule = mTimetableView.getDataSource().get(0);
mTimetableView.getDataSource().add(schedule);
mTimetableView.updateView();
}
}
周次选择栏
WeekView
是控件实现的一个默认的周次选择控件,你可以使用它快速的拥有周次选择功能,TimetableView
是没有周次选择功能的,所以需要两者配合使用。 本节你将掌握使用zfman/TimetableView添加一个周次选择栏
1.添加控件
在布局文件中放一个TimetableView
,然后在TimetableView
的上边放一个WeekView
<com.zhuangfei.timetable.view.WeekView
android:id="@+id/id_weekview"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<com.zhuangfei.timetable.TimetableView
android:id="@+id/id_timetableView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.zhuangfei.timetable.TimetableView>
2.获取控件
TimetableView mTimetableView;
WeekView weekView;
//获取控件
mTimetableView = findViewById(R.id.id_timetableView);
weekView=findViewById(R.id.id_weekview);
3.设置WeekView
//设置周次选择属性
weekView.setSource(mySubjects)
.setCurWeek(1)
.setOnWeekItemClickedListener(new IWeekView.OnWeekItemClickedListener() {
@Override
public void onWeekClicked(int curWeek) {
mTimetableView.changeWeekOnly(curWeek);
}
})
.setOnWeekLeftClickedListener(new IWeekView.OnWeekLeftClickedListener() {
@Override
public void onWeekLeftClicked() {
Log.d(TAG, "onWeekLeftClicked: ");
onWeekLeftLayoutClicked();
}
})
.showView();
4.设置TimetableView
mTimetableView.setSource(mySubjects)
.setCurWeek(1)
.setCurTerm("大三下学期")
.setOnWeekChangedListener(new ISchedule.OnWeekChangedListener() {
@Override
public void onWeekChanged(int curWeek) {
int size = mTimetableView.getDataSource().size();
titleTextView.setText("第" + curWeek + "周,共" + size + "门课");
}
})
.showView();
5.更新高亮日期
由于在onCreate
中设置了WeekView,所以默认的在WeekView初始化时会计算当前日期,如果程序在后台时间太长(超一天),那么进入页面时会发现日期不正确,所以可以在Activity的onStart生命周期方法中再次计算日期,设置高亮
@Override
protected void onStart() {
super.onStart();
//更新一下,防止因程序在后台时间过长(超过一天)而导致的高亮不准确问题
//第一次调用时会出异常
try{
mTimetableView.getOnDateBuildListener().onHighLight();
}catch (Exception e){
}
}
这个没什么可说的,你只需要任意的定制即可,因为它与TimetableView
是没有任何关联的,有问题可以参考WeekView
的实现
本控件不仅支持在代码中对属性进行设置,部分属性和监听还支持在布局文件xml中配置,一起来看看吧~
以下罗列的属性或监听可以在xml中配置
<!--Some Attr with TimetableView-->
<declare-styleable name="TimetableView">
<!--当前周-->
<attr name="cur_week" format="integer"/>
<!--当前学期-->
<attr name="cur_term" format="string"/>
<!--
指定一个方法名,该方法符合以下要求:
1.返回值为一个集合
2.集合中的每个对象都实现了ScheduleEnable接口
-->
<attr name="source" format="string"/>
<!--
指定一个方法名,该方法符合以下要求:
1.返回值为List<Schedule>
-->
<attr name="data" format="string"/>
<!--课程项的上边距-->
<attr name="mar_top" format="dimension"/>
<!--左边距-->
<attr name="mar_left" format="dimension"/>
<!--课程项的高度-->
<attr name="item_height" format="dimension"/>
<!--本周课程的圆角弧度-->
<attr name="thisweek_corner" format="dimension"/>
<!--非本周课程的圆角弧度-->
<attr name="nonweek_corner" format="dimension"/>
<!--侧边栏的最大项-->
<attr name="max_slide_item" format="integer"/>
<!--是否显示非本周课程-->
<attr name="show_notcurweek" format="boolean"/>
<attr name="onWeekChanged" format="string"/>
<attr name="onItemClicked" format="string"/>
</declare-styleable>
在根节点添加一个名为app的命名空间
xmlns:app="http://schemas.android.com/apk/res-auto"
直接在xml中对属性设置
<com.zhuangfei.timetable.TimetableView
android:id="@+id/id_timetableView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cur_week="3"
app:cur_term="大三上学期"
app:show_notcurweek="false"
app:source="getSource"
app:max_slide_item="10"
app:onWeekChanged="onWeekChanged"
app:onItemClicked="onItemClicked"/>
由于大部分的属性都在xml中配置过了,所以在Activity中只负责显示即可
mTimetableView.showView();
那么数据源从哪来呢?注意到xml中指定了app:source="getSource"
,所以在Activity中需要有一个List<MySubject> getSource()
方法,控件会自动的调用该函数对数据源进行设置
/**
* 使用自己的格式设置数据源,方法名任意,但必须和xml中设置的一致
* @return
*/
public List<MySubject> getSource(){
return SubjectRepertory.loadDefaultSubjects();
}
同理,可以设置课程项点击监听
/**
* 设置点击监听
* @return
*/
public void onItemClicked(View v,ArrayList<Schedule> scheduleList){
Log.d(TAG, "onItemClicked: "+scheduleList.size());
display(scheduleList);
}
同理,可以设置周次改变监听
/**
* 监听周次改变的方法,方法名任意,但必须和xml中设置的一致
* 参数必须与示例一致
* @return
*/
public void onWeekChanged(int curWeek){
Log.d(TAG, "onWeekChanged: "+curWeek);
if(mTimetableView!=null){
int size = mTimetableView.getDataSource().size();
titleTextView.setText("第" + curWeek + "周,共" + size + "门课");
}
}
本节主要演示如何对日期栏的属性设置以及自定义日期栏的步骤
/**
* 隐藏日期栏
*/
protected void hideDateView(){
mTimetableView.hideDateView();
}
/**
* 显示日期栏
*/
protected void showDateView(){
mTimetableView.showDateView();
}
Step1:自定义布局
需要定义两个布局,第一个item_custom_dateview_first.xml
定义的月份的样式
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/id_week_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical|center_horizontal"
android:textSize="12sp"
android:textStyle="bold" />
第二个item_custom_dateview.xml
定义的是星期一至星期日的每项的样式
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/id_week_layout"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/id_week_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="12sp"
android:textStyle="bold" />
</LinearLayout>
Step2:自定义实现类
定义了类CustomDateAdapter
并实现了ISchedule.OnDateBuildListener
接口,实现三个方法:
- getDateViews(LayoutInflater mInflate,float perWidth,int height) 获取View数组,perWidth是每个单位的宽度,月份占1个单位,其余为1.5个单位
- onHighLight() 设置高亮时回调
- onUpdateDate() 更新日期时回调
以下代码有一些长,请细细品味~~
/**
* 大部分代码copy的OnDateBuildAapter
* 你可以决定是否使用该方式,如果不愿使用该方式,
* 可以隐藏日期栏,自行实现即可
* @see com.zhuangfei.timetable.listener.OnDateBuildAapter
*/
class CustomDateAdapter implements ISchedule.OnDateBuildListener {
//第一个:月份,之后7个表示周一至周日
LinearLayout[] layouts=new LinearLayout[8];
/**
* 获取View数组
* @param mInflate
* @param perWidth 每个单位的宽度,其中月份占1份,星期占1.5份
* @param height 默认的日期栏高度,可用可不用
* @return
*/
@Override
public View[] getDateViews(LayoutInflater mInflate,float perWidth,int height) {
int heightPx= ScreenUtils.dip2px(DateActivity.this,35);
View[] views=new View[8];
View first=mInflate.inflate(R.layout.item_custom_dateview_first,null,false);
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams((int) perWidth,heightPx);
layouts[0]=null;
views[0]=first;
first.setLayoutParams(lp);
//星期设置
lp=new LinearLayout.LayoutParams((int)(perWidth*1.5),heightPx);
String[] dateArray=new String[]{"","周一","周二","周三","周四","周五","周六","周日"};
for(int i=1;i<8;i++){
View v=mInflate.inflate(R.layout.item_custom_dateview,null,false);
TextView dayTextView=v.findViewById(R.id.id_week_day);
layouts[i]=v.findViewById(R.id.id_week_layout);
views[i]=v;
layouts[i].setLayoutParams(lp);
dayTextView.setText(dateArray[i]);
}
return views;
}
@Override
public void onHighLight() {
//初始化背景色
int color=Color.parseColor("#F4F8F8");
for(int i=1;i<8;i++){
layouts[i].setBackgroundColor(color);
}
//高亮
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK)-1;
if(dayOfWeek<0) dayOfWeek=7;
layouts[dayOfWeek].setBackgroundColor(Color.parseColor("#BFF6F4"));
}
@Override
public void onUpdateDate() {
}
}
Step3:设置监听
/**
* 自定义日期栏
* @see CustomDateAdapter
*/
protected void customDateView(){
mTimetableView.setOnDateBuildListener(new CustomDateAdapter());
mTimetableView.showDateView().updateDateView();
}
/**
* 恢复默认日期栏
*/
protected void cancelCustomDateView(){
mTimetableView.setOnDateBuildListener(null);
mTimetableView.showDateView().updateDateView();
}
在课程视图的左侧有一列是侧边栏,本节演示如何对侧边栏的属性进行配置以及自定义侧边栏的步骤
添加控件
<com.zhuangfei.timetable.TimetableView
android:id="@+id/id_timetableView"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.zhuangfei.timetable.TimetableView>
获取控件
mTimetableView = findViewById(R.id.id_timetableView);
List<MySubject> mySubjects = SubjectRepertory.loadDefaultSubjects();
mTimetableView.setSource(mySubjects)
.setCurWeek(1)
.showView();
/**
* 显示时间
* 设置侧边栏构建监听,TimeSlideAdapter是控件实现的可显示时间的侧边栏
* 只修改了侧边栏的属性,所以只更新侧边栏即可(性能高),没有必要更新全部(性能低)
* @see TimeSlideAdapter
*/
protected void showTime() {
String[] times = new String[]{
"8:00", "9:00", "10:10", "11:00",
"15:00", "16:00", "17:00", "18:00",
"19:30", "20:30","21:30","22:30"
};
TimeSlideAdapter slideAdapter = new TimeSlideAdapter();
slideAdapter.setTimes(times);
mTimetableView.getScheduleManager().setOnSlideBuildListener(slideAdapter);
mTimetableView.updateSlideView();
}
/**
* 隐藏时间
* 将侧边栏监听置Null后,会默认使用默认的构建方法,即不显示时间
* 只修改了侧边栏的属性,所以只更新侧边栏即可(性能高),没有必要更新全部(性能低)
*/
protected void hideTime() {
mTimetableView.getScheduleManager().setOnSlideBuildListener(null);
mTimetableView.updateSlideView();
}
/**
* 修改侧边栏背景
* 使用new的方式会覆盖掉之前设置的侧边栏的属性值
* 如果不想覆盖,可以这样:
* TimeSlideAdapter adapter= (TimeSlideAdapter) mTimetableView.getScheduleManager()
* .getOnSlideBuildListener();
* 使用该方式获取到控件的TimeSlideAdapter对象,对其设置属性即可
*
* 在类型强制类型转换之前,你应该调用过以下代码:
* TimeSlideAdapter slideAdapter = new TimeSlideAdapter();
* mTimetableView.getScheduleManager().setOnSlideBuildListener(slideAdapter);
*
* 否则在类型转换时会出现异常,请注意
*
* @param color
*/
protected void modifySlideBgColor(int color){
TimeSlideAdapter slideAdapter = new TimeSlideAdapter();
slideAdapter.setBackground(color);
mTimetableView.getScheduleManager().setOnSlideBuildListener(slideAdapter);
mTimetableView.updateSlideView();
}
/**
* 修改侧边项背景
* @param color
*/
protected void modifyItemBgColor(int color){
TimeSlideAdapter slideAdapter = new TimeSlideAdapter();
slideAdapter.setItemBackground(color);
mTimetableView.getScheduleManager().setOnSlideBuildListener(slideAdapter);
mTimetableView.updateSlideView();
}
/**
* 修改侧边栏节次文本的颜色值
* @param color
*/
protected void modifyItemTextColor(int color){
TimeSlideAdapter slideAdapter = new TimeSlideAdapter();
slideAdapter.setTextColor(color);
mTimetableView.getScheduleManager().setOnSlideBuildListener(slideAdapter);
mTimetableView.updateSlideView();
}
/**
* 修改侧边栏时间文本的颜色值
* @param color
*/
protected void modifyItemTimeColor(int color){
String[] times = new String[]{
"8:00", "9:00", "10:10", "11:00",
"15:00", "16:00", "17:00", "18:00",
"19:30", "20:30","21:30","22:30"
};
TimeSlideAdapter slideAdapter = new TimeSlideAdapter();
slideAdapter.setTimes(times).setTimeTextColor(color);
mTimetableView.getScheduleManager().setOnSlideBuildListener(slideAdapter);
mTimetableView.updateSlideView();
}
Step1:创建布局
创建一个XML文件item_custom_slide.xml
,该文件的内容可完全自定义
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:textColor="@color/app_qing2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top|center_horizontal"
android:id="@+id/item_slide_textview"/>
</LinearLayout>
Step2:设置监听
需要实现ISchedule.OnSlideBuildListener
中的三个方法:
- setBackground(LinearLayout layout) 用于设置侧边项的背景色,参数为侧边项的View
- getSlideItemSize() 返回侧边项的个数
- onBuildSlideItem() 构建侧边项的过程,返回的View是一个侧边项
重点在第三个方法上,它决定了侧边项是如何构建的
/**
* 自定义侧边栏效果
* 使用自定义的布局文件实现的文字居顶部的效果(默认居中)
*/
protected void customSlideView(){
mTimetableView.getScheduleManager()
.setOnSlideBuildListener(new ISchedule.OnSlideBuildListener() {
@Override
public void setBackground(LinearLayout layout) {
//暂时不需要关注
}
@Override
public int getSlideItemSize() {
//返回侧边栏的Size
return 12;
}
@Override
public View onBuildSlideItem(int pos, LayoutInflater inflater, int itemHeight, int marTop) {
//获取View并返回,注意设置marTop值
View v=inflater.inflate(R.layout.item_custom_slide,null,false);
TextView tv=v.findViewById(R.id.item_slide_textview);
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
itemHeight);
lp.setMargins(0,marTop,0,0);
tv.setLayoutParams(lp);
tv.setText((pos+1)+"");
return v;
}
});
mTimetableView.updateSlideView();
}
/**
* 取消自定义的侧边栏,回到默认状态
* 只需要将监听器置空即可
*/
protected void cancelCustomSlideView(){
mTimetableView.getScheduleManager().setOnSlideBuildListener(null);
mTimetableView.updateSlideView();
}
本节将演示如何配置课程项的样式
/**
* 隐藏非本周课程
* 修改了内容的显示,所以必须更新全部(性能不高)
* 建议:在初始化时设置该属性
*/
protected void hideNonThisWeek() {
mTimetableView.getScheduleManager().setShowNotCurWeek(false);
mTimetableView.updateView();
}
/**
* 显示非本周课程
* 修改了内容的显示,所以必须更新全部(性能不高)
* 建议:在初始化时设置该属性
*/
protected void showNonThisWeek() {
mTimetableView.getScheduleManager().setShowNotCurWeek(true);
mTimetableView.updateView();
}
/**
* 设置间距以及弧度
* 该方法只能同时设置四个角的弧度,设置单个角的弧度可参考下文
*/
protected void setMarginAndCorner() {
mTimetableView.getScheduleManager()
.setCorner(0)
.setMarTop(0)
.setMarLeft(0);
mTimetableView.updateView();
}
/**
* 设置角度(四个角分别控制)
*
* @param leftTop
* @param rightTop
* @param rightBottom
* @param leftBottom
*/
public void setCorner(final int leftTop, final int rightTop, final int rightBottom, final int leftBottom) {
mTimetableView.getScheduleManager()
.setOnItemBuildListener(new OnItemBuildAdapter() {
@Override
public void onItemUpdate(FrameLayout layout, TextView textView, TextView countTextView, Schedule schedule, GradientDrawable gd) {
super.onItemUpdate(layout, textView, countTextView, schedule, gd);
//数组8个元素,四个方向依次为左上、右上、右下、左下,
// 每个方向在数组中占两个元素,值相同
gd.setCornerRadii(new float[]{leftTop, leftTop, rightTop, rightTop, rightBottom, rightBottom, leftBottom, leftBottom});
}
});
mTimetableView.updateView();
}
/**
* 修改显示的文本
*/
public void buildItemText() {
mTimetableView.getScheduleManager()
.setOnItemBuildListener(new OnItemBuildAdapter() {
@Override
public String getItemText(Schedule schedule, boolean isThisWeek) {
if (isThisWeek) return "[本周]" + schedule.getName();
return "[非本周]" + schedule.getName();
}
});
mTimetableView.updateView();
}
效果不能很好实现,存在BUG,不应该再使用,有这种需求可以考虑从数据源中删除某门课程
/**
* 将名为"计算机组成原理"的课程拦截下来,该课程不会被构建
*/
public void intercept() {
mTimetableView.getScheduleManager()
.setOnItemBuildListener(new OnItemBuildAdapter() {
@Override
public boolean interceptItemBuild(Schedule schedule) {
if (schedule.getName().equals("计算机组成原理")) return true;
return false;
}
});
mTimetableView.updateView();
Toast.makeText(this,"已拦截《计算机组成原理》",Toast.LENGTH_SHORT).show();
}
/**
* 设置非本周课的背景
*
* @param color
*/
public void setNonThisWeekBgcolor(int color) {
mTimetableView.getScheduleManager()
.getColorPool().setUselessColor(color);
mTimetableView.updateView();
}
/**
* 修改课程重叠的样式,在该接口中,你可以自定义出很多的效果
*/
protected void modifyOverlayStyle() {
mTimetableView.getScheduleManager()
.setOnItemBuildListener(new OnItemBuildAdapter() {
@Override
public void onItemUpdate(FrameLayout layout, TextView textView, TextView countTextView, Schedule schedule, GradientDrawable gd) {
super.onItemUpdate(layout, textView, countTextView, schedule, gd);
//可见说明重叠,取消角标,添加角度
if (countTextView.getVisibility() == View.VISIBLE) {
countTextView.setVisibility(View.GONE);
gd.setCornerRadii(new float[]{0, 0, 20, 20, 0, 0, 0, 0});
}
}
});
mTimetableView.updateView();
}
颜色池
ScheduleColorPool
的内部实现是控件维护的一个集合,它管理着课程项的颜色,负责对颜色的存取
以下代码的返回结果就是一个ScheduleColorPool
实例对象
mTimetableView.getScheduleManager().getColorPool();
如果需要让所有课程只在某几种颜色中分配颜色,只需要清空颜色池并加入特定的颜色,在分配颜色时会循环分配颜色池中的颜色
/**
* 设置指定的颜色,默认情况下颜色池中有一些颜色
* 所以这里需要先清空一下颜色池
* @param colors
*/
public void setColor(int... colors){
mTimetableView.getScheduleManager()
.getColorPool()
.clear()
.add(colors);
mTimetableView.updateView();
}
重置后,颜色池恢复到初始状态
/**
* 重置颜色池
*/
public void resetColor(){
mTimetableView.getScheduleManager()
.getColorPool()
.reset();
mTimetableView.updateView();
}
向颜色池中追加颜色,在为课程项分配颜色时,会按照颜色池中的顺序依次取出颜色,所以并不保证追加的颜色一定会被用到
/**
* 追加颜色
* @param colors
*/
public void addColor(int... colors){
mTimetableView.getScheduleManager()
.getColorPool()
.add(colors);
mTimetableView.updateView();
}
/**
* 设置非本周课的背景
*
* @param color
*/
public void setNonThisWeekBgcolor(int color) {
mTimetableView.getScheduleManager()
.getColorPool().setUselessColor(color);
mTimetableView.updateView();
}
为什么会有这个功能?想象这样几个场景:下拉反弹效果、下拉刷新效果、监听到滚动的位置、解决滚动布局嵌套导致的滑动冲突。这几个需求都可以使用自定义View的方式来解决。 替换滚动布局的意思是:你可以使用自定义的
ScrollView
来替换控件中的普通的ScrollView
,可以想象它将有更好的扩展性。 本节将演示如何实现一个有下拉反弹效果的课表界面,自定义View的知识不在本节的范围之内,有兴趣可以百度。
你需要先准备好一个自定义View,根据你的需求而定,可以参考demo中定义的弹性滚动布局ElasticScrollView
准备一个布局文件,命名任意,这里命名为custom_myscrollview.xml
,将以下内容复制到布局文件中,然后将根控件换成自定义控件
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/id_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<include layout="@layout/view_content"/>
</ScrollView>
custom_myscrollview.xml
中的内容如下:
<?xml version="1.0" encoding="utf-8"?>
<com.zhuangfei.android_timetableview.ElasticScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/id_scrollview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<include layout="@layout/view_content"/>
</com.zhuangfei.android_timetableview.ElasticScrollView>
/**
* 过程很简单,步骤如下:
* 1.创建一个xml文件,命名为custom_myscrollview.xml
* 2.拷贝一段代码至该文件中,具体内容可以参见custom_myscrollview.xml
* 3.将根布局控件修改为自定义的控件,其他内容无需修改
* 4.设置setOnScrollViewBuildListener()并实现其方法,将自定义的xml转换为View返回即可
*
*/
mTimetableView.setSource(mySubjects)
.setOnScrollViewBuildListener(new ISchedule.OnScrollViewBuildListener() {
@Override
public View getScrollView(LayoutInflater mInflate) {
return mInflate.inflate(R.layout.custom_myscrollview, null, false);
}
})
.showView();
控件提供了一个工具类,可以方便的以无界面的方式操作课程数据,本节演示如何使用工具类实现对课程颜色的可视化展示
在Activity的布局中放一个ListView
<ListView
android:id="@+id/id_listview"
android:layout_width="match_parent"
android:layout_height="match_parent"></ListView>
item_nonview.xml
是ListView中每一项的布局,它的内容如下:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@color/app_white">
<TextView
android:id="@+id/id_nonview_name"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:gravity="center_vertical"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:ellipsize="end"
android:singleLine="true"/>
<TextView
android:id="@+id/id_nonview_color"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"/>
</RelativeLayout>
布局文件准备好之后,需要一个适配器
public class NonViewAdapter extends BaseAdapter {
List<Schedule> schedules;
Context context;
LayoutInflater inflater;
public NonViewAdapter(Context context, List<Schedule> schedules) {
this.context = context;
this.schedules = schedules;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return schedules.size();
}
@Override
public Object getItem(int i) {
return schedules.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View convertView, ViewGroup viewGroup) {
View mView = null;
ViewHolder holder;
if (null == convertView) {
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.item_nonview, null);
holder.nameTextView = convertView.findViewById(R.id.id_nonview_name);
holder.colorTextView = convertView.findViewById(R.id.id_nonview_color);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Schedule schedule= (Schedule) getItem(i);
ScheduleColorPool colorPool=new ScheduleColorPool(context);
holder.nameTextView.setText(schedule.getName());
holder.colorTextView.setBackgroundColor(colorPool.getColorAuto(schedule.getColorRandom()));
return convertView;
}
class ViewHolder {
TextView nameTextView;
TextView colorTextView;
}
}
它是如何将课程的颜色找出来的?看下段代码:
Schedule schedule= (Schedule) getItem(i);
ScheduleColorPool colorPool=new ScheduleColorPool(context);
holder.colorTextView.setBackgroundColor(colorPool.getColorAuto(schedule.getColorRandom()));
继续看,核心就是这一行,适配器中的数据都是被分配过颜色了(怎么分配的见下文),所谓分配颜色就是给它一个编号,然后拿着编号到颜色池中取颜色,getColorAuto()
不会产生数组越界问题,内部使用模运算来循环的在颜色池中取值
colorPool.getColorAuto(schedule.getColorRandom())
设置适配器
listView=findViewById(R.id.id_listview);
adapter=new NonViewAdapter(this,schedules);
listView.setAdapter(adapter);
protected void all(){
List<Schedule> list= ScheduleSupport.transform(SubjectRepertory.loadDefaultSubjects());
list=ScheduleSupport.getColorReflect(list);//分配颜色
schedules.clear();
schedules.addAll(list);
adapter.notifyDataSetChanged();
}
/**
* 获取第一周有课的课程并显示出来
*/
protected void haveTime(){
List<Schedule> list= ScheduleSupport.transform(SubjectRepertory.loadDefaultSubjects());
list=ScheduleSupport.getColorReflect(list);//分配颜色
List<Schedule> result=new ArrayList<>();
List<Schedule>[] arr=ScheduleSupport.getSubjectInitial(list);
for(int i=0;i<arr.length;i++){
List<Schedule> tmpList=arr[i];
for(Schedule schedule:tmpList){
if(ScheduleSupport.isThisWeek(schedule,1)){
result.add(schedule);
}
}
}
schedules.clear();
schedules.addAll(result);
adapter.notifyDataSetChanged();
}
/**
* 显示第一周周一有课的课程
*/
protected void haveTimeWithMonday(){
List<Schedule> list= ScheduleSupport.transform(SubjectRepertory.loadDefaultSubjects());
list=ScheduleSupport.getColorReflect(list);//分配颜色
List<Schedule> tmpList=ScheduleSupport.getTodaySubjects(list,1,0);
schedules.clear();
schedules.addAll(tmpList);
adapter.notifyDataSetChanged();
}
还有很多的功能我没有展示出来,其他的就靠你自己来探索了,在此之前,我给你一个藏宝图 Javadocs