CATableView(表单视图)

2018-09-08 15:44 更新

类说明 

CATableView 主要用于生成列表,在table中展示数据,是一个一维的表,可以让用户能通过分层的数据进行导航,表可以是静态的或者动态的,可通过 dataSource 协议和 delegate 协议可以实现很多的个性化定制,即便拥有大量数据也非常有效率。CATableView只能有一列数据(cell),且只支持纵向滑动。


我们先了解一下CATableView的界面构成,CATableView主要是由两级目录构成Selection级和Cell级。如图所示,一个CATableView包含一个或多个Selection,一个Selection包含一个或多个Cell,这样就构成了CATableVIew的层级表示图。


CATableView的使用方法和CAListView比较类似,我们也要分别使用:CATableView、CATableViewCell、CATableViewDelegate、CATableViewDataSource来构建。
CATableView是表格视图的容器,是容器的载体。
CATableViewCell是表格视图的一个单元(本节后面简称cell)。
CATableViewDelegate是交互代理,响应cell选中和取消状态。
CATableViewDataSource是数据代理,设置Selection个数及Selection包含cell个数。


CATableView 属性(点击查看方法介绍)

属性说明
TableViewDataSource添加数据代理
TableViewDelegate添加交互代理
TableHeaderView添加头部视图
TableFooterView添加尾部视图
SeparatorColor设置cell分割线的颜色
TableHeaderHeight设置头部的高度
TableFooterHeight设置尾部的高度
SeparatorViewHeight设置cell分割线的高度
AllowsSelection是否开启cell选择
AllowsMultipleSelection是否可以多选cell
AlwaysTopSectionHeader设置cell顶部的标题
AlwaysBottomSectionFooter设置cell底部的标题


CATableView 方法(点击查看方法介绍)

方法说明
setAllowsSelection是否开启cell选择
setAllowsMultipleSelection是否可以多选cell
setSelectRowAtIndexPath设置选中cell时调用
setUnSelectRowAtIndexPath设置取消选中cell时调用
setShowsScrollIndicators设置显示滚动条
getNumberOfSections获取tableview包含的section个数
getNumberOfRowsInSection获取对应的section所包含的cell个数
getSectionHeightInSection通过索引获取section高度
getSectionHeaderHeightInSection通过索引获取section顶部的高度
getSectionFooterHeightInSection通过索引获取section底部的高度
getRowHeightInSectionInRow通过索引cell高度获取section和cell
createWithFrame创建,并指定其Frame,默认Frame为(0,0,0,0)
createWithCenter创建,并指定其Center,默认Center为(0,0,0,0)
dequeueReusableCellWithIdentifier可以重用单元标示符
cellForRowAtIndexPath通过索引cell获取Index路径
switchPCMode开关PC模式
ccTouchBegan触摸事件开始时的回调函数
ccTouchMoved触摸事件中触点移动时的回调函数
ccTouchEnded触摸事件结束时的回调函数
ccTouchCancelled触摸非正常结束时的回调函数。(例如:电话或锁屏)
mouseMoved鼠标移动
mouseMovedOutSide鼠标移出
init初始化
reloadData重载数据


CATableViewCell 属性(点击查看方法介绍)

属性说明
ContentView内容视图
BackgroundView背景视图
ReuseIdentifier重用标识符
Sectionsection
Rowcell
ControlStateEffect控制状态
AllowsSelected允许选择


CATableViewCell 方法(点击查看方法介绍)

方法说明
create创建,默认Frame为(0,0,0,0)
initWithReuseIdentifier重用标识符初始化


CATableViewDelegate 方法(点击查看方法介绍)

方法说明
tableViewDidSelectRowAtIndexPath选中cell时调用
tableViewDidDeselectRowAtIndexPath取消选择cell时调用


CATableViewDataSource 方法(点击查看方法介绍)

方法说明
tableCellAtIndex获取指定cell
tableViewHeightForRowAtIndexPath获取指定的cell高度
numberOfRowsInSection获取对应的section所包含的cell个数
numberOfSections获取section个数
tableViewSectionViewForHeaderInSection在tableView中通过索引获取头部Section
tableViewHeightForHeaderInSection在tableView中通过索引获取头部Section高度
tableViewSectionViewForFooterInSection在tableView中通过索引获取尾部Section
tableViewHeightForFooterInSection在tableView中通过索引获取尾部Section高度
tableViewWillDisplayCellAtIndex回调当前将要显示的tableView


