那么如何制作出这样的表格呢?
详情参照:
如何制作表格(1)——TableLayout
如何制作表格(2)——GridLayout
如何作表格(3)——GridView+RecyclerView
首先:选择什么样控件来制作头部的格子:
大家一看发现只有一行的表格,但是第一列的大小和其他列的大小是不一样的。大家肯定马上加想到了用TableLayout和GridLayout来制作头部的表格,当然如果不嫌麻烦可以直接用TextView堆加成一行。由于GridView生成的格子大小一致,所以不可以使用。(Recycler是可以制作的,但是总感觉有点大材小用了)。
个人选择GridLayout来制作该头部。(当然小伙伴也可以使用其他的控件来进行头部的制作,看看哪个更方便)
其次:设置每个格子的高度,和宽度。由于第一行比较特殊还需要分离出来。
本人是获取屏幕大小,然后分成15分,第一行占1份,其他行占2分来确定。
最后:分割线的确定
本人选择了,使用
最后的效果:
添加头部:
columCount = "15" :其中有7列用来填充分割线的(这种做法,分割线和表格内容没有分开,容易混乱,不建议使用。本人懒癌发作了,请见谅。
背景:
//中间背景色为透明。
利用代码填充表格内容:
//表格的内容
private static final String [] TITLE_DATA = {"9月","周一","周二","周三","周四","周五","周六","周日"};
private GridLayout mGlClsTitle;
//屏幕宽度的1/15
private int mTableDistance;
protected void onCreateView(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
mGlClsTitle = getViewById(R.id.main_grid_title);
mTableDistance = getScreenPixelWidth()/15;
}
//设置表格的头部
private void setUpClsTitle(){
for (int i=0; i
首先:选择使用哪种控件来制作表格:
private static final int GRID_ROW_COUNT = 12;
private static final int GRID_COL_COUNT = 8;
//初始化课表显示的格子
//初始化表格的距离
for (int i=1; i
#378BE0
#fff
#00000000
#9960BFE5
#9968CA5E
#99F49C97
#9993AAE2
public class Course {
//星期几:周一到周日
private int day;
//第几节课:总共12节
private int clsNum;
//每节课的长度
private int clsCount;
//随机的颜色
private int color;
//课程名
private String clsName;
public int getClsNum() {
return clsNum;
}
public void setClsNum(int clsNum) {
this.clsNum = clsNum;
}
public String getClsName() {
return clsName;
}
public void setClsName(String clsName) {
this.clsName = clsName;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getClsCount() {
return clsCount;
}
public void setClsCount(int clsCount) {
this.clsCount = clsCount;
}
@Override
public String toString() {
return "StuClass{" +
"clsCount=" + clsCount +
", day=" + day +
", clsNum=" + clsNum +
", color=" + color +
", clsName='" + clsName + '\'' +
'}';
}
}
//弯曲四个角
private void showCls(){
for (int i = 0; i< mStuCourseList.size(); ++i){
Course course = mStuCourseList.get(i);
int row = course.getClsNum();
int col = course.getDay();
int size = course.getClsCount();
//设定View在表格的哪行那列
GridLayout.LayoutParams params = new GridLayout.LayoutParams(
GridLayout.spec(row,size),
GridLayout.spec(col)
);
//设置View的宽高
params.width = mTableDistance*2;
params.height = (int) getResources().getDimension(R.dimen.table_row_height) * size;
params.setGravity(Gravity.FILL);
//通过代码改变的背景颜色
GradientDrawable drawable = (GradientDrawable) getResources().getDrawable(R.drawable.cls_bg);
drawable.setColor(getResources().getColor(course.getColor()));
//设置View
TextView textView = new TextView(this);
textView.setTextColor(getResources().getColor(R.color.white));
textView.setText(course.getClsName());
textView.setGravity(Gravity.CENTER);
textView.setBackground(drawable);
//添加到表格中
mGlClsContent.addView(textView,params);
}
}
RadioButtonList1:可能显示值为unable to decode value。该内容可以从网站的源码中找到(单击右键,查看网络源代码)
最后查询出来的结果是"学生"
public class HttpConnection {
private static final long TIME_OUT = 10000;
private OkHttpClient mClient;
private static HttpConnection sConnection;
private final Map> mCookieMap = new HashMap<>();
private HttpConnection(){
mClient = new OkHttpClient.Builder()
.connectTimeout(TIME_OUT, TimeUnit.MILLISECONDS)
.readTimeout(TIME_OUT,TimeUnit.MILLISECONDS)
.cookieJar(new MyCookieJar())
.build();
}
public static HttpConnection getInstance(){
if (sConnection == null){
sConnection = new HttpConnection();
}
return sConnection;
}
/*存储Cookie的类*/
/**
* 由于网站不能够持久化登陆,就直接将Cookie值放在HashMap中了
*/
class MyCookieJar implements CookieJar{
@Override
public void saveFromResponse(HttpUrl url, List cookies) {
mCookieMap.put(url.host(),cookies);
}
@Override
public List loadForRequest(HttpUrl url) {
List cookieList = mCookieMap.get(url.host());
return cookieList == null ? new ArrayList() : cookieList;
}
}
public void saveCookie(HttpUrl url,List cookies){
//如果url相同则替换
mClient.cookieJar().saveFromResponse(url,cookies);
}
public List getCookies(HttpUrl url){
//未判断Http是否合法
return mClient.cookieJar().loadForRequest(url);
}
/*默认使用异步加载*/
public void connectUrl(Request request, Callback callback){
Call call = mClient.newCall(request);
call.enqueue(callback);
}
public interface HttpCallBack {
void callback(T data);
}
}
(3)、创建URLManager,管理网址
/**
* Created by PC on 2016/9/25.
* 存储需要用到的网址
*/
public class URLManager {
//登陆的首页
public static final String URL_BASE = "http://202.115.80.153";
//登陆的验证码
public static final String URL_CODES = "http://202.115.80.153/CheckCode.aspx?";
//登陆的判定提交地址
public static final String URL_LOGIN = "http://202.115.80.153/default2.aspx";
//登陆之后的跳转页面
public static final String URL_REFERER = "http://202.115.80.153/xs_main.aspx?xh=XH";
//课程表
public static final String URL_CLS = "http://202.115.80.153/xskbcx.aspx?xh=XH";
}
/**
* Created by PC on 2016/9/25.
* 登陆到学校的教务网
* 需要设置为单例模式
*/
public class LoginService {
public static final String TAG = "LoginService";
private final Handler mHandler = new Handler(Looper.getMainLooper());
private Context mContext;
//设置登陆的Post参数
private String rudioButton = "学生";
private String state = "dDwyODE2NTM0OTg7Oz7QBx05W486R++11e1KrLTLz5ET2Q==";
private String button1 = "";
private String language = "";
private String hidPdrs = "";
private String hidsc = "";
private HttpConnection mConnection = HttpConnection.getInstance();
public LoginService(Context context){
mContext = context;
}
//获取验证码
/**
* 获取验证码的时候,会返回给客户端一个Cookie
* 作用:获取验证码
* @param httpCallBack
*/
public void getCodesImg(final HttpConnection.HttpCallBack httpCallBack) throws IOException{
URL codeUrl = new URL(URLManager.URL_CODES);
final Request request = new Request.Builder()
.url(codeUrl)
.build();
Callback callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG,"出错");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()){
//用流优化当收到的数据比较大
byte [] bytes = response.body().bytes();
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
final Bitmap bitmap = BitmapFactory.decodeStream(bais);
//切换线程环境
changeEnvironment(httpCallBack,bitmap);
response.close();
}
}
};
mConnection.connectUrl(request,callback);
}
public void login(final String username, String pwd, final String codes, final HttpConnection.HttpCallBack httpCallBack) throws IOException{
URL url = new URL(URLManager.URL_LOGIN);
FormBody formBody = new FormBody.Builder()
.add("__VIEWSTATE",state)
.add("txtUserName",username)
.add("TextBox2",pwd)
.add("txtSecretCode",codes)
.add("RadioButtonList1",rudioButton)
.add("Button1",button1)
.add("lbLanguage",language)
.add("hidPdrs",hidPdrs)
.add("hidsc",hidsc)
.build();
final Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
Callback callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.d(TAG,"错误");
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()){
boolean isLogin = false;
//判断是否登陆成功 注释①
if(CourseParse.
parseIsLoginSucceed(response.body().string())){
isLogin = true;
}
else {
//显示登陆失败。
isLogin = false;
}
changeEnvironment(httpCallBack,isLogin);
response.close();
}
}
};
mConnection.connectUrl(request,callback);
}
private void changeEnvironment(final HttpConnection.HttpCallBack httpCallBack, final T data){
mHandler.post(new Runnable() {
@Override
public void run() {
httpCallBack.callback(data);
}
});
}
}
public static boolean parseIsLoginSucceed(String data){
Document doc = Jsoup.parse(data);
//查看登陆文档。
Element element = doc.getElementById("xhxm");
if (element != null){
return true;
}
return false;
}
public class CourseService {
public static final String TAG = "CourseService";
private final Handler mHandler = new Handler();
private HttpConnection mConnection = HttpConnection.getInstance();
public > void getCourse(String username, final HttpConnection.HttpCallBack callBack) throws IOException {
//因为xh为学号,需要自己设置
String urlCls = URLManager.URL_CLS.replace("XH",username);
//重点:因为该网站实现的是动态跳转(有没有发现跳转到课表页面,但是网址没有变化)
//必须添加Referer到Http头,Referer指的是当前页面的网址,否则会拒绝访问
String referer = URLManager.URL_REFERER.replace("XH",username);
Log.d(TAG,urlCls);
URL url = new URL(urlCls);
Request.Builder builder = new Request.Builder();
builder.addHeader("Referer",referer);
builder.url(url);
final Request request = builder.build();
Callback callback = new Callback() {
@Override
public void onFailure(Call call, IOException e) {
//网络较差环境下的问题
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
//登陆到课表,并解析课程表的资源
if (response.isSuccessful()){
//其实这里可以使用InputStream进行优化的。以后再说吧
final String clsDocument = response.body().string();
mHandler.post(new Runnable() {
@Override
public void run() {
T stuClassList = (T) CourseParse.parsePersonal(clsDocument);
callBack.callback(stuClassList);
}
});
response.close();
}
}
};
mConnection.connectUrl(request,callback);
}
}
(7)解析课表数据,并转化为Course(在CourseParase类中)
/*解析个人课表*/
public static List parsePersonal(String data){
List courses = new ArrayList<>();
Document doc = Jsoup.parse(data);
//首先获取Table
Element table = doc.getElementById("Table1");
//然后获取table中的td节点
Elements trs = table.select("tr");
//移除不需要的参数,这里表示移除前两个数值。
trs.remove(0);
trs.remove(0);
//遍历td节点
for (int i=0; i
好了,到这里,超级课程表就出炉了~~~~~吼吼