ส่วนเสริมที่เป็นการ์ดส่วนใหญ่จะสร้างขึ้นจากการ์ดหลายใบที่แสดง "หน้า" ต่างๆ ของอินเทอร์เฟซส่วนเสริม เพื่อให้ผู้ใช้ได้รับประสบการณ์ที่มีประสิทธิภาพ คุณควรใช้การนำทางที่เรียบง่ายและเป็นธรรมชาติระหว่างการ์ดต่างๆ ในส่วนเสริม
เดิมทีเป็นส่วนเสริมของ Gmail การเปลี่ยนระหว่างการ์ดต่างๆ ของ UI จะจัดการได้ด้วยการผลักและเรียกการ์ดไปยังและจากชุดการ์ดเดียว โดยการ์ดบนสุดของกลุ่มที่ Gmail แสดง
ส่วนเสริมของ Google Workspace จะแนะนำ
หน้าแรก
และการ์ดที่ไม่ใช่บริบท ส่วนเสริมของ Google Workspace มีสแต็กการ์ดภายในสำหรับแต่ละการ์ดเพื่อความสะดวก เมื่อเปิดส่วนเสริมในโฮสต์ homepageTrigger
ที่เกี่ยวข้องจะเริ่มทำงานเพื่อสร้างการ์ดหน้าแรกรายการแรกในสแต็ก (การ์ด "หน้าแรก" สีน้ำเงินเข้มในแผนภาพด้านล่าง)
หากไม่ได้กำหนด homepageTrigger
ระบบจะสร้าง แสดง และพุชการ์ดเริ่มต้นไปยังสแต็กที่ไม่ใช่ตามบริบท การ์ดแรกนี้เป็นการ์ดรูท
ส่วนเสริมสามารถสร้างการ์ดที่ไม่ใช่บริบทเพิ่มเติมและดันการ์ดดังกล่าวลงบนสแต็ก ("การ์ดที่พุช" สีน้ำเงินในแผนภาพ) ขณะที่ผู้ใช้ไปยังส่วนต่างๆ ของส่วนเสริม UI ของส่วนเสริมจะแสดงการ์ดบนสุดในกลุ่ม ดังนั้นการพุชการ์ดใหม่ไปยังกองจะเปลี่ยนการแสดงผล และการเปิดการ์ดออกจากกองจะเป็นการแสดงการ์ดก่อนหน้า
หากส่วนเสริมมีทริกเกอร์ตามบริบทที่กำหนดไว้แล้ว เมื่อผู้ใช้ป้อนบริบทดังกล่าว ทริกเกอร์ก็จะเริ่มทำงาน ฟังก์ชันทริกเกอร์จะสร้างการ์ดบริบท แต่การแสดงผลของ UI จะอัปเดตตาม DisplayStyle
ของการ์ดใหม่ ดังนี้
- หาก
DisplayStyle
เป็นREPLACE
(ค่าเริ่มต้น) การ์ดบริบท (การ์ด "บริบท" สีส้มเข้มในแผนภาพ) จะแทนที่การ์ดที่แสดงอยู่ในปัจจุบัน ซึ่งจะเริ่มต้นสแต็กการ์ดใหม่ตามบริบทอย่างมีประสิทธิภาพเหนือสแต็กการ์ดที่ไม่ใช่ตามบริบท และการ์ดบริบทนี้คือการ์ดรูทของสแต็กบริบท - หาก
DisplayStyle
คือPEEK
UI จะสร้างส่วนหัวที่โผล่ขึ้นมาที่ด้านล่างของแถบด้านข้างของส่วนเสริมโดยวางซ้อนการ์ดปัจจุบัน ส่วนหัวของการดูข้อมูลจะแสดงชื่อของการ์ดใหม่ และให้การควบคุมปุ่มผู้ใช้สำหรับตัดสินใจว่าจะดูการ์ดใหม่หรือไม่ หากผู้ใช้คลิกปุ่มดู การ์ดดังกล่าวจะแทนที่การ์ดปัจจุบัน (ตามที่อธิบายไว้ด้านบนด้วยREPLACE
)
คุณสามารถสร้างการ์ดบริบทเพิ่มเติมและดันการ์ดเข้าไปในกองซ้อน ("การ์ดที่พุช" สีเหลืองในแผนภาพ) การอัปเดตกลุ่มการ์ดจะเปลี่ยน UI ของส่วนเสริมให้แสดงการ์ดบนสุด หากผู้ใช้ออกจากบริบท ระบบจะนำการ์ดบริบทในกลุ่มออก และการแสดงผลจะอัปเดตไปยังการ์ดหรือหน้าแรกที่ไม่ใช่ตามบริบทระดับบนสุด
หากผู้ใช้ป้อนบริบทที่ส่วนเสริมไม่ได้กำหนดทริกเกอร์ตามบริบทไว้ ระบบจะไม่สร้างการ์ดใหม่และการ์ดปัจจุบันจะยังคงแสดงอยู่
การดำเนินการ Navigation
ที่อธิบายไว้ด้านล่างจะทำงานกับการ์ดจากบริบทเดียวกันเท่านั้น ตัวอย่างเช่น popToRoot()
จากภายในการ์ดบริบทจะแสดงการ์ดบริบทอื่นๆ ทั้งหมดเท่านั้น และจะไม่ส่งผลต่อการ์ดหน้าแรก
ในทางตรงกันข้าม ผู้ใช้จะใช้ปุ่ม
เพื่อนำทางจากการ์ดบริบทไปยังการ์ดที่ไม่ใช่บริบทได้เสมอวิธีไปยังส่วนต่างๆ
คุณสร้างการเปลี่ยนระหว่างการ์ดได้โดยการเพิ่มหรือนำการ์ดออกจากกองการ์ด คลาส Navigation
มีฟังก์ชันสำหรับพุชและเปิดการ์ดจากกองซ้อน หากต้องการสร้างการนำทางการ์ดที่มีประสิทธิภาพ คุณจะต้องกำหนดค่าวิดเจ็ตให้ใช้การดำเนินการการนำทาง คุณจะพุชหรือแสดงการ์ดหลายใบพร้อมกันได้ แต่จะนำการ์ดหน้าแรกที่พุชเข้าไปในกองแรกออกไม่ได้เมื่อส่วนเสริมเริ่มทำงาน
หากต้องการไปยังการ์ดใหม่เพื่อตอบกลับการโต้ตอบของผู้ใช้กับวิดเจ็ต ให้ทำตามขั้นตอนต่อไปนี้
- สร้างออบเจ็กต์
Action
และเชื่อมโยงกับฟังก์ชัน Callback ที่คุณกำหนด - เรียกใช้ฟังก์ชันตัวแฮนเดิลวิดเจ็ตที่เหมาะสมของวิดเจ็ตเพื่อตั้งค่า
Action
ในวิดเจ็ตนั้น - ใช้ฟังก์ชัน Callback ที่ใช้ในการนำทาง ฟังก์ชันนี้จะกำหนดออบเจ็กต์เหตุการณ์การดำเนินการเป็นอาร์กิวเมนต์ และต้องดำเนินการต่อไปนี้
- สร้างออบเจ็กต์
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 แอปพลิเคชันแสดง
หากมีการ์ดเพียงใบเดียว ระบบจะเพิ่มการ์ดดังกล่าวในสแต็กที่ไม่มีบริบทหรือตามบริบทเป็นการ์ดรูท และ 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();
}