http://blog.csdn.net/mhxy199288/article/details/30255761
由于毕业设计有一个功能模块是课程表,就想模仿一下超级课程表的界面,可是开始做的时候却没有一点头绪,百度google均无果,在CSDN和知乎上提问了也没人回答(估计是太简单了 大神不愿回答),总之自己鼓捣了几天还是弄出来了,虽然实现的方法很挫。。。因为有好几个人都发私信问我怎么实现的,现在毕设做完了,所以我干脆就写到博客上吧,先上几张效果图:
当时看到超级课程表的界面时,第一个想法就是使用ListView来实现,好不容易把格子画出来了,课程信息不知道怎么放上去····,主要难点有:
1、第一排的8个格子是固定的,下面的课表信息部分是可以滑动的,单用ListView无法实现,即下图。
2、课程信息怎么附着在格子上,并且可以随着课表一起滚动。
放弃了ListView实现的想法,就只有另寻它路了,在CSDN上有一位朋友的回答给了我灵感,即每一个格子都用一个TextView实现。然后课程信息可以使用相对布局,根据课程的时间(节数和天数)算出他的偏移位置,比如星期二的第三、四节课就可以和周二下面的第一个格子保持左对齐和上对齐,并且向下偏移2个格子的距离。这个N个格子和课程信息都放到一个RelativeLayout中,然后再在外面嵌套一个ScrollViewLayout,就可以滚动了,总的布局还是RelayoutLayout,不多说了,直接上代码!
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="@drawable/c_bg" >
- <!-- 最左边空白的格子 -->
- <TextView android:id="@+id/test_empty"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="@style/courseTableText"
- android:text="@string/empty"
- android:background="@drawable/course_text_view_bg"
- />
- <!-- 星期一的格子 -->
- <TextView android:id="@+id/test_monday_course"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/mon"
- style="@style/courseTableText"
- android:layout_toRightOf="@id/test_empty"
- android:background="@drawable/course_text_view_bg"
- />
- <!-- 星期二的格子 -->
- <TextView android:id="@+id/test_tuesday_course"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/tue"
- style="@style/courseTableText"
- android:layout_toRightOf="@id/test_monday_course"
- android:background="@drawable/course_text_view_bg"
- />
- <!-- 星期三的格子 -->
- <TextView android:id="@+id/test_wednesday_course"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/wen"
- style="@style/courseTableText"
- android:layout_toRightOf="@id/test_tuesday_course"
- android:background="@drawable/course_text_view_bg"
- />
- <!-- 星期四的格子 -->
- <TextView android:id="@+id/test_thursday_course"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/thu"
- style="@style/courseTableText"
- android:layout_toRightOf="@id/test_wednesday_course"
- android:background="@drawable/course_text_view_bg"
- />
- <!-- 星期五的格子 -->
- <TextView android:id="@+id/test_friday_course"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/fri"
- style="@style/courseTableText"
- android:layout_toRightOf="@id/test_thursday_course"
- android:background="@drawable/course_text_view_bg"
- />
- <!-- 星期六的格子 -->
- <TextView android:id="@+id/test_saturday_course"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/sta"
- style="@style/courseTableText"
- android:layout_toRightOf="@id/test_friday_course"
- android:background="@drawable/course_text_view_bg"
- />
- <!-- 星期天的格子 -->
- <TextView android:id="@+id/test_sunday_course"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="@style/courseTableText"
- android:text="@string/sun"
- android:layout_toRightOf="@id/test_saturday_course"
- android:background="@drawable/course_table_last_colum"
- />
- <!-- 课程表body部分 -->
- <ScrollView
- android:id="@+id/scroll_body"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/test_empty"
- android:scrollbars="none"
- >
- <!-- 课程信息 -->
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:id="@+id/test_course_rl"
- >
- </RelativeLayout>
- </ScrollView>
- </RelativeLayout>
当然这样做的坏处有:
1、有多少个格子就要生成多少个TextView,实在是有点浪费资源。
2、用TextView表示一个格子,即有边框的TextView,整个课表是由N个TextView组成的,所以就没办法使用一张图当背景了。
当然现在我也想到了改进的方法,其实给课程信息做参照算出偏移位置的只需要一个格子就可以了,所以可以用一个透明的TextView放在星期一的第一个格子的位置作为参照,格子使用view画线实现,就可以使用背景了,也不用生成多个TextView了···这是我的想法,我还没用代码实现,有兴趣的朋友可以自己去试试。
超级课程表还有一个要点就是它的课程展示3D视图,不过那个可以用Android自带的gallery实现,网上有现成的代码,拿过来改改就可以了,下面上主要代码
1、CourseTableActivity
- package nd.leiyi.crims.activity;
- import java.lang.ref.WeakReference;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.List;
- import java.util.Map;
- import nd.leiyi.crims.R;
- import nd.leiyi.crims.adapter.CourseInfoAdapter;
- import nd.leiyi.crims.appException.AppException;
- import nd.leiyi.crims.constant.UserInfo;
- import nd.leiyi.crims.db.CourseInfoDBManager;
- import nd.leiyi.crims.gallery3D.CourseInfoGallery;
- import nd.leiyi.crims.http.CourseInfoFetcher;
- import nd.leiyi.crims.model.CourseInfo;
- import nd.leiyi.crims.util.CourseSettingUtil;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.app.Dialog;
- import android.app.ProgressDialog;
- import android.content.Context;
- import android.content.Intent;
- import android.content.SharedPreferences;
- import android.content.SharedPreferences.Editor;
- import android.graphics.Color;
- import android.graphics.drawable.BitmapDrawable;
- import android.graphics.drawable.Drawable;
- import android.os.Bundle;
- import android.os.Handler;
- import android.os.Message;
- import android.util.DisplayMetrics;
- import android.util.Log;
- import android.view.Gravity;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.ViewGroup.LayoutParams;
- import android.view.Window;
- import android.view.WindowManager;
- import android.widget.AdapterView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.ListView;
- import android.widget.PopupWindow;
- import android.widget.PopupWindow.OnDismissListener;
- import android.widget.Button;
- import android.widget.RelativeLayout;
- import android.widget.SimpleAdapter;
- import android.widget.TextView;
- import android.widget.Toast;
- public class CourseTableActivity extends Activity {
- /** 标题栏文字 */
- protected TextView textTitle;
- /** 第一个无内容的格子 */
- protected TextView empty;
- /** 星期一的格子 */
- protected TextView monColum;
- /** 星期二的格子 */
- protected TextView tueColum;
- /** 星期三的格子 */
- protected TextView wedColum;
- /** 星期四的格子 */
- protected TextView thrusColum;
- /** 星期五的格子 */
- protected TextView friColum;
- /** 星期六的格子 */
- protected TextView satColum;
- /** 星期日的格子 */
- protected TextView sunColum;
- /** 课程表body部分布局 */
- protected RelativeLayout course_table_layout;
- /** 选择周数弹出窗口 */
- protected PopupWindow weekListWindow;
- /** 显示周数的listview*/
- protected ListView weekListView;
- /** 选择周数弹出窗口的layout */
- protected View popupWindowLayout;
- /** 课程信息 **/
- protected Map<String, List<CourseInfo>> courseInfoMap;
- /** 保存显示课程信息的TextView **/
- protected List<TextView> courseTextViewList = new ArrayList<TextView>();
- /** 保存每个textview对应的课程信息 map,key为哪一天(如星期一则key为1) **/
- protected Map<Integer, List<CourseInfo>> textviewCourseInfoMap = new HashMap<Integer, List<CourseInfo>>();
- /** 课程格子平均宽度 **/
- protected int aveWidth;
- /** 屏幕宽度 **/
- protected int screenWidth;
- /** 格子高度 **/
- protected int gridHeight = 80;
- /** 最大课程节数 **/
- protected int maxCourseNum;
- protected Button goBackButton;
- protected ProgressDialog pDialog;
- protected Handler mhandler = new Handler();
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- //设置自定义标题栏布局
- requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
- setContentView(R.layout.course_table_layout);
- getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,R.layout.title);
- //设置标题栏周数
- textTitle = (TextView) this.findViewById(R.id.textTile);
- textTitle.setTextSize(20);
- textTitle.setPadding(15, 2, 15, 2);
- //右边白色倒三角
- Drawable down = this.getResources().getDrawable(R.drawable.title_down);
- down.setBounds(0, 0, down.getMinimumWidth(), down.getMinimumHeight());
- textTitle.setCompoundDrawables(null, null, down, null);
- textTitle.setCompoundDrawablePadding(2);
- //获得列头的控件
- empty = (TextView) this.findViewById(R.id.test_empty);
- monColum = (TextView) this.findViewById(R.id.test_monday_course);
- tueColum = (TextView) this.findViewById(R.id.test_tuesday_course);
- wedColum = (TextView) this.findViewById(R.id.test_wednesday_course);
- thrusColum = (TextView) this.findViewById(R.id.test_thursday_course);
- friColum = (TextView) this.findViewById(R.id.test_friday_course);
- satColum = (TextView) this.findViewById(R.id.test_saturday_course);
- sunColum = (TextView) this.findViewById(R.id.test_sunday_course);
- //返回按钮
- goBackButton = (Button) this.findViewById(R.id.button_go_back);
- goBackButton.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- //改变返回按钮的背景,体现出被“按下出”的感觉
- goBackButton.setBackgroundDrawable(CourseTableActivity.this
- .getResources().getDrawable(R.drawable.arrow_left_down));
- // 恢复背景
- mhandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- goBackButton.setBackgroundDrawable(CourseTableActivity.this
- .getResources().getDrawable(R.drawable.arrow_left));
- }
- }, 200);
- mhandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- finish();
- }
- }, 400);
- }
- });
- // 列表布局文件
- course_table_layout = (RelativeLayout) this.findViewById(R.id.test_course_rl);
- DisplayMetrics dm = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(dm);
- //屏幕宽度
- int width = dm.widthPixels;
- //平均宽度
- int aveWidth = width / 8;
- //给列头设置宽度
- empty.setWidth(aveWidth * 3/4);
- monColum.setWidth(aveWidth * 33/32 + 1);
- tueColum.setWidth(aveWidth * 33/32 + 1);
- wedColum.setWidth(aveWidth * 33/32 + 1);
- thrusColum.setWidth(aveWidth * 33/32 + 1);
- friColum.setWidth(aveWidth * 33/32 + 1);
- satColum.setWidth(aveWidth * 33/32 + 1);
- sunColum.setWidth(aveWidth * 33/32 + 1);
- this.screenWidth = width;
- this.aveWidth = aveWidth;
- //初始化body部分
- init();
- }
- /**
- * 初始化课程表body部分
- * @param aveWidth
- */
- protected void init(){
- //获取课表配置信息
- final SharedPreferences courseSettings = getSharedPreferences("course_setting", Activity.MODE_PRIVATE);
- //检测是否设置过学期
- if(courseSettings.getString("currentTerm_" + UserInfo.currentUser.getStuNum(), null) == null)
- {
- Toast.makeText(CourseTableActivity.this, "您尚未设置当前学期!快去设置吧!", Toast.LENGTH_SHORT).show();
- return;
- }
- //计算出当前的周数
- final String currentWeekStr = CourseSettingUtil.figureCurrentWeek(courseSettings);
- if(currentWeekStr.equals(""))
- {
- textTitle.setText("全部");
- }
- else
- {
- textTitle.setText("第" + currentWeekStr + "周");
- }
- //设置点击事件
- textTitle.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- //改变背景(体现出被"按下去"的感觉
- textTitle.setBackgroundDrawable(
- CourseTableActivity.this.getResources().getDrawable(R.drawable.title_text_bg));
- //显示弹出窗口
- showWeekListWindow(textTitle);
- }
- });
- //获取最大课程节数
- String maxCourseNumStr = courseSettings.getString("maxCourseNum_" + UserInfo.currentUser.getStuNum(), "");
- if(maxCourseNumStr.equals(""))
- {
- courseSettings.edit().putString("maxCourseNum_" + UserInfo.currentUser.getStuNum(), "12");
- maxCourseNum = 12;
- }
- else
- {
- maxCourseNum = Integer.parseInt(maxCourseNumStr);
- }
- DisplayMetrics dm = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(dm);
- //屏幕高度
- int height = dm.heightPixels;
- gridHeight = height / maxCourseNum;
- //设置课表界面
- //动态生成12 * maxCourseNum个textview
- for(int i = 1; i <= maxCourseNum; i ++){
- for(int j = 1; j <= 8; j ++){
- TextView tx = new TextView(CourseTableActivity.this);
- tx.setId((i - 1) * 8 + j);
- //除了最后一列,都使用course_text_view_bg背景(最后一列没有右边框)
- if(j < 8)
- tx.setBackgroundDrawable(CourseTableActivity.this.
- getResources().getDrawable(R.drawable.course_text_view_bg));
- else
- tx.setBackgroundDrawable(CourseTableActivity.this.
- getResources().getDrawable(R.drawable.course_table_last_colum));
- //相对布局参数
- RelativeLayout.LayoutParams rp = new RelativeLayout.LayoutParams(
- aveWidth * 33 / 32 + 1,
- gridHeight);
- //文字对齐方式
- tx.setGravity(Gravity.CENTER);
- //字体样式
- tx.setTextAppearance(this, R.style.courseTableText);
- //如果是第一列,需要设置课的序号(1 到 12)
- if(j == 1)
- {
- tx.setText(String.valueOf(i));
- rp.width = aveWidth * 3/4;
- //设置他们的相对位置
- if(i == 1)
- rp.addRule(RelativeLayout.BELOW, empty.getId());
- else
- rp.addRule(RelativeLayout.BELOW, (i - 1) * 8);
- }
- else
- {
- rp.addRule(RelativeLayout.RIGHT_OF, (i - 1) * 8 + j - 1);
- rp.addRule(RelativeLayout.ALIGN_TOP, (i - 1) * 8 + j - 1);
- tx.setText("");
- }
- tx.setLayoutParams(rp);
- course_table_layout.addView(tx);
- }
- }
- pDialog = new ProgressDialog(this);
- pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
- pDialog.setMessage("正在加载信息。。。。");
- pDialog.setIndeterminate(true);
- pDialog.setCanceledOnTouchOutside(false);
- pDialog.setCancelable(false);
- pDialog.show();
- //获取当前学期
- final String currentTerm = courseSettings.getString("currentTerm_" + UserInfo.currentUser.getStuNum(), null);
- //查看这个学期的课程信息是否已经抓取过
- final boolean hasSetting = courseSettings.getBoolean("Is_" + currentTerm + "_saved_" + UserInfo.currentUser.getStuNum(), false);
- /**
- 这里写你自己的获取课程信息的方法
- */
- new Thread() {
- @Override
- public void run() {
- CourseInfoDBManager dbManager = new CourseInfoDBManager(CourseTableActivity.this);
- //打开数据库
- dbManager.open();
- try {
- //入果还没抓取过该学期的课程信息,先抓取
- if(!hasSetting)
- {
- //抓取这个学期的课表信息
- List<CourseInfo> list = CourseInfoFetcher.fetchCourseInfo("", currentTerm, UserInfo.currentUser.getStuNum());
- //插入课程信息
- for(CourseInfo courseInfo : list)
- {
- dbManager.insertCourse(courseInfo, currentTerm);
- }
- //设置该学期的课程已经抓取过的标志
- Editor editor = courseSettings.edit();
- editor.putBoolean("Is_" + currentTerm + "_saved_" + UserInfo.currentUser.getStuNum(), true);
- editor.commit();
- }
- //从数据库中读取课程信息,存放在courseInfoMap中,key为星期几,value是这一天的课程信息
- courseInfoMap = dbManager.query(currentTerm);
- // 发送更新界面信息
- Message msg = new Message();
- if(courseInfoMap.isEmpty())
- {
- msg.what = -2;
- courseInfoInitMessageHandler.sendMessage(msg);
- return;
- }
- int currentWeek = -1;
- if(!currentWeekStr.equals(""))
- {
- currentWeek = Integer.parseInt(currentWeekStr);
- }
- dbManager.close();
- InitMessageObj msgObj = new InitMessageObj(aveWidth, currentWeek, screenWidth, maxCourseNum);
- msg.obj = msgObj;
- courseInfoInitMessageHandler.sendMessage(msg);
- } catch (AppException e) {
- Message msg = new Message();
- msg.what = -1;
- courseInfoInitMessageHandler.sendMessage(msg);
- Log.e("courseInfo_fetch_exception", e.toString());
- } finally {
- dbManager.close();
- }
- }
- }.start();
- }
- CourseInfoInitMessageHandler courseInfoInitMessageHandler = new CourseInfoInitMessageHandler(this);
- static class InitMessageObj{
- int aveWidth;
- int currentWeek;
- int screenWidth;
- int maxCourseNum;
- public InitMessageObj(int aveWidth, int currentWeek, int screenWidth, int maxCourseNum) {
- super();
- this.aveWidth = aveWidth;
- this.currentWeek = currentWeek;
- this.screenWidth = screenWidth;
- this.maxCourseNum = maxCourseNum;
- }
- }
- //初始化课程表的messageHandler
- static class CourseInfoInitMessageHandler extends Handler{
- WeakReference<CourseTableActivity> mActivity;
- public CourseInfoInitMessageHandler(CourseTableActivity activity){
- mActivity = new WeakReference<CourseTableActivity>(activity);
- }
- @Override
- public void handleMessage(Message msg) {
- mActivity.get().pDialog.dismiss();
- //网络错误
- if(msg.what == -1)
- {
- Toast.makeText(mActivity.get(), "获取课程信息失败!请检查您的网络或者稍后再试", Toast.LENGTH_SHORT).show();
- return;
- }
- //没有课程信息
- if(msg.what == -2)
- {
- Toast.makeText(mActivity.get(), "教务管理系统中无该学期的课程信息···", Toast.LENGTH_SHORT).show();
- return;
- }
- //五种颜色的背景
- int[] background = {R.drawable.course_info_blue, R.drawable.course_info_green,
- R.drawable.course_info_red, R.drawable.course_info_red,
- R.drawable.course_info_yellow};
- //获取课程信息的map
- Map<String, List<CourseInfo>> courseInfoMap = mActivity.get().courseInfoMap;
- //一些传过来的参数
- final InitMessageObj msgObj = (InitMessageObj) msg.obj;
- //当前周数
- int currentWeek = msgObj.currentWeek;
- //最大课程节数
- int maxCourseNum = msgObj.maxCourseNum;
- for(Map.Entry<String, List<CourseInfo>> entry: courseInfoMap.entrySet())
- {
- //查找出最顶层的课程信息(顶层课程信息即显示在最上层的课程,最顶层的课程信息满足两个条件 1、当前周数在该课程的周数范围内 2、该课程的节数跨度最大
- CourseInfo upperCourse = null;
- //list里保存的是一周内某 一天的课程
- final List<CourseInfo> list = new ArrayList<CourseInfo>(entry.getValue());
- //
- //按开始的时间(哪一节)进行排序
- Collections.sort(list, new Comparator<CourseInfo>(){
- @Override
- public int compare(CourseInfo arg0, CourseInfo arg1) {
- if(arg0.getBeginIndex() < arg1.getBeginIndex())
- return -1;
- else
- return 1;
- }
- });
- int lastListSize;
- do {
- lastListSize = list.size();
- Iterator<CourseInfo> iter = list.iterator();
- //先查找出第一个在周数范围内的课
- while(iter.hasNext())
- {
- CourseInfo c = iter.next();//
- if(((c.getBeginWeek() <= currentWeek && c.getEndWeek() >= currentWeek) || currentWeek == -1) && c.getEndIndex() <= maxCourseNum)
- {
- //判断是单周还是双周的课
- if(c.getCourseType() == CourseInfo.ALL ||
- (c.getCourseType() == CourseInfo.EVEN && currentWeek % 2 == 0) ||
- (c.getCourseType() == CourseInfo.ODD && currentWeek % 2 != 0) )
- {
- //从list中移除该项,并设置这节课为顶层课
- iter.remove();
- upperCourse = c;
- break;
- }
- }
- }
- if(upperCourse != null)
- {
- List<CourseInfo> courseInfoList = new ArrayList<CourseInfo>();
- courseInfoList.add(upperCourse);
- int index = 0;
- iter = list.iterator();
- //查找这一天有哪些课与刚刚查找出来的顶层课相交
- while(iter.hasNext())
- {
- CourseInfo c = iter.next();
- //先判断该课程与upperCourse是否相交,如果相交加入courseInfoList中
- if((c.getBeginIndex() <= upperCourse.getBeginIndex()
- &&upperCourse.getBeginIndex() < c.getEndIndex())
- ||(upperCourse.getBeginIndex() <= c.getBeginIndex()
- && c.getBeginIndex() < upperCourse.getEndIndex()))
- {
- courseInfoList.add(c);
- iter.remove();
- //在判断哪个跨度大,跨度大的为顶层课程信息
- if((c.getEndIndex() - c.getEndIndex()) > (upperCourse.getEndIndex() - upperCourse.getBeginIndex())
- && ((c.getBeginWeek() <= currentWeek && c.getEndWeek() >= currentWeek) || currentWeek == -1))
- {
- upperCourse = c;
- index ++;
- }
- }
- }
- //记录顶层课程在courseInfoList中的索引位置
- final int upperCourseIndex = index;
- // 动态生成课程信息TextView
- TextView courseInfo = new TextView(mActivity.get());
- courseInfo.setId(1000 + upperCourse.getDay() * 100 + upperCourse.getBeginIndex() * 10 + upperCourse.getId());
- int id = courseInfo.getId();
- mActivity.get().textviewCourseInfoMap.put(id, courseInfoList);
- courseInfo.setText(upperCourse.getCourseName() + "\n@" + upperCourse.getClassRoom());
- //该textview的高度根据其节数的跨度来设置
- RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
- msgObj.aveWidth * 31 / 32,
- (mActivity.get().gridHeight - 5) * 2 + (upperCourse.getEndIndex() - upperCourse.getBeginIndex() - 1) * mActivity.get().gridHeight);
- //textview的位置由课程开始节数和上课的时间(day of week)确定
- rlp.topMargin = 5 + (upperCourse.getBeginIndex() - 1) * mActivity.get().gridHeight;
- rlp.leftMargin = 1;
- // 前面生成格子时的ID就是根据Day来设置的
- rlp.addRule(RelativeLayout.RIGHT_OF, upperCourse.getDay());
- //字体居中中
- courseInfo.setGravity(Gravity.CENTER);
- //选择一个颜色背景
- int colorIndex = ((upperCourse.getBeginIndex() - 1) * 8 + upperCourse.getDay()) % (background.length - 1);
- courseInfo.setBackgroundResource(background[colorIndex]);
- courseInfo.setTextSize(12);
- courseInfo.setLayoutParams(rlp);
- courseInfo.setTextColor(Color.WHITE);
- //设置不透明度
- courseInfo.getBackground().setAlpha(222);
- // 设置监听事件
- courseInfo.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View arg0) {
- Log.i("text_view", String.valueOf(arg0.getId()));
- Map<Integer, List<CourseInfo>> map = mActivity.get().textviewCourseInfoMap;
- final List<CourseInfo> tempList = map.get(arg0.getId());
- if(tempList.size() > 1)
- {
- //如果有多个课程,则设置点击弹出gallery 3d 对话框
- LayoutInflater layoutInflater = (LayoutInflater) mActivity.get().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View galleryView = layoutInflater.inflate(R.layout.course_info_gallery_layout, null);
- final Dialog coursePopupDialog = new AlertDialog.Builder(mActivity.get()).create();
- coursePopupDialog.setCanceledOnTouchOutside(true);
- coursePopupDialog.setCancelable(true);
- coursePopupDialog.show();
- WindowManager.LayoutParams params = coursePopupDialog.getWindow().getAttributes();
- params.width = LayoutParams.FILL_PARENT;
- coursePopupDialog.getWindow().setAttributes(params);
- CourseInfoAdapter adapter = new CourseInfoAdapter(mActivity.get(), tempList, msgObj.screenWidth, msgObj.currentWeek);
- CourseInfoGallery gallery = (CourseInfoGallery) galleryView.findViewById(R.id.course_info_gallery);
- gallery.setSpacing(10);
- gallery.setAdapter(adapter);
- gallery.setSelection(upperCourseIndex);
- gallery.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(
- AdapterView<?> arg0, View arg1,
- int arg2, long arg3) {
- CourseInfo courseInfo = tempList.get(arg2);
- Intent intent = new Intent();
- Bundle mBundle = new Bundle();
- mBundle.putSerializable("courseInfo", courseInfo);
- intent.putExtras(mBundle);
- intent.setClass(mActivity.get(), DetailCourseInfoActivity.class);
- mActivity.get().startActivity(intent);
- coursePopupDialog.dismiss();
- }
- });
- coursePopupDialog.setContentView(galleryView);
- }
- else
- {
- Intent intent = new Intent();
- Bundle mBundle = new Bundle();
- mBundle.putSerializable("courseInfo", tempList.get(0));
- intent.putExtras(mBundle);
- intent.setClass(mActivity.get(), DetailCourseInfoActivity.class);
- mActivity.get().startActivity(intent);
- }
- }
- });
- mActivity.get().course_table_layout.addView(courseInfo);
- mActivity.get().courseTextViewList.add(courseInfo);
- upperCourse = null;
- }
- } while(list.size() < lastListSize && list.size() != 0);
- }
- super.handleMessage(msg);
- }
- }
- /**
- * 显示周数下拉列表悬浮窗
- * @param parent
- */
- private void showWeekListWindow(View parent){
- if(weekListWindow == null)
- {
- LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- //获取layout
- popupWindowLayout = layoutInflater.inflate(R.layout.week_list_layout, null);
- weekListView = (ListView) popupWindowLayout.findViewById(R.id.week_list_view_body);
- //禁用滚动条(貌似没用··)
- weekListView.setVerticalScrollBarEnabled(false);
- List<Map<String, Object>> weekList = new ArrayList<Map<String, Object>>();
- //默认25周
- for(int i = 1; i <= 25; i ++)
- {
- Map<String, Object> rowData = new HashMap<String, Object>();
- rowData.put("week_index", "第" + i + "周");
- weekList.add(rowData);
- }
- //设置listview的adpter
- SimpleAdapter listAdapter = new SimpleAdapter(this,
- weekList, R.layout.week_list_item_layout,
- new String[]{"week_index"},
- new int[]{R.id.week_list_item});
- weekListView.setAdapter(listAdapter);
- weekListView.setOnItemClickListener(new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> adpater, View arg1,
- int arg2, long arg3) {
- int index = 0;
- String indexStr = textTitle.getText().toString();
- indexStr = indexStr.replaceAll("第", "").replaceAll("周", "");
- if(!indexStr.equals("全部"))
- index = Integer.parseInt(indexStr);
- textTitle.setText("第" + (arg2 + 1) + "周");
- weekListWindow.dismiss();
- if((arg2 + 1) != index)
- {
- Log.i("courseTableActivity", "清空当前课程信息");
- for(TextView tx : courseTextViewList)
- {
- course_table_layout.removeView(tx);
- }
- courseTextViewList.clear();
- //重新设置课程信息
- Message msg = new Message();
- InitMessageObj msgObj = new InitMessageObj(aveWidth, arg2 + 1, screenWidth, maxCourseNum);
- msg.obj = msgObj;
- courseInfoInitMessageHandler.sendMessage(msg);
- }
- }
- });
- int width = textTitle.getWidth();
- //实例化一个popupwindow
- weekListWindow = new PopupWindow(popupWindowLayout, width + 100, width + 120);
- }
- weekListWindow.setFocusable(true);
- //设置点击外部可消失
- weekListWindow.setOutsideTouchable(true);
- weekListWindow.setBackgroundDrawable(new BitmapDrawable());
- //消失的时候恢复按钮的背景(消除"按下去"的样式)
- weekListWindow.setOnDismissListener(new OnDismissListener() {
- @Override
- public void onDismiss() {
- textTitle.setBackgroundDrawable(null);
- }
- });
- weekListWindow.showAsDropDown(parent, -50, 0);
- }
- }
2、CourseInfo
- package nd.leiyi.crims.model;
- import java.io.Serializable;
- public class CourseInfo implements Serializable{
- /**
- *
- */
- private static final long serialVersionUID = 2074656067805712769L;
- /** id */
- private int id;
- /** 课程名称 */
- private String courseName;
- /** 上课教室 */
- private String classRoom;
- /** 老师 */
- private String teacher;
- /** 上课时间(哪一天)(周一--周日) */
- private int day;
- /** 上课时间(哪一节)开始(1--12) */
- private int beginIndex;
- /** 上课时间(哪一节)节数(1--12) */
- private int endIndex;
- /** 上课时间(哪一周) 开始 */
- private int beginWeek;
- /** 上课时间(哪一周) 结束 */
- private int endWeek;
- /** 课程类型(单周还是双周) **/
- private int courseType;
- public static final int ALL = 1;
- public static final int ODD = 2;
- public static final int EVEN = 3;
- public String getCourseName() {
- return courseName;
- }
- public void setCourseName(String courseName) {
- this.courseName = courseName;
- }
- public String getClassRoom() {
- return classRoom;
- }
- public void setClassRoom(String classRoom) {
- this.classRoom = classRoom;
- }
- public String getTeacher() {
- return teacher;
- }
- public void setTeacher(String teacher) {
- this.teacher = teacher;
- }
- public int getDay() {
- return day;
- }
- public void setDay(int day) {
- this.day = day;
- }
- public int getBeginIndex() {
- return beginIndex;
- }
- public void setBeginIndex(int beginIndex) {
- this.beginIndex = beginIndex;
- }
- public int getEndIndex() {
- return endIndex;
- }
- public void setEndIndex(int endIndex) {
- this.endIndex = endIndex;
- }
- public int getBeginWeek() {
- return beginWeek;
- }
- public void setBeginWeek(int beginWeek) {
- this.beginWeek = beginWeek;
- }
- public int getEndWeek() {
- return endWeek;
- }
- public void setEndWeek(int endWeek) {
- this.endWeek = endWeek;
- }
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public int getCourseType() {
- return courseType;
- }
- public void setCourseType(int courseType) {
- this.courseType = courseType;
- }
- }
3、CourseInfoGallery
- package nd.leiyi.crims.gallery3D;
- import android.content.Context;
- import android.graphics.Camera;
- import android.graphics.Matrix;
- import android.util.AttributeSet;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.animation.Transformation;
- import android.widget.Gallery;
- public class CourseInfoGallery extends Gallery {
- private Camera mCamera = new Camera();
- private int mMaxRotationAngle = 60;
- private int mMaxZoom = -60;
- private int mCoveflowCenter;
- public CourseInfoGallery(Context context) {
- super(context);
- this.setStaticTransformationsEnabled(true);
- }
- public CourseInfoGallery(Context context, AttributeSet attrs) {
- super(context, attrs);
- this.setStaticTransformationsEnabled(true);
- }
- public CourseInfoGallery(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- this.setStaticTransformationsEnabled(true);
- }
- public int getMaxRotationAngle() {
- return mMaxRotationAngle;
- }
- public void setMaxRotationAngle(int maxRotationAngle) {
- mMaxRotationAngle = maxRotationAngle;
- }
- public int getMaxZoom() {
- return mMaxZoom;
- }
- public void setMaxZoom(int maxZoom) {
- mMaxZoom = maxZoom;
- }
- private int getCenterOfCoverflow() {
- return (getWidth() - getPaddingLeft() - getPaddingRight()) / 2
- + getPaddingLeft();
- }
- private static int getCenterOfView(View view) {
- return view.getLeft() + view.getWidth() / 2;
- }
- protected boolean getChildStaticTransformation(View child, Transformation t) {
- final int childCenter = getCenterOfView(child);
- final int childWidth = child.getWidth();
- int rotationAngle = 0;
- t.clear();
- t.setTransformationType(Transformation.TYPE_MATRIX);
- if (childCenter == mCoveflowCenter) {
- transformImageBitmap(child, t, 0);
- } else {
- rotationAngle = (int) (((float) (mCoveflowCenter - childCenter) / childWidth) * mMaxRotationAngle);
- if (Math.abs(rotationAngle) > mMaxRotationAngle) {
- rotationAngle = (rotationAngle < 0) ? -mMaxRotationAngle
- : mMaxRotationAngle;
- }
- transformImageBitmap(child, t, rotationAngle);
- }
- return true;
- }
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- mCoveflowCenter = getCenterOfCoverflow();
- super.onSizeChanged(w, h, oldw, oldh);
- }
- private void transformImageBitmap(View child, Transformation t,
- int rotationAngle) {
- mCamera.save();
- final Matrix imageMatrix = t.getMatrix();
- final int imageHeight = child.getLayoutParams().height;
- final int imageWidth = child.getLayoutParams().width;
- final int rotation = Math.abs(rotationAngle);
- mCamera.translate(0.0f, 0.0f, 100.0f);
- // As the angle of the view gets less, zoom in
- if (rotation < mMaxRotationAngle) {
- float zoomAmount = (float) (mMaxZoom + (rotation * 1.5));
- mCamera.translate(0.0f, 0.0f, zoomAmount);
- }
- mCamera.rotateY(rotationAngle);
- mCamera.getMatrix(imageMatrix);
- imageMatrix.preTranslate(-(imageWidth / 2), -(imageHeight / 2));
- imageMatrix.postTranslate((imageWidth / 2), (imageHeight / 2));
- mCamera.restore();
- }
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_MOVE) {
- return true;
- } else {
- return false;
- }
- }
- }
4、CourseInfoAdapter
- package nd.leiyi.crims.adapter;
- import java.util.List;
- import nd.leiyi.crims.R;
- import nd.leiyi.crims.gallery3D.CourseInfoGallery;
- import nd.leiyi.crims.model.CourseInfo;
- import android.content.Context;
- import android.graphics.Color;
- import android.view.Gravity;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.TextView;
- public class CourseInfoAdapter extends BaseAdapter {
- private Context context;
- private TextView[] courseTextViewList;
- private int screenWidth;
- private int currentWeek;
- public CourseInfoAdapter(Context context, List<CourseInfo> courseList, int width, int currentWeek) {
- super();
- this.screenWidth = width;
- this.context = context;
- this.currentWeek = currentWeek;
- createGalleryWithCourseList(courseList);
- }
- private void createGalleryWithCourseList(List<CourseInfo> courseList){
- //五种颜色的背景
- int[] background = {R.drawable.course_info_blue, R.drawable.course_info_green,
- R.drawable.course_info_red, R.drawable.course_info_red,
- R.drawable.course_info_yellow};
- this.courseTextViewList = new TextView[courseList.size()];
- for(int i = 0; i < courseList.size(); i ++)
- {
- final CourseInfo course = courseList.get(i);
- TextView textView = new TextView(context);
- textView.setText(course.getCourseName() + "@" + course.getClassRoom());
- textView.setLayoutParams(new CourseInfoGallery.LayoutParams((screenWidth / 6) *3, (screenWidth / 6) *3));
- textView.setTextColor(Color.WHITE);
- textView.setGravity(Gravity.CENTER_VERTICAL);
- textView.setPadding(10, 0, 0, 0);
- if(course.getBeginWeek() <= currentWeek && course.getEndWeek() >= currentWeek &&
- (course.getCourseType() == CourseInfo.ALL ||
- (course.getCourseType() == CourseInfo.EVEN && currentWeek % 2 == 0) ||
- (course.getCourseType() == CourseInfo.ODD && currentWeek % 2 != 0)))
- {
- //选择一个颜色背景
- int colorIndex = ((course.getBeginIndex() - 1) * 8 + course.getDay()) % (background.length - 1);
- textView.setBackgroundResource(background[colorIndex]);
- }
- else
- {
- textView.setBackgroundResource(R.drawable.course_info_light_grey);
- }
- textView.getBackground().setAlpha(222);
- // textView.setOnClickListener(new OnClickListener() {
- // @Override
- // public void onClick(View arg0) {
- // // TODO Auto-generated method stub
- // Intent intent = new Intent();
- // Bundle mBundle = new Bundle();
- // mBundle.putSerializable("courseInfo", course);
- // intent.putExtras(mBundle);
- // intent.setClass(context, DetailCourseInfoActivity.class);
- // context.startActivity(intent);
- // }
- // });
- this.courseTextViewList[i] = textView;
- }
- }
- @Override
- public int getCount() {
- return courseTextViewList.length;
- }
- @Override
- public Object getItem(int index) {
- return courseTextViewList[index];
- }
- @Override
- public long getItemId(int arg0) {
- return arg0;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- return courseTextViewList[position];
- }
- public float getScale(boolean focused, int offset) {
- return Math.max(0, 1.0f / (float) Math.pow(2, Math.abs(offset)));
- }
- }
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
- <nd.leiyi.crims.gallery3D.CourseInfoGallery
- android:id="@+id/course_info_gallery"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- />
- </LinearLayout>
6、gallery-3d-item
- <?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:orientation="vertical" >
- <TextView
- android:id="@+id/course_info_gallery_item"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textColor="#ffffff"
- android:gravity="center_vertical"/>
- </LinearLayout>
7、course_text_view_bg (课程格子背景)
- <?xml version="1.0" encoding="UTF-8"?>
- <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
- <item>
- <shape>
- <solid android:color="#FFFFFF" />
- <stroke
- android:width="1dp"
- android:color="#a8abad" />
- </shape>
- </item>
- <item
- android:right="1dp"
- android:bottom="1dp">
- <shape>
- <solid android:color="#FFFFFF" />
- <stroke
- android:width="1dp"
- android:color="#ffffff" />
- </shape>
- </item>
- </layer-list>
8、course_table_last_colum(最后一列的背景,无边框)
- <?xml version="1.0" encoding="UTF-8"?>
- <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
- <item>
- <shape>
- <solid android:color="#FFFFFF" />
- <stroke
- android:width="1dp"
- android:color="#a8abad" />
- </shape>
- </item>
- <item
- android:bottom="1dp">
- <shape>
- <solid android:color="#FFFFFF" />
- <stroke
- android:width="1dp"
- android:color="#ffffff" />
- </shape>
- </item>
- </layer-list>
还有一些布局文件就不贴了。代码太多了··,有兴趣的同学可以在github里下载我的工程···工程比较大,而且后台服务端程序我已经从云服务器上撤销了,所以跑不起来,我也不愿改代码了··
gitbub上的代码已删除
demo版:超级课程表demo