我们本节也使用CATableView来实现一个简单的表单视图,首先我们需要新建一个Class,命名为:MyTableViewCell并继承CATableViewCell。代码示例如下:

文件CATableViewCell.h

#ifndef _My_TableViewCell_h_
#define _My_TableViewCell_h_
#include <iostream>
#include "CrossApp.h"
USING_NS_CC;
class MyTableViewCell:public CATableViewCell
{
public:
    MyTableViewCell();
    virtual ~MyTableViewCell();
     
    //创建MyTableViewCell
    static MyTableViewCell* create(const std::string& identifier, const DRect& _rect = DRectZero);
     
public:
    //初始化
    void initWithCell();
     
    //按钮的回调函数
    void cellBtnCallback(CAControl* btn, DPoint point);
protected:
     
    //正常状态下调用
    virtual void normalTableViewCell();
     
    //高亮状态下调用
    virtual void highlightedTableViewCell();
     
    //选择状态下调用
    virtual void selectedTableViewCell();
     
    //禁用状态下调用
    virtual void disabledTableViewCell();
     
    //恢复状态下调用
    virtual void recoveryTableViewCell();
};
#endif

文件CATableViewCell.cpp

#include "MyTableViewCell.h"
MyTableViewCell::MyTableViewCell()
{
}
MyTableViewCell::~MyTableViewCell()
{
}
MyTableViewCell* MyTableViewCell::create(const std::string& identifier, const DRect& _rect)
{
    //创建
    MyTableViewCell* tableViewCell = new MyTableViewCell();
    if(tableViewCell&&tableViewCell->initWithReuseIdentifier(identifier))
    {
        tableViewCell->setFrame(_rect);
        tableViewCell->autorelease();
        return tableViewCell;
    }
    CC_SAFE_DELETE(tableViewCell);
    return NULL;
}
void MyTableViewCell::initWithCell()
{
    //Cell的大小
    DSize m_size = this->getFrame().size;
     
    //创建CALabel
    CALabel* cellText = CALabel::createWithCenter(DRect(m_size.width*0.1, m_size.height*0.5, m_size.width*0.3, m_size.height*0.8));
     
    //设置tag
    cellText->setTag(100);
     
    //设置字体大小
    cellText->setFontSize(_px(30));
     
    //设置中心对齐
    cellText->setTextAlignment(CATextAlignmentCenter);
    cellText->setVerticalTextAlignmet(CAVerticalTextAlignmentCenter);
     
    //添加到当前cell
    this->addSubview(cellText);
     
    //创建CAButton
    CAButton* btnOnCell = CAButton::createWithCenter(DRect(m_size.width*0.85, m_size.height*0.5, m_size.width*0.2, m_size.height*0.7), CAButtonTypeRoundedRect);
     
    //设置tag
    btnOnCell->setTag(102);
     
    //设置显示文本
    btnOnCell->setTitleForState(CAControlStateAll, "Touch");
     
    //添加回调监听
    btnOnCell->addTarget(this, CAControl_selector(MyTableViewCell::cellBtnCallback), CAControlEventTouchUpInSide);
     
    //添加到cell
    this->addSubview(btnOnCell);
}
void MyTableViewCell::cellBtnCallback(CAControl* btn, DPoint point)
{
    //按钮被点击时打印log
    CCLog("MyTableViewCell::cellBtnCallback-->");
}
void MyTableViewCell::normalTableViewCell()
{
    //改变背景颜色
    this->setBackgroundView(CAView::createWithColor(CAColor_white));
}
void MyTableViewCell::highlightedTableViewCell()
{
    //改变背景颜色
    this->setBackgroundView(CAView::createWithColor(CAColor_gray));
}
void MyTableViewCell::selectedTableViewCell()
{
    //改变背景颜色
    this->setBackgroundView(CAView::createWithColor(CAColor_orange));
}
void MyTableViewCell::disabledTableViewCell()
{
    //改变背景颜色
    this->setBackgroundView(CAView::createWithColor(CAColor_black));
}
void MyTableViewCell::recoveryTableViewCell()
{
    //改变背景颜色
    this->setBackgroundView(CAView::createWithColor(CAColor_blue));
}

