由于毕业设计有一个功能模块是课程表,就想模仿一下超级课程表的界面,可是开始做的时候却没有一点头绪,百度google均无果,在CSDN和知乎上提问了也没人回答(估计是太简单了 大神不愿回答),总之自己鼓捣了几天还是弄出来了,虽然实现的方法很挫。。。因为有好几个人都发私信问我怎么实现的,现在毕设做完了,所以我干脆就写到博客上吧,先上几张效果图:
当时看到超级课程表的界面时,第一个想法就是使用ListView来实现,好不容易把格子画出来了,课程信息不知道怎么放上去····,主要难点有:
1、第一排的8个格子是固定的,下面的课表信息部分是可以滑动的,单用ListView无法实现,即下图。
2、课程信息怎么附着在格子上,并且可以随着课表一起滚动。
放弃了ListView实现的想法,就只有另寻它路了,在CSDN上有一位朋友的回答给了我灵感,即每一个格子都用一个TextView实现。然后课程信息可以使用相对布局,根据课程的时间(节数和天数)算出他的偏移位置,比如星期二的第三、四节课就可以和周二下面的第一个格子保持左对齐和上对齐,并且向下偏移2个格子的距离。这个N个格子和课程信息都放到一个RelativeLayout中,然后再在外面嵌套一个ScrollViewLayout,就可以滚动了,总的布局还是RelayoutLayout,不多说了,直接上代码!
当然这样做的坏处有:
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> courseInfoMap;
/** 保存显示课程信息的TextView **/
protected List courseTextViewList = new ArrayList();
/** 保存每个textview对应的课程信息 map,key为哪一天(如星期一则key为1) **/
protected Map> textviewCourseInfoMap = new HashMap>();
/** 课程格子平均宽度 **/
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 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 mActivity;
public CourseInfoInitMessageHandler(CourseTableActivity activity){
mActivity = new WeakReference(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> courseInfoMap = mActivity.get().courseInfoMap;
//一些传过来的参数
final InitMessageObj msgObj = (InitMessageObj) msg.obj;
//当前周数
int currentWeek = msgObj.currentWeek;
//最大课程节数
int maxCourseNum = msgObj.maxCourseNum;
for(Map.Entry> entry: courseInfoMap.entrySet())
{
//查找出最顶层的课程信息(顶层课程信息即显示在最上层的课程,最顶层的课程信息满足两个条件 1、当前周数在该课程的周数范围内 2、该课程的节数跨度最大
CourseInfo upperCourse = null;
//list里保存的是一周内某 一天的课程
final List list = new ArrayList(entry.getValue());
//
//按开始的时间(哪一节)进行排序
Collections.sort(list, new Comparator(){
@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 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 courseInfoList = new ArrayList();
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> map = mActivity.get().textviewCourseInfoMap;
final List 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
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;
}
}
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;
}
}
}
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 courseList, int width, int currentWeek) {
super();
this.screenWidth = width;
this.context = context;
this.currentWeek = currentWeek;
createGalleryWithCourseList(courseList);
}
private void createGalleryWithCourseList(List 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)));
}
}
5、gallery-3d布局
-
-
-
-
gitbub上的代码已删除
demo版:超级课程表demo