cocos2dx 3.2键盘操控的列表页的初步实现
一、实现后的目标效果 有图有真相,首先上实现了的效果。 二 、思路 由于要加载较多数据,那么为了使得界面更近流畅,我采用TableView,其中他的Cell是可以复用的。创建10000个也是秒秒钟的事情。 那么使用上下排列的TableView,每个cell自定义三个Item即可
一、实现后的目标效果
有图有真相,首先上实现了的效果。
二 、思路
由于要加载较多数据,那么为了使得界面更近流畅,我采用TableView,其中他的Cell是可以复用的。创建10000个也是秒秒钟的事情。
那么使用上下排列的TableView,每个cell自定义三个Item即可,当然也可以N个,可以自己写好接口。
由于我们想使得tableView可以滚动到指定的cell位置,也就是一格一格滚动,那么我们最好自定义一个tableView继承于系统的tableView.
三 、实现步骤
如果你对于TableView不太熟悉,建议先看官方Testcpp例子.
如果你比较熟悉,那么我就不废话,继续往下讲了。
我们先来自定义一个TableViewcell。也就是自定义一行的内容。我相信这个非常简单。
四、准备工作
我们先来自定义一个TableViewcell。也就是自定义一行的内容。我相信这个非常简单。
cell头文件
class XTableViewCell : public cocos2d::extension::TableViewCell { public: XTableViewCell(); virtual ~XTableViewCell(); CREATE_FUNC(XTableViewCell); /************************************************************************/ /* update item by data */ /************************************************************************/ bool updateItemData(const unsigned int tag, const std::string icon, const std::string name, const std::string size, const std::string downnum, const std::string score); bool setItemSelected(const unsigned int tag,bool isSeleted); CC_CONSTRUCTOR_ACCESS: bool init(); //bool init bool initLayout(); void update(float t); private: cocos2d::Size _cellSize; //the size of cell unsigned char _itemNum; // the number of item };
cell .源文件
///////////////////////////////////////////////////////////////////////////////////////////// /***************************CustomTableViewCell Class**************************************/ //////////////////////////////////////////////////////////////////////////////////////////// XTableViewCell::XTableViewCell():_itemNum(3),_cellSize(Size(1920,275)) { } XTableViewCell::~XTableViewCell() { } bool XTableViewCell::init() { IF_NULL_RETURN_FALSE(Node::init()); IF_NULL_RETURN_FALSE(initLayout()); //scheduleUpdate(); //resumeSchedulerAndActions(); return true; } bool XTableViewCell::initLayout() { auto lout = ui::Layout::create(); IF_NULL_RETURN_FALSE(lout); lout->setLayoutType(ui::Layout::Type::ABSOLUTE); lout->setTouchEnabled(true); lout->setLoopFocus(false); lout->setPassFocusToChild(true); lout->setContentSize(Size(_cellSize.width,200.0f)); this->addChild(lout); lout->setTag(100); lout->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT); lout->setPosition(Vec2(0,75)); for(int j =0;j<_itemnum const std::string txt='StringUtils::format("%dt%d",0,j);//名称后面得重新修改' griditem item="GridItem::create();" if_null_return_false item->setPosition(Vec2(j*600+90,0)); item->setName(txt); lout->addChild(item,1,j); } return true; } void XTableViewCell::update( float t ) { log("XTableViewCell::update"); } bool XTableViewCell::updateItemData( const unsigned int tag, const std::string icon, const std::string name, const std::string size, const std::string downnum, const std::string score ) { auto lout = this->getChildByTag(100); IF_NULL_RETURN_FALSE(lout); auto item = (GridItem*)lout->getChildByTag(tag); IF_NULL_RETURN_FALSE(item); if(""!=icon) { item->updateIcon(icon); } if(""!=name) { item->updateName(name); } if(""!=size) { item->updateSize(size); } if(""!=downnum) { item->updateDownNum(downnum); } if(""!=score) { item->updateScore(score); } return true; } bool XTableViewCell::setItemSelected( const unsigned int tag,bool isSeleted ) { auto lout = this->getChildByTag(100); IF_NULL_RETURN_FALSE(lout); auto item = (GridItem*)lout->getChildByTag(tag); IF_NULL_RETURN_FALSE(item); item->setSelected(isSeleted); return true; }</_itemnum>
里面都实现了什么,其实就是简单的添加了三个自定义Item.
然后,我们自定义一个TableView实现了两个方法。
一个是去实现滚动到指定cell的方法。
另外一个是我使用触摸的时候需要获得当前使用的cell去判断哪个Item位置位于触摸位置。
我们这里只讲键盘的。那么你可能就用不到这个函数了。
代码如下:
class XTableView : public cocos2d::extension::TableView { public: /** * @brief scroll to the Designated cell * @param index --- the idx of Designated cell **/ void scrollToCellIndex(ssize_t index); /*************************************************** * @decripition if you need Analyzing touch item , * maby you will use this function to get used cell ****************************************************/ cocos2d::Vector<:extension::tableviewcell> getCurrentCells() const; };</:extension::tableviewcell>
///////////////////////////////////////////////////////////////////////////////////////////// /***************************XTableView Class**************************************/ //////////////////////////////////////////////////////////////////////////////////////////// void XTableView::scrollToCellIndex( ssize_t index ) { this->getContainer()->stopAllActions(); Vec2 offset = _offsetFromIndex(index)*-1; Vec2 maxOffSet = this->maxContainerOffset(); Vec2 minOffSet = this->minContainerOffset(); float offX = MIN(offset.x,maxOffSet.x); offX = MAX(offX,minOffSet.x); float offY = MIN(offset.y,maxOffSet.y); offY = MAX(offY,minOffSet.y); this->setContentOffset(Vec2(offX,offY),true); } cocos2d::Vector<:extension::tableviewcell> XTableView::getCurrentCells() const { log("used cell count is %d",_cellsUsed.size()); return this->_cellsUsed; }</:extension::tableviewcell>
好了,那么接下来的重点是列表页的实现。
五、页面具体实现
由于篇幅受限,代码内容比较多,相信大家自己分析就能理解,那么先就不废话了,先上代码吧。不懂的或者有好的建议希望可以留言讨论。
头文件。(注:具体数据录入,我自己的已删除,需要的可以添加自己的数据,现在展示的基本只是一个界面)
enum class POS_TYPE { TYPE_0,// right, down and scroll up TYPE_1,//left,right, down and scroll up TYPE_2,//left, down and scroll up TYPE_3,// right,up,down TYPE_4,//left,right,up,down TYPE_5,//left, up,down TYPE_6,// right,up, and scroll down TYPE_7,//left,right,up, and scroll down TYPE_8,//left, up, and scroll down TYPE_9 // can do nothing }; enum class CHANGE_TYPE { LEFT, RIGHT, UP, DOWN, UP_SCROLL, DOWN_SCROLL, NOTHING }; typedef struct { //item idx ,and start from value 0 to _pageX unsigned char idx; //cell idx unsigned int cellIdx; // selected state bool isSelected; /***************************************** * pos in screen like a matrix,such as * (0,0),(1,0),(2,0) * (0,1),(1,1),(2,1) * (0,2),(1,2),(2,2) *****************************************/ unsigned char posX; unsigned char posY; POS_TYPE posType; }itemState; class XGridView :public cocos2d::Layer, public cocos2d::extension::TableViewDataSource, public cocos2d::extension::TableViewDelegate { public: CREATE_FUNC(XGridView); /*** *@brief create a GridView *@ ***/ virtual void scrollViewDidScroll(cocos2d::extension::ScrollView* view); virtual void scrollViewDidZoom(cocos2d::extension::ScrollView* view); virtual void tableCellTouched(cocos2d::extension::TableView* table, cocos2d::extension::TableViewCell* cell); virtual cocos2d::Size tableCellSizeForIndex(cocos2d::extension::TableView *table, ssize_t idx); virtual cocos2d::extension::TableViewCell* tableCellAtIndex(cocos2d::extension::TableView *table, ssize_t idx); virtual ssize_t numberOfCellsInTableView(cocos2d::extension::TableView *table); CC_CONSTRUCTOR_ACCESS: XGridView(); virtual ~XGridView(); virtual bool init(); virtual bool initWithDatas(ssize_t cellTotalNum,const cocos2d::Size tableSize); virtual bool initMoveFoucus(); virtual bool initTable(); virtual bool initProgressBar(); virtual bool initKeyListen(); virtual void initStateMatrix(); virtual void keyHandler(cocos2d::EventKeyboard::KeyCode key); virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *unused_event); virtual void onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *unused_event); virtual void onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *unused_event); virtual void onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *unused_event); virtual void listenItemTouch(cocos2d::Touch *touch, cocos2d::Event *unused_event); void updateBySceenState(); virtual void isItemTouched(cocos2d::Node* item,const cocos2d::Vec2 point); virtual void deCodeByJson(); void update(float t); virtual void onEnterTransitionDidFinish(); //some model function bool isSelectedByIdx(ssize_t mIdx) const; void updateSceenStateByKey(cocos2d::EventKeyboard::KeyCode key); POS_TYPE getPosTypeByXY(unsigned int X_i,unsigned int Y_j); itemState* getSelectedItemState() const; CHANGE_TYPE getChangeType(POS_TYPE posType,cocos2d::EventKeyboard::KeyCode key); void updateMoveFoucs(cocos2d::EventKeyboard::KeyCode key,POS_TYPE pos); void loadPageNumData(unsigned int cellIndx); void keyListenDelay(float t); void updateDalay(float t); void onExit() override; // update cell at idx void updateCellAtIdx(ssize_t idx); // update Item At idx void updateItemAtIdx(ssize_t idx); private: XTableView* _mTable; cocos2d::Sprite* _progressBar; ssize_t _cellTotalNum; cocos2d::Size _tableSize; ssize_t _pageX; ssize_t _pageY; std::vector<:string> _iconImg; std::vector<:string> _appName; std::vector<:string> _appSize; std::vector<:string> _downNum; std::vector<:string> _appScore; //the state of screen,true means selected and false means unselected std::vector<itemstate> _screenState; //the cell of selected idx ssize_t _currentCellIdx; //item idx which in cell unsigned char _selectedItmIdx; bool _isdecoded; unsigned int _itemTotalNum; std::atomic_bool _firstPageUpdate[9]; cocos2d::Vec2 _pos[9]; cocos2d::Sprite* _moveFoucus; bool _keyContrl; long _scrollTime; bool _updateCell; };</itemstate></:string></:string></:string></:string></:string>
USING_NS_CC; USING_NS_CC_EXT; char* dataIndex[]= { "allnum", "appico", //APP ICO Image "apptitle", //APP Name "downnum", //APP Down times "score" , //APP Score "appSize" //APP size }; XGridView::XGridView():_mTable(nullptr),_progressBar(nullptr), _cellTotalNum(100),_tableSize(Size(1920.0f,960.0f)),_moveFoucus(nullptr), _pageX(3),_pageY(3),_gridId(0),_isdecoded(false),_keyContrl(true),_currentCellIdx(0), _selectedItmIdx(0),_itemTotalNum(300),_loadNum(0),_scrollTime(0L),_updateCell(true) { } XGridView::~XGridView() { CC_SAFE_RELEASE(_mTable); CC_SAFE_RELEASE(_progressBar); } bool XGridView::init() { IF_RETURN_FALSE(!initWithDatas(_cellTotalNum,_tableSize)); return true; } bool XGridView::initWithDatas(ssize_t cellTotalNum,const Size tableSize ) { IF_NULL_RETURN_FALSE(Layer::init()); setData(_json); _cellTotalNum = cellTotalNum; _tableSize = tableSize; IF_NULL_RETURN_FALSE(initKeyListen()); IF_NULL_RETURN_FALSE(initMoveFoucus()); IF_NULL_RETURN_FALSE(initTable()); IF_NULL_RETURN_FALSE(initProgressBar()); initStateMatrix(); deCodeJsonById(); return true; } void XGridView::tableCellTouched(TableView* table,TableViewCell* cell ) { log("cell touched at index: %ld", cell->getIdx()); auto lout = (ui::Layout*)cell->getChildByTag(100); IF_RETURN(!lout); for(auto &item : lout->getChildren()) { if(!item) continue; else { if(item==lout->getCurrentFocusedWidget(true)) { ((GridItem*)item)->setSelected(true); //_selectedIdx = cell->getIdx()*_pageX+item->getTag(); } else { ((GridItem*)item)->setSelected(false); } } } } Size XGridView::tableCellSizeForIndex(TableView *table, ssize_t idx ) { return Size(_tableSize.width, _tableSize.height/_pageY); } TableViewCell* XGridView::tableCellAtIndex(TableView *table, ssize_t idx ) { auto string = String::createWithFormat("%ld", idx); TableViewCell *cell = table->dequeueCell(); if (!cell) { cell = XTableViewCell::create(); IF_RETURN_P(!cell,nullptr); cell->autorelease(); return cell; for(unsigned char i=0;i<_pagex if_null_continue ssize_t itemidx="idx*_pageX+i;" if_continue>_iconImg.size()-1||itemIdx>_appName.size()-1); ((XTableViewCell*)cell)->updateItemData(i,_iconImg.at(itemIdx),_appName.at(itemIdx),"5.03M","","7.6"); ((XTableViewCell*)cell)->setItemSelected(i,idx==_currentCellIdx&&i==_selectedItmIdx); } auto label = Label::createWithSystemFont(string->getCString(), "Helvetica", 40.0); IF_NULL_RETURN_P(label,cell); label->setPosition(Vec2::ZERO); label->setAnchorPoint(Vec2::ZERO); label->setTag(123); cell->addChild(label); } else { auto _cellChild = cell->getChildByTag(100); for(unsigned char i=0;i<_pagex if_null_continue ssize_t itemidx="idx*_pageX+i;" if_continue>_iconImg.size()-1||itemIdx>_appName.size()-1); ((XTableViewCell*)cell)->updateItemData(i,_iconImg.at(itemIdx),_appName.at(itemIdx),"5.03M","","7.6"); ((XTableViewCell*)cell)->setItemSelected(i,idx==_currentCellIdx&&i==_selectedItmIdx); } auto label = (Label*)cell->getChildByTag(123); IF_RETURN_P(!label,cell); label->setString(string->getCString()); } return cell; } ssize_t XGridView::numberOfCellsInTableView(TableView *table ) { return _cellTotalNum; } bool XGridView::initTable() { _mTable = (XTableView*)TableView::create(this,_tableSize); IF_RETURN_FALSE(!_mTable); _mTable->setDirection(ScrollView::Direction::VERTICAL); _mTable->setDelegate(this); this->addChild(_mTable); _mTable->setVerticalFillOrder(TableView::VerticalFillOrder::TOP_DOWN); _mTable->reloadData(); return true; } void XGridView::scrollViewDidScroll( cocos2d::extension::ScrollView* view ) { Vec2 pos = view->getContentOffset(); Vec2 _pos = view->getContentSize()-view->getViewSize(); float percent = -(pos.y/_pos.y); // log("scroll percent is : %f", percent); IF_NULL_RETURN(_progressBar); _progressBar->setPositionY(960/2-600/2 +_progressBar->getScaleY()*_progressBar->getContentSize().height +600*percent*(1-_progressBar->getScaleY())); } void XGridView::scrollViewDidZoom( cocos2d::extension::ScrollView* view ) { } bool XGridView::onTouchBegan( Touch *touch, Event *unused_event ) { return true; } void XGridView::onTouchMoved( Touch *touch, Event *unused_event ) { } void XGridView::onTouchEnded( Touch *touch, Event *unused_event ) { listenItemTouch(touch,unused_event); } void XGridView::onTouchCancelled( Touch *touch, Event *unused_event ) { } void XGridView::listenItemTouch( Touch *touch, Event *unused_event ) { auto touchPoint = touch->getLocationInView(); touchPoint = Director::getInstance()->convertToGL(touchPoint); for(auto &e:_mTable->getCurrentCells()) { IF_NULL_CONTINUE(e); log("cell[%d]",e->getIdx()); auto lout = e->getChildByTag(100); IF_NULL_CONTINUE(lout); if(dynamic_cast<:layout>(lout)) { for (auto item:((ui::Layout*)lout)->getChildren()) { isItemTouched(item,touchPoint); } } } } void XGridView::isItemTouched( cocos2d::Node* item,const cocos2d::Vec2 point ) { IF_RETURN(!item); auto gItem = dynamic_cast<griditem>(item); IF_RETURN(!gItem); auto acP = gItem->getAnchorPoint();//item锚点 auto itemPos = gItem->getPosition();//item相对父容器的pos itemPos = gItem->getParent()->convertToWorldSpaceAR(itemPos);//相对于世界的位置 auto itemSize = gItem->getContentSize(); auto itemRect = Rect(itemPos.x,itemPos.y,itemSize.width,itemSize.height); if(itemRect.containsPoint(point)) { gItem->setSelected(true); //_selectedIdx = gItem->getIdx(); //log("_selectedIdx=%d",_selectedIdx); } else { gItem->setSelected(false); } } bool XGridView::initProgressBar() { auto barBg = Sprite::create("grid/progress_bg.png"); IF_NULL_RETURN_FALSE(barBg); barBg->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT); barBg->setPosition(90+600+600+500+80,960/2-600/2); addChild(barBg); _progressBar = Sprite::create("grid/progress_pre.png"); IF_NULL_RETURN_FALSE(_progressBar); _progressBar->setAnchorPoint(Vec2::ANCHOR_TOP_LEFT); addChild(_progressBar); float scaleY = 1; if(_cellTotalNum>_pageY) { //float s = _pageY/_cellTotalNum; scaleY = MAX(_pageY/(_cellTotalNum*1.0f),0.02f); } _progressBar->setScaleY(scaleY); _progressBar->setPosition(90+600+600+500+80,960/2-600/2 +_progressBar->getScaleY()*_progressBar->getContentSize().height +600*1*(1-_progressBar->getScaleY())); return true; } bool XGridView::initKeyListen() { auto listener = EventListenerKeyboard::create(); IF_NULL_RETURN_FALSE(listener); listener->onKeyReleased = [=](EventKeyboard::KeyCode key,Event* event){ keyHandler(key); }; this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener,this); return true; } void XGridView::keyHandler(EventKeyboard::KeyCode key ) { updateSceenStateByKey(key); updateBySceenState(); } void XGridView::initStateMatrix() { IF_NOEMPTY_CLEAR(_screenState); for (unsigned int i = 0; i posType; auto change_Type = getChangeType(p,key); updateMoveFoucs(key,p); auto maxIdx = _screenState.size(); switch (change_Type) { case CHANGE_TYPE::LEFT: log("left"); _selectedItmIdx--; for (unsigned int i = 0;i<maxidx _screenstate _currentcellidx _mtable->updateCellAtIndex(_currentCellIdx); break; case CHANGE_TYPE::RIGHT: log("right"); _selectedItmIdx++; for (unsigned int i = 0;i<maxidx _screenstate _currentcellidx _mtable->updateCellAtIndex(_currentCellIdx); break; case CHANGE_TYPE::UP: log("up"); _currentCellIdx --; for (unsigned int i = 0;i<maxidx _screenstate _currentcellidx _mtable->updateCellAtIndex(_currentCellIdx+1); _mTable->updateCellAtIndex(_currentCellIdx); break; case CHANGE_TYPE::DOWN: log("down"); _currentCellIdx++; for (unsigned int i = 0;i<maxidx _screenstate _currentcellidx _mtable->updateCellAtIndex(_currentCellIdx-1); _mTable->updateCellAtIndex(_currentCellIdx); break; case CHANGE_TYPE::UP_SCROLL: if (!_keyContrl) { return; } if(_keyContrl) { _keyContrl = false; scheduleOnce(schedule_selector(XGridView::keyListenDelay), 0.05f); } log("up_scroll"); _currentCellIdx--; for (unsigned int i = 0;i<maxidx _screenstate _currentcellidx _scrolltime="getCurrentMillionTime();" _mtable->scrollToCellIndex(_currentCellIdx+2); _mTable->updateCellAtIndex(_currentCellIdx+2); _mTable->updateCellAtIndex(_currentCellIdx+1); _mTable->updateCellAtIndex(_currentCellIdx); return; case CHANGE_TYPE::DOWN_SCROLL: if (!_keyContrl) { return; } if(_keyContrl) { _keyContrl = false; scheduleOnce(schedule_selector(XGridView::keyListenDelay), 0.05f); } log("down_scroll"); _currentCellIdx ++; for (unsigned int i = 0;i<maxidx _screenstate _currentcellidx _scrolltime="getCurrentMillionTime();" _mtable->scrollToCellIndex(_currentCellIdx); _mTable->updateCellAtIndex(_currentCellIdx-2); _mTable->updateCellAtIndex(_currentCellIdx-1); _mTable->updateCellAtIndex(_currentCellIdx); return; case CHANGE_TYPE::NOTHING: log("nothing"); return; default: log("default"); return; } //_mTable->reloadData(); } POS_TYPE XGridView::getPosTypeByXY( unsigned int X_i,unsigned int Y_j ) { // if(0==X_i&&0==Y_j) return POS_TYPE::TYPE_0; if(0<x_i return pos_type::type_1 if pos_type::type_2>Y_j) return POS_TYPE::TYPE_3; if(0<x_i>Y_j) return POS_TYPE::TYPE_4; if(_pageX-1==X_i&&0<y_j>Y_j) return POS_TYPE::TYPE_5; // if(0==X_i&&_pageY-1==Y_j) return POS_TYPE::TYPE_6; if(0<x_i return pos_type::type_7 if pos_type::type_8 pos_type::type_9 itemstate xgridview::getselecteditemstate const for e:_screenstate nullptr change_type xgridview::getchangetype pos_type postype key auto pos="(int)posType;" switch case eventkeyboard::keycode change_type::left break change_type::right change_type::up change_type::up_scroll change_type::down _celltotalnum-1 change_type::down_scroll change_type::nothing void xgridview::updatebysceenstate>reloadData(); } void XGridView::deCodeJsonById() { // do some thing to initialize data //... _isdecoded = true; } void XGridView::handlerValueChangge(float t) { for (unsigned char i=0;i<once_load_num if _firstpageupdate false _mtable->updateCellAtIndex(i/_pageX); } } } void XGridView::update( float t ) { Layer::update(t); } void XGridView::onEnterTransitionDidFinish() { Layer::onEnterTransitionDidFinish(); scheduleUpdate(); schedule(schedule_selector(XGridView::updateDalay),0.2f); } bool XGridView::initMoveFoucus() { _moveFoucus = Sprite::create("grid/focus.png"); IF_NULL_RETURN_FALSE(_moveFoucus); addChild(_moveFoucus); _moveFoucus->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT); //_moveFoucus->setPosition(500,500); for (unsigned char i=0;isetPosition(_pos[0]); return true; } void XGridView::updateMoveFoucs( EventKeyboard::KeyCode key,POS_TYPE pos ) { int mPos = (int)pos; float time = 0.1f; int nextPos = -1; switch (key) { case EventKeyboard::KeyCode(KEY_LEFT): if (mPos%_pageX) { nextPos = mPos - 1; } break; case EventKeyboard::KeyCode(KEY_RIGHT): if ((mPos+1)%_pageX) { nextPos = mPos + 1; } break; case EventKeyboard::KeyCode(KEY_UP): if (mPos>_pageX-1) { nextPos = mPos - _pageX; } break; case EventKeyboard::KeyCode(KEY_DOWN): if (mPos<_pagex nextpos="mPos" _pagex break default: if _movefoucus->stopAllActions(); _moveFoucus->runAction(MoveTo::create(time,_pos[nextPos])); } } void XGridView::loadPageNumData(unsigned int cellIndx) { //load data of cell } void XGridView::keyListenDelay( float t ) { _keyContrl = true; } void XGridView::updateDalay( float t ) { if(getCurrentMillionTime()-_scrollTime>500) { loadPageNumData(_currentCellIdx); } } void XGridView::onExit() { NotificationCenter::getInstance()->removeAllObservers(this); this->unscheduleAllSelectors(); Layer::onExit(); } void XGridView::updateCellAtIdx( ssize_t idx ) { for (unsigned int i = idx*_pageX;i<br> <p> </p> <p> <span>http://blog.csdn.net/q229827701/article/details/40619697</span></p> <br> </_pagex></once_load_num></x_i></y_j></x_i></x_i></maxidx></maxidx></maxidx></maxidx></maxidx></maxidx></griditem></:layout></_pagex></_pagex>

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Menurut berita dari laman web ini pada 12 Ogos, VGN melancarkan siri papan kekunci dan tetikus "Elden Ring" berjenama bersama pada 6 Ogos, termasuk papan kekunci, tetikus dan pad tetikus, yang direka dengan tema tersuai bagi siri Lani/Faded One produk Ia telah diletakkan di JD.com, berharga dari 99 yuan. Maklumat produk baharu jenama bersama yang dilampirkan pada tapak ini adalah seperti berikut: Papan Kekunci VGN丨Elden Law Ring S99PRO Papan kekunci ini menggunakan cangkerang aloi aluminium tulen, ditambah dengan struktur penyenyap lima lapisan, menggunakan struktur spring daun GASKET, mempunyai satu PCB berslot kunci, dan bahan PBT tinggi asal, satah belakang diperibadikan aloi aluminium menyokong sambungan tiga mod dan teknologi kependaman rendah SMARTSPEEDX, ia boleh menguruskan berbilang peranti dalam satu hentian, bermula pada 549 yuan; VGN丨Elden French Ring F1PROMAX tetikus wayarles tetikus

Bagaimana untuk melaksanakan log masuk WeChat dwi pada telefon mudah alih Huawei? Dengan kebangkitan media sosial, WeChat telah menjadi salah satu alat komunikasi yang sangat diperlukan dalam kehidupan seharian orang ramai. Walau bagaimanapun, ramai orang mungkin menghadapi masalah: log masuk ke beberapa akaun WeChat pada masa yang sama pada telefon mudah alih yang sama. Bagi pengguna telefon mudah alih Huawei, tidak sukar untuk mencapai log masuk WeChat dwi Artikel ini akan memperkenalkan cara mencapai log masuk WeChat dwi pada telefon mudah alih Huawei. Pertama sekali, sistem EMUI yang disertakan dengan telefon mudah alih Huawei menyediakan fungsi yang sangat mudah - pembukaan dua aplikasi. Melalui fungsi pembukaan dwi aplikasi, pengguna boleh serentak

Bagaimana untuk menetapkan kulit untuk papan kekunci WeChat? Papan Kekunci WeChat ialah perisian kaedah input telefon mudah alih yang sangat pintar Perisian ini mempunyai banyak fungsi mesra pengguna Ia membolehkan pengguna memilih mod input mereka sendiri dan mencari ungkapan yang mereka mahukan secepat mungkin pada perisian ini. Perisian ini juga membolehkan pengguna menukar kulit papan kekunci itu sendiri Ramai pengguna tidak pasti bagaimana untuk menukar kulit Editor di bawah telah menyusun kaedah menukar kulit untuk rujukan anda. Bagaimana untuk menetapkan kulit papan kekunci WeChat Dalam WeChat, SMS atau aplikasi lain yang memerlukan penggunaan papan kekunci pada telefon anda, anda boleh mengklik ikon tetapan kaedah input di penjuru kiri sebelah atas papan kekunci untuk memasuki halaman tetapan untuk melihat pilihan tetapan fungsi untuk pelbagai kaedah input. 2. Klik "Kulit Peribadi" pada halaman tetapan kaedah input.

Menurut berita dari laman web ini pada 29 Februari, Maicong hari ini melancarkan dua versi "Hyacinth Switch" dan "Glazed Ice Cream Switch" untuk papan kekunci mekanikal tiga mod K87 yang mempunyai ciri "Gasket structure, 80% arrangement", aci berkaitan papan kekunci Maklumat harga adalah seperti berikut: Versi "Hyacinth Switch": harga awal ialah 299 yuan versi "Suis Ais Krim Liuguang": harga awal ialah 379 yuan Menurut laporan, siri papan kekunci menggunakan struktur Gasket, 87-kunci % susunan, peralihan kunci penuh dan terma sokongan Untuk memasang dan mencabut plag, ia mendakwa menggunakan "kapkunci PBT dua warna asal/MDA", menggunakan PCB berslot kunci tunggal 1.2mm (kedudukan lampu bawah), dilengkapi dengan RGB kesan pencahayaan, dan mempunyai reka bentuk papan nama penyerapan magnetik. Selain itu, papan kekunci ini dilengkapi dengan bateri 6000 mAh dan kelewatan tanpa wayar 3ms Saiz dan saiz papan kekunci rasmi belum diumumkan.

Pengguna papan kekunci mudah alih Apple ingin menyediakan kaedah input tulisan tangan, tetapi tidak tahu cara melakukannya sebenarnya sangat mudah Pengguna boleh terus memilih kaedah input tulisan tangan dalam tetapan papan kekunci telefon kaedah input tulisan tangan. Cara menetapkan kaedah input tulisan tangan pada papan kekunci telefon mudah alih Apple A: Dayakan kaedah input tulisan tangan terus dalam tetapan papan kekunci 1. Apabila pengguna Apple menggunakan kaedah input, kaedah input tulisan tangan didayakan secara lalai. 2. Pengguna hanya perlu klik dan tahan sudut kiri bawah untuk memilih kaedah input tulisan tangan semasa menaip. 3. Jika pengguna tidak mempunyai kaedah input tulisan tangan dalam telefon bimbitnya, dia juga boleh menambahnya secara manual. 4. Pengguna memasuki tetapan, mencari tetapan papan kekunci universal dan menambah pilihan input tulisan tangan pada papan kekunci pertama. 5. Gunakan kaedah input tulisan tangan untuk

Bagaimana untuk melaksanakan fungsi klon WeChat pada telefon mudah alih Huawei Dengan populariti perisian sosial dan penekanan yang semakin meningkat terhadap privasi dan keselamatan orang ramai, fungsi klon WeChat telah beransur-ansur menjadi tumpuan perhatian. Fungsi klon WeChat boleh membantu pengguna log masuk ke berbilang akaun WeChat pada telefon mudah alih yang sama pada masa yang sama, menjadikannya lebih mudah untuk diurus dan digunakan. Tidak sukar untuk melaksanakan fungsi klon WeChat pada telefon mudah alih Huawei Anda hanya perlu mengikuti langkah berikut. Langkah 1: Pastikan versi sistem telefon mudah alih dan versi WeChat memenuhi keperluan Pertama, pastikan versi sistem telefon mudah alih Huawei anda telah dikemas kini kepada versi terkini, serta Apl WeChat.

Menurut berita dari laman web ini pada 19 Julai, papan kekunci mekanikal tiga mod Lingbao K87/PRO akan dijual pada pukul 8 malam ini. Perbezaan utama antara kedua-dua versi adalah perbezaan aci/warna/bateri dilengkapi dengan Bateri 4000 mAh, versi PRO dilengkapi dengan bateri 8000 mAh Maklumat harga yang disusun oleh laman web ini adalah seperti berikut: K87 Light Cloud White: 99 yuan K87 Night Purple/Xiaguang Purple/Sunny Mountain Blue: 149 yuan K87. Dust Grey/Star Daisy Purple: 199 yuan K87PRO : 249 yuan Menurut laporan, papan kekunci ini menggunakan struktur Gasket, menggunakan susun atur 80%, tersedia dalam pelbagai warna, mempunyai lampu RGB cahaya rendah terbina dalam, dan menyokong sambungan tiga mod 2.4G (1KHz)/berwayar (1KHz)/Bluetooth (125Hz) ). Dari segi spesifikasi, papan kekunci siri adalah pilihan

Menurut berita dari laman web ini pada 31 Mac, Aitou baru-baru ini melancarkan model papan kekunci paksi magnet 87 kunci "NA87MAG" di JD.com Harga standard ialah 219 yuan Jika anda membayar deposit 10 yuan, anda akan mendapat diskaun serta-merta daripada 20 yuan pada pembayaran akhir Harga sebenar ialah 199 yuan. Menurut laporan, papan kekunci ini menggunakan struktur Asat dan didakwa memberikan "kualiti bunyi menaip tahap HIFI dan rasa lasak yang konsisten. Pengguna juga boleh melaraskan rasa papan kekunci dengan menggantikan pad yang berbeza untuk mencapai penyesuaian daripada yang sukar kepada lembut." Keperluan pertukaran. Selain itu, papan kekunci ini turut dilengkapi dengan "struktur dalaman permainan tiga dimensi", yang dikatakan mampu menumpukan bunyi setiap kekunci melalui reka bentuk tertutup kekunci tunggal dalam format papan catur, seterusnya "mencapai tiga dimensi. pengoptimuman bunyi"; ia juga mempunyai 16.8 juta warna cahaya RGB. Selain itu, papan kekunci ini menampilkan Le