我们创建了cell之后,就在FirstViewController实现CATableViewDelegate和CATableViewDataSource这两个代理,那么FirstViewController.h的内容如下:

#ifndef __HelloCpp__ViewController__
#define __HelloCpp__ViewController__
#include <iostream>
#include "CrossApp.h"
#include "MyTableViewCell.h"
USING_NS_CC;
class FirstViewController: public CAViewController , public CATableViewDataSource ,public CATableViewDelegate
{
     
public:
    FirstViewController();
     
    virtual ~FirstViewController();
     
public:
    //选中cell时触发
    virtual void tableViewDidSelectRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row);
     
    //取消选中cell时触发
    virtual void tableViewDidDeselectRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row);
     
    //获取对应的section所包含的cell个数
    virtual unsigned int numberOfRowsInSection(CATableView *table, unsigned int section);
     
    //获取tableview包含的section个数
    virtual unsigned int numberOfSections(CATableView *table);
     
    //获得指定cell
    virtual CATableViewCell* tableCellAtIndex(CATableView* table, const DSize& cellSize, unsigned int section, unsigned int row);
     
    //设置section的头部
    virtual CAView* tableViewSectionViewForHeaderInSection(CATableView* table, const DSize& viewSize, unsigned int section);
     
    //设置section的尾部
    virtual CAView* tableViewSectionViewForFooterInSection(CATableView* table, const DSize& viewSize, unsigned int section);
     
    //获取指定的cell高度
    virtual unsigned int tableViewHeightForRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row);
     
    //获得指定的section的header vier的高度
    virtual unsigned int tableViewHeightForHeaderInSection(CATableView* table, unsigned int section);
     
    //获得指定的section的footer view的高度
    virtual unsigned int tableViewHeightForFooterInSection(CATableView* table, unsigned int section);
     
protected:
     
    void viewDidLoad();
     
    void viewDidUnload();
     
};
#endif /* defined(__HelloCpp__ViewController__) */

然后我们在FirstViewController.cpp中实现表格视图如下:

