超级课程表-课表格子UI

/ 6评 / 5

前言

在前面三篇博客里面,我分别介绍了使用Java登陆教务的原理以及如何获取课表还有简单的使用ViewPager+ListView简单的实现了一下课表界面,不过这样不够直观和具体,没有分单双周以及每天的课程没有按照时间顺序排序。今天我来介绍一下,如何将我们获取到的课表信息使用格子效果展示出来。以前的三篇博客点击下面链接可进入分类查看。

超级课程表所有实现

课表的格子效果

还是老规矩,在介绍以前先贴出效果图,看看是否是你需要的效果。

SurperTableUI2

可以看到,基本效果全部实现了,包括切换当前周,自动根据课程节数设置大小,点击课程显示详细信息,还可以设置一共有多少周和一天有多少节课,其中最后一个我因为不想设计UI,所以空着了,但是代码写出来了,如果查看源码可以很清楚的看到。

在/res/strings/下有一个名为kb的项,这是我在前面几篇博客上获取的数据处理后的json字符串,用于本Demo的数据。

layout

如上图所示,其实整体分为三个部分,顶部一个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

2016_2_22.3 - 副本

我们首先来分析下这个弹出框,这个弹出框是什么?这个弹出框是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

  1. 刘嘉兴说道:

    您好,我想查看您的超级课表的代码用于学习,但是您的地址已经失效,能单独给我发一份吗?感激不尽

  2. 匿名说道:

    你好!可以私聊有关你的代码么?你发的原地址已经失效了。甚是感激

  3. 老黑说道:

    您好,可以分享一下课程格子的代码吗?我想学习一下,感激不敬!

回复 Alias 取消回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注