前言
在前面三篇博客里面,我分别介绍了使用Java登陆教务的原理以及如何获取课表还有简单的使用ViewPager+ListView简单的实现了一下课表界面,不过这样不够直观和具体,没有分单双周以及每天的课程没有按照时间顺序排序。今天我来介绍一下,如何将我们获取到的课表信息使用格子效果展示出来。以前的三篇博客点击下面链接可进入分类查看。
课表的格子效果
还是老规矩,在介绍以前先贴出效果图,看看是否是你需要的效果。
可以看到,基本效果全部实现了,包括切换当前周,自动根据课程节数设置大小,点击课程显示详细信息,还可以设置一共有多少周和一天有多少节课,其中最后一个我因为不想设计UI,所以空着了,但是代码写出来了,如果查看源码可以很清楚的看到。
在/res/strings/下有一个名为kb的项,这是我在前面几篇博客上获取的数据处理后的json字符串,用于本Demo的数据。
- 整体布局
如上图所示,其实整体分为三个部分,顶部一个TextView和一个ImageView,中间星期几是一个横向的线性布局,放置8个TextView(第一个位置占位置,不显示文字)。最下面是一个ScrollView,里面有一个横向的线性布局,这个线性布局包含8个空的线性布局用于显示课表(为空的目的是,在代码中动态添加TextView)。
贴出整体布局文件。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/bg" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#F7F7F7" android:gravity="center" android:orientation="horizontal" android:padding="10dp" > <TextView android:id="@+id/changeWeek" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="第一周" android:textColor="#3583BD" android:textSize="20sp" /> <ImageView android:layout_width="10dp" android:layout_height="10dp" android:layout_marginLeft="5dp" android:src="@drawable/arrow_down" /> </LinearLayout> <!-- 顶部星期一二三四五六七 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#eeCDF5FD" android:orientation="horizontal" > <TextView android:layout_width="@dimen/left_width" android:layout_height="wrap_content" android:background="@drawable/boder" android:gravity="center" android:paddingBottom="5dp" android:paddingTop="5dp" android:textSize="18sp" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/boder" android:gravity="center" android:paddingBottom="5dp" android:paddingTop="5dp" android:text="周一" android:textColor="@color/font" android:textSize="18sp" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/boder" android:gravity="center" android:paddingBottom="5dp" android:paddingTop="5dp" android:text="周二" android:textColor="@color/font" android:textSize="18sp" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/boder" android:gravity="center" android:paddingBottom="5dp" android:paddingTop="5dp" android:text="周三" android:textColor="@color/font" android:textSize="18sp" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/boder" android:gravity="center" android:paddingBottom="5dp" android:paddingTop="5dp" android:text="周四" android:textColor="@color/font" android:textSize="18sp" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/boder" android:gravity="center" android:paddingBottom="5dp" android:paddingTop="5dp" android:text="周五" android:textColor="@color/font" android:textSize="18sp" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/boder" android:gravity="center" android:paddingBottom="5dp" android:paddingTop="5dp" android:text="周六" android:textColor="@color/font" android:textSize="18sp" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/boder" android:gravity="center" android:paddingBottom="5dp" android:paddingTop="5dp" android:text="周日" android:textColor="@color/font" android:textSize="18sp" /> </LinearLayout> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:overScrollMode="never" android:scrollbars="none" > <!-- 下面是一个横向的8个线性布局(1+7 1是左边的课程编号) --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <!-- 左边的课程编号 --> <LinearLayout android:id="@+id/leftNo" android:layout_width="@dimen/left_width" android:layout_height="wrap_content" android:background="#eeCDF5FD" android:orientation="vertical" > </LinearLayout> <!-- 一二三四五六七的课 --> <LinearLayout android:id="@+id/monday" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" > </LinearLayout> <LinearLayout android:id="@+id/tuesday" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" > </LinearLayout> <LinearLayout android:id="@+id/wednesday" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" > </LinearLayout> <LinearLayout android:id="@+id/thursday" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" > </LinearLayout> <LinearLayout android:id="@+id/firday" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" > </LinearLayout> <LinearLayout android:id="@+id/saturday" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" > </LinearLayout> <LinearLayout android:id="@+id/weekend" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:orientation="vertical" > </LinearLayout> </LinearLayout> </ScrollView> </LinearLayout>
- 布局的初始化
在布局文件中,我们已经直接在布局文件中设置了顶部和显示星期几的部分,在代码中动态处理的是课表的显示部分。
首先初始化左边的课程节数:首先获取左边的宽高为多少,然后动态添加mMaxCouese个TextView,mMaxCouese是一个成员变量,控制一天有多少节课,此变量在配置文件读取,所以可以动态修改一天的课程总数,同理,也可以修改一学期有多少周。
/** * 绘制左边的课程节数 */ private void drawLeftNo() { mLeftHeight = getResources().getDimension(R.dimen.left_height); mLeftWidth = getResources().getDimension(R.dimen.left_width); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams((int) mLeftWidth, (int) mLeftHeight); for (int i = 1; i <= mMaxCouese; i++) { TextView tv = new TextView(this); tv.setText(i + ""); tv.setGravity(Gravity.CENTER); tv.setTextColor(getResources().getColor(R.color.font)); tv.setBackgroundResource(R.drawable.boder); mLeftNo.addView(tv, lp); } }
- 动态添加课程
终于到了重点的位置了,如何使课程编程格子效果。我在上面介绍了,每一天的课程都是一个LinearLayout,从上到下排列,当我们添加第一节的时候,肯定是从最顶部开始,这时,我们判断课程有多长,然后根据一节课的长度就可以计算出来这节课程占用的长度,每一节的长度就是上面添加左边编号时用到的mLeftHeight ,代表左边一个TextView的高度,这样我们就能控制添加课程的打消了,可是这样只能从最顶部向下一个一个的排列,你一定会我觉得我在逗你,放下菜刀,不要急,回忆一下,平常我们在布局文件中,经常设置的外边距,如果我们根据课程是第几课课,然后在它的上面计算出一个上边距不就可以了吗?具体流程就是,对于一天的第一节课,我们只需要计算它和顶部的距离,对于一天中其他的课,就只需要计算它和上一节课的距离就够了,这样我们就实现了格子效果。下面贴出代码,很多方法在课程的包装类中,可以自行下载源码查看。
/** * 绘制课表 * @param ll 绘制课表到哪一个LinearLayout上 * @param dayOfWeek 绘制的数据来自周几 一二三四五六七 */ private void drawCourse(LinearLayout ll, char dayOfWeek) { // 删除所有子View ll.removeAllViews(); // 上一节课结束是第几节 int perCourse = -1; for (CourseBean course : mCourse) { // 判断是否显示这节课 // 是不是同一天 是不是这一周 if (course.getDayOfWeek() != dayOfWeek || !course.inThisWeek(mNowWeek)) continue; // 设置TextView的属性样式 TextView tv = new TextView(this); tv.setText(course.getCourse_name() + "\n@" + course.getCourse_address()); tv.setBackgroundResource(R.drawable.course); tv.setTextColor(getResources().getColor(R.color.course_font_color)); // 将数据绑定到TextView上 tv.setTag(course); tv.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { CourseBean tag = (CourseBean) v.getTag(); showCouseDetails(tag); } }); // 设置TextView的位置 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( LayoutParams.MATCH_PARENT, (int) (course.getStep() * mLeftHeight)); // 说明这节课为第一节课 if (perCourse == -1) { lp.setMargins(1, (int) ((course.getMinCourse() - 1) * mLeftHeight), 1, 0); // useHeight = (int) ((course.getMaxCourse()-1) * mLeftHeight); } else { lp.setMargins(1, (course.getMinCourse() - perCourse - 1) * (int) mLeftHeight, 1, 0); // useHeight = useHeight + (course.getMaxCourse() - perCourse - // 1)* (int) mLeftHeight; } perCourse = course.getMaxCourse(); ll.addView(tv, lp); } }
- 点击课程显示课程详细信息
在上面的代码中可以看到,每当添加一个TextView的时候,我通过setTag将对于的课程信息绑定到了TextView上,然后设置点击监听事件,点击就调用showCouseDetails()方法去显示详细信息,这个方法是我从前面写的博客里面直接复制过来的,可以点击 这里 查看,主要是使用的AlertDialog,关于AlertDialog的用法,可以查看自定义样式的AlertDialog。
- 点击顶部切换当前周
我们首先来分析下这个弹出框,这个弹出框是什么?这个弹出框是PopupWindow,这里我给他设置了一个背景图片而已,关于PopupWindow的用法可以参看PopupWindow详解与仿QQ底部弹出菜单 。里面是一个ListView,这里由于布局很简单,所以使用的是系统提供的适配器ArrayAdapter,具体实现请看代码。
/** * 显示切换当前周的窗口 */ public void showChangeWeekDlg(View v) { View view = View.inflate(this, R.layout.changweek_layout, null); ListView weekList = (ListView) view.findViewById(R.id.weekList); ArrayList<String> strList = new ArrayList<String>(); for (int i = 1; i < mMaxWeek; i++) { strList.add("第" + i + "周"); } ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.item, strList); weekList.setAdapter(adapter); view.measure(0, 0); final PopupWindow pop = new PopupWindow(view, 300, 500, true); pop.setBackgroundDrawable(new ColorDrawable(0x00000000)); int xOffSet = -(pop.getWidth() - v.getWidth()) / 2; pop.showAsDropDown(v, xOffSet, 0); weekList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapter, View view, int positon, long id) { mNowWeek = positon + 1; pop.dismiss(); drawNowWeek(); drawAllCourse(); } }); }
上面几点已经包含了大致所有的细节,源码下载在本文底部,如果有建议或意见,请在博客下留言,我会在第一时间回复。
源码下载 : 360云盘 访问密码 0344
整个系列最终源码 : 360云盘 访问密码 1924
您好,我想查看您的超级课表的代码用于学习,但是您的地址已经失效,能单独给我发一份吗?感激不尽
@刘嘉兴 这个很简单的,可以和你说说原理
你好!可以私聊有关你的代码么?你发的原地址已经失效了。甚是感激
@匿名 你可以加我的QQ私聊,看看右侧的信息栏
您好,可以分享一下课程格子的代码吗?我想学习一下,感激不敬!
@老黑 大半夜的….