#include "FirstViewController.h"
FirstViewController::FirstViewController()
{
}
FirstViewController::~FirstViewController()
{
}
void FirstViewController::viewDidLoad()
{
    DSize size = this->getView()->getBounds().size;
    CATableView* p_TableView = CATableView::createWithCenter(DRect(size.width*0.5, size.height*0.5, size.width, size.height));
    p_TableView->setTableViewDataSource(this);
    p_TableView->setTableViewDelegate(this);
    p_TableView->setAllowsSelection(true);
    p_TableView->setAllowsMultipleSelection(true);
    p_TableView->setSeparatorColor(CAColor_clear);
    this->getView()->addSubview(p_TableView);
}
void FirstViewController::viewDidUnload()
{
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}
void FirstViewController::tableViewDidSelectRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row)
{
}
void FirstViewController::tableViewDidDeselectRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row)
{
}
CATableViewCell* FirstViewController::tableCellAtIndex(CATableView* table, const DSize& cellSize, unsigned int section, unsigned int row)
{
    DSize _size = cellSize;
     
    //根据标识获得cell
    MyTableViewCell* cell = dynamic_cast<MyTableViewCell*>(table->dequeueReusableCellWithIdentifier("CrossApp"));
     
    //如果没有找到cell
    if (cell == NULL)
    {
        //创建一个
        cell = MyTableViewCell::create("CrossApp", DRect(0, 0, _size.width, _size.height));
         
        //调用cell的初始化
        cell->initWithCell();
    }
    //如果是section为1的情况
    if (section == 1)
    {
        //根据tag获得CAButton
        CAButton* cellBtn = (CAButton*)cell->getSubviewByTag(102);
         
        //隐藏按钮
        cellBtn->setVisible(false);
    }
    else
    {
        //根据tag获得CAButton
        CAButton* cellBtn = (CAButton*)cell->getSubviewByTag(102);
         
        //显示按钮
        cellBtn->setVisible(true);
    }
    string order = crossapp_format_string("cell-%d",row);
     
    //根据tag获得CALabel
    CALabel* cellText = (CALabel*)cell->getSubviewByTag(100);
     
    //设置文本显示
    cellText->setText(order);
    return cell;
}
CAView* FirstViewController::tableViewSectionViewForHeaderInSection(CATableView* table, const DSize& viewSize, unsigned int section)
{
    CCLog("Header-->");
    string head = crossapp_format_string("Selection-%d", section);
     
    //创建Section头部视图
    CAView* view = CAView::createWithColor(CAColor_gray);
    DSize _size = viewSize;
    CALabel* header = CALabel::createWithCenter(DRect(_size.width*0.5, _size.height*0.5, _size.width*0.8, _size.height));
    header->setText(head);
    header->setFontSize(_px(30));
    header->setColor(CAColor_white);
    header->setTextAlignment(CATextAlignmentCenter);
    header->setVerticalTextAlignmet(CAVerticalTextAlignmentCenter);
    view->addSubview(header);
    return view;
}
CAView* FirstViewController::tableViewSectionViewForFooterInSection(CATableView* table, const DSize& viewSize, unsigned int section)
{
    CCLog("Footer-->");
    CAView* view = CAView::createWithColor(CAColor_white);
    return view;
}
unsigned int FirstViewController::numberOfRowsInSection(CATableView *table, unsigned int section)
{
    //cell数,从0计算。10表示0-9
    return 10;
}
unsigned int FirstViewController::numberOfSections(CATableView *table)
{
    //表格数,从0开始计算。4则表示0-3
    return 4;
}
unsigned int FirstViewController::tableViewHeightForRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row)
{
    //高度
    return _px(130);
}
unsigned int FirstViewController::tableViewHeightForHeaderInSection(CATableView* table, unsigned int section)
{
    //高度
    return _px(50);
}
unsigned int FirstViewController::tableViewHeightForFooterInSection(CATableView* table, unsigned int section)
{
    return 1;
}

这样我们就构建了一个表格视图,大家可以自己尝试这用CATableVIew去实现一个微信的通信录列表。


CATableView 属性说明

TableViewDataSource

类型:CATableViewDataSource*

解释:添加数据代理。set/get{}。


TableViewDelegate

类型:CATableViewDelegate*

解释:添加交互代理。set/get{}。


TableHeaderView

类型:CAView*

解释:添加头部视图。set/get{}。


TableFooterView

类型:CAView*

解释:添加尾部视图。set/get{}。


SeparatorColor

类型:CAColor4B

解释:设置cell分割线的颜色。set/get{}。


TableHeaderHeight

类型:unsigned int

解释:设置头部视图的高度。set/get{}。


TableFooterHeight

类型:unsigned int

解释:设置尾部视图的高度。set/get{}。


SeparatorViewHeight

类型:unsigned int

解释:设置cell分割线的高度。set/get{}。


AllowsSelection

类型:bool

解释:是否开启cell选择。is{}。


AllowsMultipleSelection

类型:bool

解释:是否可以多选cell。is{}。


AlwaysTopSectionHeader

类型:bool

解释:设置cell顶部的标题。is/set{}。


AlwaysBottomSectionFooter

类型:bool

解释:设置cell底部的标题。is/set{}。


CATableView 方法说明

virtual void setAllowsSelection(bool var);

返回值:virtual void

参数:

类型
参数名说明
boolvar是否允许选择

解释:是否开启cell选择


virtual void setAllowsMultipleSelection(bool var);

返回值:virtual void

参数:

类型
参数名说明
boolvar是否允许多个选择

解释:是否可以多选cell


void setSelectRowAtIndexPath(unsigned int section, unsigned int row);

返回值:void

参数:

类型
参数名说明
unsigned intsectioncell所属的区域
unsigned int
rowcell所在行数

解释:设置选中cell时调用


void setUnSelectRowAtIndexPath(unsigned int section, unsigned int row);

返回值:void

参数:

类型
参数名说明
unsigned intsectioncell所属的区域
unsigned introw
cell所在行数

解释:设置取消选中cell时调用


virtual void setShowsScrollIndicators(bool var);

返回值:virtual void

