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