ส่วนเสริมที่อิงตามการ์ดส่วนใหญ่สร้างขึ้นโดยใช้การ์ดหลายรายการที่แสดงถึง "หน้า" ต่างๆ ของอินเทอร์เฟซส่วนเสริม เพื่อมอบประสบการณ์ของผู้ใช้ที่มีประสิทธิภาพ คุณควรใช้การนําทางที่เป็นธรรมชาติและเรียบง่ายระหว่างการ์ดในส่วนเสริม
เดิมทีมาจากส่วนเสริม Gmail การเปลี่ยนระหว่างการ์ดต่างๆ ของ UI จะดําเนินการโดยพุชและสลับการ์ดไปยังและจากสแต็กการ์ดเดียวที่มีการ์ดด้านบนของสแต็กที่แสดงโดย Gmail
Google Workspace ส่วนเสริมจะแนะนําหน้าแรกและการ์ดที่ไม่ใช่บริบท เพื่อรองรับการ์ดตามบริบทและไม่เป็นบริบท
Google Workspace ส่วนเสริมมีสแต็กการ์ดภายใน
แต่ละบัตร เมื่อเปิดส่วนเสริมในโฮสต์ homepageTrigger
ที่เกี่ยวข้องจะเริ่มทํางานเพื่อสร้างการ์ดหน้าแรกรายการแรกในสแต็ก (การ์ด "หน้าแรก" สีเข้มในแผนภาพด้านล่าง)
หากไม่ได้กําหนด homepageTrigger
ระบบจะสร้าง แสดง และแสดงการ์ดเริ่มต้นไปยังสแต็กที่ไม่ใช่บริบท การ์ดใบแรกเป็นการ์ดรูท
ส่วนเสริมของคุณสามารถสร้างการ์ดที่ไม่ใช่บริบทเพิ่มเติมและพุชไปยังสแต็ก ("การ์ดที่ถูกพุช" สีน้ําเงินในแผนภาพ) เมื่อผู้ใช้ไปยังส่วนต่างๆ ของส่วนเสริม UI ส่วนเสริมจะแสดงการ์ดยอดนิยมในกลุ่ม ดังนั้น การพุชการ์ดใหม่ไปยังสแต็กจะเปลี่ยนการแสดงผล และการเด้งการ์ดออกจากสแต็กจะแสดงผลการ์ดเป็นการ์ดก่อนหน้า
หากส่วนเสริมมีทริกเกอร์บริบทที่กําหนดไว้ เมื่อผู้ใช้ป้อนบริบทนั้น ทริกเกอร์จะเริ่มทํางาน ฟังก์ชันทริกเกอร์จะสร้างการ์ดตามบริบท แต่จอแสดงผล UI จะอัปเดตตาม DisplayStyle
ของการ์ดใหม่
- หาก
DisplayStyle
เป็นREPLACE
(ค่าเริ่มต้น) การ์ดบริบท (การ์ด "บริบท" สีส้มในแผนภาพ) จะแทนที่การ์ดที่แสดงอยู่ในปัจจุบัน การดําเนินการนี้จะเริ่มต้นสแต็กการ์ดบริบทใหม่ที่ด้านบนของกลุ่มการ์ดที่ไม่ใช่บริบทอย่างมีประสิทธิภาพ และการ์ดบริบทนี้จะเป็นการ์ดรูทของสแต็กตามบริบท - หาก
DisplayStyle
เป็นPEEK
UI จะสร้างส่วนหัวซึ่งปรากฏขึ้นด้านล่างของแถบด้านข้างสําหรับส่วนเสริม โดยวางซ้อนการ์ดปัจจุบันแทน ส่วนหัวของตัวอย่างจะแสดงชื่อการ์ดใหม่และให้การควบคุมปุ่มผู้ใช้ที่ช่วยให้ตัดสินใจได้ว่าจะดูการ์ดใหม่หรือไม่ หากคลิกปุ่มดู การ์ดจะแทนที่การ์ดปัจจุบัน (ตามที่อธิบายไว้ข้างต้นด้วยREPLACE
)
คุณสร้างการ์ดตามบริบทเพิ่มเติมและพุชไปยังสแต็ก ("การ์ดพุช" สีเหลืองในแผนภาพได้) การอัปเดตสแต็กการ์ดจะเปลี่ยน UI ส่วนเสริมเพื่อแสดงการ์ดด้านบนสุด หากผู้ใช้ออกจากบริบท ระบบจะนําการ์ดบริบทบนสแต็กออกและจอแสดงผลจะอัปเดตเป็นการ์ดหรือหน้าแรกที่ไม่ใช่บริบทด้านบนสุด
หากผู้ใช้ป้อนบริบทที่ส่วนเสริมไม่ได้กําหนดทริกเกอร์ตามบริบท ระบบจะไม่สร้างการ์ดใหม่และแสดงการ์ดปัจจุบันไว้
การดําเนินการ Navigation
ที่อธิบายไว้ด้านล่างจะดําเนินการกับการ์ดจากบริบทเดียวกันเท่านั้น เช่น
popToRoot()
จากภายในการ์ดบริบทจะแสดงการ์ดบริบทอื่นๆ ทั้งหมดเท่านั้น และจะไม่ส่งผลต่อการ์ดหน้าแรก
ในทางตรงกันข้าม ปุ่ม
จะพร้อมให้นําทางผู้ใช้จากการ์ดบริบทไปยังการ์ดที่ไม่ใช่บริบทเสมอวิธีการนําทาง
คุณสร้างการเปลี่ยนระหว่างการ์ดได้โดยเพิ่มหรือนําการ์ดออกจากสแต็กการ์ด คลาส Navigation
มีฟังก์ชันในการพุชและป๊อปอัปการ์ดจากสแต็ก หากต้องการสร้างการนําทางในการ์ดที่มีประสิทธิภาพ คุณจะต้องกําหนดค่าวิดเจ็ตเพื่อใช้การดําเนินการในการนําทาง คุณสามารถพุชหรือป๊อปการ์ดหลายรายการพร้อมกัน แต่จะนําการ์ดหน้าแรกที่พุชมาใส่ลงในสแต็กครั้งแรกไม่ได้เมื่อส่วนเสริมเริ่มทํางาน
หากต้องการไปที่การ์ดใหม่เพื่อไม่ให้ผู้ใช้โต้ตอบกับวิดเจ็ต ให้ทําตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์
Action
และเชื่อมโยงกับฟังก์ชันเรียกกลับที่คุณกําหนด - เรียกฟังก์ชันตัวแฮนเดิลวิดเจ็ตที่เหมาะสมของวิดเจ็ตเพื่อตั้งค่า
Action
ในวิดเจ็ตนั้น - ใช้ฟังก์ชันเรียกกลับที่ดําเนินการการนําทาง ฟังก์ชันนี้จะได้รับออบเจ็กต์เหตุการณ์การดําเนินการเป็นอาร์กิวเมนต์และต้องดําเนินการต่อไปนี้
- สร้างออบเจ็กต์
Navigation
เพื่อกําหนดการเปลี่ยนแปลงการ์ด ออบเจ็กต์Navigation
รายการเดียวอาจมีขั้นตอนการนําทางหลายรายการได้ ซึ่งจะดําเนินการตามลําดับที่เพิ่มในออบเจ็กต์ - สร้างออบเจ็กต์
ActionResponse
โดยใช้คลาสActionResponseBuilder
และออบเจ็กต์Navigation
- แสดงผล
ActionResponse
ที่สร้างขึ้นใหม่
- สร้างออบเจ็กต์
เมื่อสร้างการควบคุมการนําทาง ให้ใช้ฟังก์ชันออบเจ็กต์ Navigation
ต่อไปนี้
การทำงาน | คำอธิบาย |
---|---|
Navigation.pushCard(Card) |
พุชการ์ดไปยังสแต็กปัจจุบัน ซึ่งจะเป็นการสร้างการ์ดให้เสร็จสมบูรณ์ก่อน |
Navigation.popCard() |
นําการ์ด 1 ใบออกจากด้านบนของสแต็ก เทียบเท่ากับการคลิกลูกศรย้อนกลับในแถวส่วนหัวส่วนเสริม การดําเนินการนี้จะไม่นําการ์ดรูทออก |
Navigation.popToRoot() |
นําการ์ดทั้งหมดออกจากสแต็ก ยกเว้นการ์ดรูท รีเซ็ตสแต็กการ์ดเป็นค่าเริ่มต้น |
Navigation.popToNamedCard(String) |
แสดงการ์ดจากสแต็กจนกว่าจะไปถึงการ์ดที่มีชื่อที่ระบุหรือการ์ดรูทของสแต็ก คุณกําหนดชื่อให้กับการ์ดได้โดยใช้ฟังก์ชัน CardBuilder.setName(String) |
Navigation.updateCard(Card) |
แทนที่บัตรปัจจุบันในตําแหน่งปัจจุบันหรือไม่ โดยการรีเฟรชการ์ดที่แสดงใน UI |
แนวทางปฏิบัติแนะนําสําหรับการนําทาง
หากการโต้ตอบของผู้ใช้หรือเหตุการณ์ใดควรส่งผลให้เกิดการแสดงการ์ดอีกครั้งในบริบทเดียวกัน ให้ใช้เมธอด Navigation.pushCard()
, Navigation.popCard()
และ Navigation.updateCard()
เพื่อแทนที่การ์ดที่มีอยู่ หากการโต้ตอบของผู้ใช้หรือเหตุการณ์ใดควรส่งผลให้เกิดการแสดงการ์ดอีกครั้งในบริบทอื่น ให้ใช้ ActionResponseBuilder.setStateChanged()
เพื่อบังคับให้ส่วนเสริมของคุณแสดงใหม่ในบริบทเหล่านั้น
ตัวอย่างการนําทางมีดังต่อไปนี้
- หากการโต้ตอบหรือเหตุการณ์เปลี่ยนสถานะของการ์ดปัจจุบัน (เช่น การเพิ่มงานลงในรายการงาน) ให้ใช้
updateCard()
- หากการโต้ตอบหรือกิจกรรมให้รายละเอียดเพิ่มเติมหรือแจ้งให้ผู้ใช้ดําเนินการเพิ่มเติม (เช่น คลิกที่ชื่อรายการเพื่อดูรายละเอียดเพิ่มเติม หรือกดปุ่มเพื่อสร้างกิจกรรมในปฏิทินใหม่) ให้ใช้
pushCard()
เพื่อแสดงหน้าใหม่พร้อมทั้งอนุญาตให้ผู้ใช้ออกจากหน้าเว็บใหม่โดยใช้ปุ่มย้อนกลับ - หากสถานะการโต้ตอบหรือการอัปเดตเหตุการณ์ในการ์ดก่อนหน้า (เช่น การอัปเดตชื่อของรายการด้วยมุมมองรายละเอียด) ให้ใช้รายละเอียดอย่าง
popCard()
,popCard()
,pushCard(previous)
และpushCard(current)
เพื่ออัปเดตการ์ดก่อนหน้าและการ์ดปัจจุบัน
กําลังรีเฟรชการ์ด
Google Workspace ส่วนเสริมช่วยให้ผู้ใช้รีเฟรชการ์ดได้โดยการเรียกใช้ฟังก์ชันทริกเกอร์ Apps Script ที่ลงทะเบียนไว้ในไฟล์ Manifest อีกครั้ง ผู้ใช้เรียกใช้การรีเฟรชนี้ผ่านรายการในเมนูของส่วนเสริม:
ระบบจะเพิ่มการดําเนินการนี้ลงในการ์ดที่สร้างโดยฟังก์ชันทริกเกอร์ homepageTrigger
หรือ contextualTrigger
โดยอัตโนมัติตามที่ระบุไว้ในไฟล์ Manifest
ของส่วนเสริม ("ราก" ของสแต็กการ์ดตามบริบทและที่ไม่ใช่บริบท)
การส่งคืนบัตรหลายใบ
ฟังก์ชันหน้าแรกหรือฟังก์ชันทริกเกอร์ตามบริบทใช้เพื่อสร้างและแสดงผลออบเจ็กต์ Card
รายการเดียว หรืออาร์เรย์ของออบเจ็กต์ Card
ที่ UI ของแอปพลิเคชันแสดง
หากมีการ์ดเพียง 1 รายการ ระบบจะเพิ่มการ์ดดังกล่าวไปยังสแต็กที่ไม่ใช่บริบทหรือบริบทเป็นการ์ดรูท และ UI ของแอปพลิเคชันโฮสต์จะแสดงการ์ดดังกล่าว
หากอาร์เรย์ที่แสดงผลมีออบเจ็กต์ Card
ที่สร้างขึ้นมากกว่า 1 รายการ แอปพลิเคชันโฮสต์จะแสดงการ์ดใหม่แทน ซึ่งประกอบด้วยรายการส่วนหัวของการ์ดแต่ละรายการ เมื่อผู้ใช้คลิกส่วนหัวเหล่านั้น
UI จะแสดงการ์ดที่เกี่ยวข้อง
เมื่อผู้ใช้เลือกการ์ดจากรายการ ระบบจะพุชการ์ดดังกล่าวไปยังสแต็กปัจจุบันและแอปพลิเคชันโฮสต์จะแสดงการ์ด ปุ่ม
จะส่งผู้ใช้กลับไปยังรายการส่วนหัวของการ์ดการจัดเรียงการ์ด "แนวราบ" นี้จะใช้งานได้ดีหากส่วนเสริมของคุณไม่จําเป็นต้องมีการเปลี่ยนระหว่างการ์ดที่คุณสร้าง แต่ในกรณีส่วนใหญ่ วิธีที่ดีที่สุดคือการเปลี่ยนการเปลี่ยนการ์ดโดยตรง และให้หน้าแรกและฟังก์ชันทริกเกอร์บริบทแสดงออบเจ็กต์การ์ดเดียว
ตัวอย่าง
นี่คือตัวอย่างที่แสดงวิธีสร้างการ์ดหลายใบด้วยปุ่มการนําทางที่สลับไปมาระหว่างการ์ดต่างๆ คุณสามารถเพิ่มการ์ดเหล่านี้เข้าไปในสแต็กตามบริบทหรือบริบทที่ไม่ใช่บริบท โดยพุชการ์ดที่แสดงผลโดย createNavigationCard()
ในหรือนอกบริบทที่เจาะจง
/**
* Create the top-level card, with buttons leading to each of three
* 'children' cards, as well as buttons to backtrack and return to the
* root card of the stack.
* @return {Card}
*/
function createNavigationCard() {
// Create a button set with actions to navigate to 3 different
// 'children' cards.
var buttonSet = CardService.newButtonSet();
for(var i = 1; i <= 3; i++) {
buttonSet.addButton(createToCardButton(i));
}
// Build the card with all the buttons (two rows)
var card = CardService.newCardBuilder()
.setHeader(CardService.newCardHeader().setTitle('Navigation'))
.addSection(CardService.newCardSection()
.addWidget(buttonSet)
.addWidget(buildPreviousAndRootButtonSet()));
return card.build();
}
/**
* Create a button that navigates to the specified child card.
* @return {TextButton}
*/
function createToCardButton(id) {
var action = CardService.newAction()
.setFunctionName('gotoChildCard')
.setParameters({'id': id.toString()});
var button = CardService.newTextButton()
.setText('Card ' + id)
.setOnClickAction(action);
return button;
}
/**
* Create a ButtonSet with two buttons: one that backtracks to the
* last card and another that returns to the original (root) card.
* @return {ButtonSet}
*/
function buildPreviousAndRootButtonSet() {
var previousButton = CardService.newTextButton()
.setText('Back')
.setOnClickAction(CardService.newAction()
.setFunctionName('gotoPreviousCard'));
var toRootButton = CardService.newTextButton()
.setText('To Root')
.setOnClickAction(CardService.newAction()
.setFunctionName('gotoRootCard'));
// Return a new ButtonSet containing these two buttons.
return CardService.newButtonSet()
.addButton(previousButton)
.addButton(toRootButton);
}
/**
* Create a child card, with buttons leading to each of the other
* child cards, and then navigate to it.
* @param {Object} e object containing the id of the card to build.
* @return {ActionResponse}
*/
function gotoChildCard(e) {
var id = parseInt(e.parameters.id); // Current card ID
var id2 = (id==3) ? 1 : id + 1; // 2nd card ID
var id3 = (id==1) ? 3 : id - 1; // 3rd card ID
var title = 'CARD ' + id;
// Create buttons that go to the other two child cards.
var buttonSet = CardService.newButtonSet()
.addButton(createToCardButton(id2))
.addButton(createToCardButton(id3));
// Build the child card.
var card = CardService.newCardBuilder()
.setHeader(CardService.newCardHeader().setTitle(title))
.addSection(CardService.newCardSection()
.addWidget(buttonSet)
.addWidget(buildPreviousAndRootButtonSet()))
.build();
// Create a Navigation object to push the card onto the stack.
// Return a built ActionResponse that uses the navigation object.
var nav = CardService.newNavigation().pushCard(card);
return CardService.newActionResponseBuilder()
.setNavigation(nav)
.build();
}
/**
* Pop a card from the stack.
* @return {ActionResponse}
*/
function gotoPreviousCard() {
var nav = CardService.newNavigation().popCard();
return CardService.newActionResponseBuilder()
.setNavigation(nav)
.build();
}
/**
* Return to the initial add-on card.
* @return {ActionResponse}
*/
function gotoRootCard() {
var nav = CardService.newNavigation().popToRoot();
return CardService.newActionResponseBuilder()
.setNavigation(nav)
.build();
}