参数:

类型
参数名说明
boolvar是否设置显示滚动条

解释:设置显示滚动条


unsigned int getNumberOfSections();

返回值:unsigned int

参数:

解释:获取tableview包含的section个数


unsigned int getNumberOfRowsInSection(unsigned int section);

返回值:unsigned int

参数:

类型
参数名说明
unsigned int sectioncell所属的区域

解释:获取对应的section所包含的cell个数


float getSectionHeightInSection(unsigned int section);

返回值:float

参数:

类型
参数名说明
unsigned intsectioncell所属的区域

解释:通过索引获取section高度


float getSectionHeaderHeightInSection(unsigned int section);

返回值:float

参数:

类型
参数名说明
unsigned intsectioncell所属的区域

解释:通过section索引获取section顶部的高度


float getSectionFooterHeightInSection(unsigned int section);

返回值:float

参数:

类型
参数名说明
unsigned intsectioncell所属的区域

解释:通过section索引获取section底部的高度


float getRowHeightInSectionInRow(unsigned int section, unsigned int row);

返回值:float

参数:

类型
参数名说明
unsigned intsectioncell所属的区域
unsigned introwcell所在行数

解释:通过索引cell高度获取section和cell

     

static CATableView* createWithFrame(const DRect& rect);

返回值:static CATableView*

参数:

类型
参数名说明
DRectrect区域大小

解释:创建,并指定其Frame,默认Frame为(0,0,0,0)


static CATableView* createWithCenter(const DRect& rect);

返回值:static CATableView*

参数:

类型
参数名说明
DRectrect中心点的位置及大小

解释:创建,并指定其Center,默认Center为(0,0,0,0)

virtual bool init();

返回值:virtual void

参数:

解释:初始化


void reloadData();

返回值:void

参数:

解释:重载数据


CATableViewCell* dequeueReusableCellWithIdentifier(const char* reuseIdentifier);

返回值:CATableViewCell*

参数:

类型
参数名说明
const char*reuseIdentifier重用标识符

解释:可以重用单元标示符


CATableViewCell* cellForRowAtIndexPath(unsigned int section, unsigned int row);

返回值:CATableViewCell*

参数:

类型
参数名说明
unsigned intsectioncell所属的区域
unsigned introwcell所在行数

解释:通过索引cell获取Index路径


virtual void switchPCMode(bool var);

返回值:virtual void

参数:

类型
参数名说明
boolvar开关

解释:开关PC模式


virtual bool ccTouchBegan(CATouch *pTouch, CAEvent *pEvent);

返回值:virtual bool

参数:

类型
参数名说明
CATouch*pTouch触摸传递对象
CAEvent*pEvent此参数待定

解释:触摸事件开始时的回调函数


virtual void ccTouchMoved(CATouch *pTouch, CAEvent *pEvent);

返回值:virtual void

参数:

类型
参数名说明
CATouch*pTouch触摸传递对象
CAEvent*pEvent此参数待定

解释:触摸事件中触点移动时的回调函数


virtual void ccTouchEnded(CATouch *pTouch, CAEvent *pEvent);

返回值:virtual void

参数:

类型
参数名说明
CATouch*pTouch触摸传递对象
CAEvent*pEvent此参数待定

解释:触摸事件结束时的回调函数


virtual void ccTouchCancelled(CATouch *pTouch, CAEvent *pEvent);

返回值:virtual void

参数:

类型
参数名说明
CATouch*pTouch触摸传递对象
CAEvent*pEvent此参数待定

解释:触摸非正常结束时的回调函数。(例如:电话或锁屏)


virtual void mouseMoved(CATouch* pTouch, CAEvent* pEvent);

返回值:virtual void

参数:

类型
参数名说明
CATouch*pTouch传递对象
CAEvent*pEvent此参数待定

解释:鼠标移动


virtual void mouseMovedOutSide(CATouch* pTouch, CAEvent* pEvent);

返回值:virtual void

参数:

类型
参数名说明
CATouch*pTouch传递对象
CAEvent*pEvent此参数待定

解释:鼠标移出


CATableViewCell 属性介绍

ContentView

类型:CAView*

解释:内容视图。get{}。


BackgroundView

