全网第二好的Android课程表控件之工具类

工具类

https://github.com/zfman/TimetableView
一个开源的、完善的、简洁的课程表控件

控件提供了一个工具类,可以方便的以无界面的方式操作课程数据,本节演示如何使用工具类实现对课程颜色的可视化展示

布局文件

在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();
    }

结语

至此,v2.0.0的讲解就结束了,虽然这个控件的实现原理很简单,我知道的有两种实现方法,超级课程表、课程格子都是用相对布局来实现的,该控件使用线性布局实现。

两种方式各有优劣,使用线性布局+weight的使用和Relative都需要两次测量,但是Relative可以减少一个布局层次已经减少7个布局,比线性布局的实现要好上一点。最开始的版本滑动时有明显卡顿,经过对其优化,滑动性能大幅度提高,目前滑动性能在警戒线之内。

控件实现不难,但是如何灵活的设计却很难(对我来说),我花费了半个月左右的时间重构了v1.0.4版本

如果感觉不错就帮我点个star吧,蟹蟹~~

上一篇:全网第二好的Android课程表控件之替换滚动布局

猜你喜欢

转载自blog.csdn.net/lzhuangfei/article/details/80744560