类型:CAView*

解释:背景视图。set/get{}。


ReuseIdentifier

类型:std::string

解释:重用标识符。set/get{}。


Section

类型:unsigned int

解释:section。get{}。


Row

类型:unsigned int

解释:cell。get{}。


ControlStateEffect

类型:bool

解释:控制状态。is/set{}。


AllowsSelected

类型:bool

解释:允许选择。is/set{}。


CATableViewCell 方法介绍

static CATableViewCell* create(const std::string& reuseIdentifier);

返回值:static CATableViewCell*

参数:

类型
参数名说明
std::stringreuseIdentifier重用标识符

解释:创建,默认Frame为(0,0,0,0)


virtual bool initWithReuseIdentifier(const std::string& reuseIdentifier);

返回值:virtual bool

参数:

类型
参数名说明
std::stringreuseIdentifier重用标识符

解释:重用标识符初始化


CATableViewDelegate 方法说明

virtual void tableViewDidSelectRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row);

返回值:virtual void

参数:

类型
参数名说明
CATableViewtable当前tableView
unsigned intsectioncell所属的区域
unsigned introwcell所在行数

解释:选中cell时调用


virtual void tableViewDidDeselectRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row);

返回值:virtual void

参数:

类型
参数名说明
CATableViewtable当前tableView
unsigned intsectioncell所属的区域
unsigned introwcell所在行数

解释:取消选择cell时调用


CATableViewDataSource 方法说明

virtual CATableViewCell* tableCellAtIndex(CATableView* table, const DSize& cellSize, unsigned int section, unsigned int row);

返回值:virtual CATableViewCell*

参数:

类型
参数名说明
CATableViewtable当前tableView
DSizecellSizecell大小
unsigned intsectioncell所属的区域
unsigned introwcell所在行数

解释:获取指定cell


virtual unsigned int tableViewHeightForRowAtIndexPath(CATableView* table, unsigned int section, unsigned int row);

返回值:virtual unsigned int

参数:

类型
参数名说明
CATableViewtable当前tableView
unsigned intsectioncell所属的区域
unsigned introwcell所在行数

解释:获取指定的cell高度


virtual unsigned int numberOfRowsInSection(CATableView* table, unsigned int section);

返回值:virtual unsigned int

参数:

类型
参数名说明
CATableViewtable当前tableView
unsigned intsectioncell所属的区域

解释:获取对应的section所包含的cell个数


virtual unsigned int numberOfSections(CATableView* table);

返回值:virtual unsigned int

参数:

类型参数名说明
CATableView*table当前tableView

解释:获取section个数


virtual CAView* tableViewSectionViewForHeaderInSection(CATableView* table, const DSize& viewSize, unsigned int section);

返回值:virtual CAView*

参数:

类型参数名说明
CATableView*table当前tableView
const DSize&viewSize视图大小
unsigned intsectioncell所属的区域

解释:在tableView中通过索引获取头部Section


virtual unsigned int tableViewHeightForHeaderInSection(CATableView* table, unsigned int section);

返回值:virtual unsigned int

参数:

类型参数名说明
CATableView*table当前tableView
unsigned intsectioncell所属的区域

解释:在tableView中通过索引获取头部Section高度


virtual CAView* tableViewSectionViewForFooterInSection(CATableView* table, const DSize& viewSize, unsigned int section);

返回值:virtual CAView*

参数:

类型参数名说明
CATableView*table当前tableView
const DSize&viewSize视图大小
unsigned intsectioncell所属的区域

解释:在tableView中通过索引获取尾部Section


virtual unsigned int tableViewHeightForFooterInSection(CATableView* table, unsigned int section);

返回值:virtual unsigned int

参数:

类型参数名说明
CATableView*table当前tableView
unsigned intsectioncell所属的区域

解释:在tableView中通过索引获取尾部Section高度


virtual void tableViewWillDisplayCellAtIndex(CATableView* table, CATableViewCell* cell, unsigned int section, unsigned int row);

返回值:virtual void

参数:

类型参数名说明
CATableView*table当前tableView
CATableViewCell*cellcell
unsigned intsectioncell所属的区域
unsigned introwcell所在行数

解释:回调当前将要显示的tableView

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号