diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml index c24850d847..211e1ff37f 100644 --- a/AndroidManifest-common.xml +++ b/AndroidManifest-common.xml @@ -20,7 +20,6 @@ - + + + "কোনো শ্বৰ্টকাট বাছনি কৰিবলৈ স্পৰ্শ কৰি ৰাখক।" + "কোনো শ্বৰ্টকাট বাছনি কৰিবলৈ দুবাৰ টিপি ৰাখক বা নিজৰ উপযোগিতা অনুসৰি বনোৱা কাৰ্যসমূহ ব্যৱহাৰ কৰক।" + "শ্বৰ্টকাটসমূহ" + "%1$s শ্বৰ্টকাটসমূহ" + diff --git a/go/res/values-az-rAZ/strings.xml b/go/res/values-az-rAZ/strings.xml new file mode 100644 index 0000000000..c4b8cb7801 --- /dev/null +++ b/go/res/values-az-rAZ/strings.xml @@ -0,0 +1,26 @@ + + + + + "Qısayolu seçmək üçün toxunub saxlayın." + "Qısayolu seçmək üçün iki dəfə basıb saxlayın və ya fərdi əməliyyatlardan istifadə edin." + "Qısayollar" + "%1$s qısayolları" + diff --git a/go/res/values-be-rBY/strings.xml b/go/res/values-be-rBY/strings.xml new file mode 100644 index 0000000000..4189e35fa0 --- /dev/null +++ b/go/res/values-be-rBY/strings.xml @@ -0,0 +1,26 @@ + + + + + "Дакраніцеся і ўтрымлiвайце ярлык, каб дадаць яго." + "Дакраніцеся двойчы і ўтрымлівайце, каб выбраць ярлык або выкарыстоўваць спецыяльныя дзеянні." + "Ярлыкі" + "Ярлыкі %1$s" + diff --git a/go/res/values-bn-rBD/strings.xml b/go/res/values-bn-rBD/strings.xml new file mode 100644 index 0000000000..c56c925a29 --- /dev/null +++ b/go/res/values-bn-rBD/strings.xml @@ -0,0 +1,26 @@ + + + + + "কোনও শর্টকাট বেছে নিতে টাচ করে ধরে রাখুন।" + "কোনও শর্টকাট বেছে নিতে ডাবল ট্যাপ করে ধরে রাখুন অথবা কাস্টম ক্রিয়াগুলি ব্যবহার করুন।" + "শর্টকাট" + "%1$s এর শর্টকাট" + diff --git a/go/res/values-bs-rBA/strings.xml b/go/res/values-bs-rBA/strings.xml new file mode 100644 index 0000000000..3141b9d8fd --- /dev/null +++ b/go/res/values-bs-rBA/strings.xml @@ -0,0 +1,26 @@ + + + + + "Dodirnite i držite da uzmete prečicu." + "Dodirnite dvaput i držite da uzmete prečicu ili koristite prilagođene akcije." + "Prečice" + "Prečice aplikacije %1$s" + diff --git a/go/res/values-bs/strings.xml b/go/res/values-bs/strings.xml index 7042468b47..3141b9d8fd 100644 --- a/go/res/values-bs/strings.xml +++ b/go/res/values-bs/strings.xml @@ -20,7 +20,7 @@ "Dodirnite i držite da uzmete prečicu." - "Dvaput dodirnite i držite da uzmete prečicu ili koristite prilagođene akcije." + "Dodirnite dvaput i držite da uzmete prečicu ili koristite prilagođene akcije." "Prečice" "Prečice aplikacije %1$s" diff --git a/go/res/values-et-rEE/strings.xml b/go/res/values-et-rEE/strings.xml new file mode 100644 index 0000000000..2513e65a33 --- /dev/null +++ b/go/res/values-et-rEE/strings.xml @@ -0,0 +1,26 @@ + + + + + "Otsetee valimiseks puudutage seda pikalt." + "Topeltpuudutage ja hoidke otsetee valimiseks või kohandatud toimingute kasutamiseks." + "Otseteed" + "Rakenduse %1$s otseteed" + diff --git a/go/res/values-eu-rES/strings.xml b/go/res/values-eu-rES/strings.xml new file mode 100644 index 0000000000..9949ef091d --- /dev/null +++ b/go/res/values-eu-rES/strings.xml @@ -0,0 +1,26 @@ + + + + + "Eduki sakatuta lasterbide bat aukeratzeko." + "Sakatu birritan eta eduki sakatuta lasterbide bat aukeratzeko edo ekintza pertsonalizatuak erabiltzeko." + "Lasterbideak" + "%1$s aplikazioaren lasterbidea" + diff --git a/go/res/values-gl-rES/strings.xml b/go/res/values-gl-rES/strings.xml new file mode 100644 index 0000000000..31621d5c2c --- /dev/null +++ b/go/res/values-gl-rES/strings.xml @@ -0,0 +1,26 @@ + + + + + "Mantén premido un atallo para seleccionalo." + "Toca dúas veces e mantén premido para seleccionar un atallo ou utiliza accións personalizadas." + "Atallos" + "Atallos da aplicación %1$s" + diff --git a/go/res/values-gu-rIN/strings.xml b/go/res/values-gu-rIN/strings.xml new file mode 100644 index 0000000000..bdb549ff7f --- /dev/null +++ b/go/res/values-gu-rIN/strings.xml @@ -0,0 +1,26 @@ + + + + + "એક શૉર્ટકટ ચૂંટવા ટૅપ કરી રાખો." + "એક શૉર્ટકટ ચૂંટવા અથવા કોઈ કસ્ટમ ક્રિયાઓનો ઉપયોગ કરવા માટે બે વાર ટૅપ કરી રાખો." + "શૉર્ટકટ" + "%1$s શૉર્ટકટ" + diff --git a/go/res/values-hy-rAM/strings.xml b/go/res/values-hy-rAM/strings.xml new file mode 100644 index 0000000000..4747f6df35 --- /dev/null +++ b/go/res/values-hy-rAM/strings.xml @@ -0,0 +1,26 @@ + + + + + "Կրկնակի հպեք և պահեք՝ դյուրանցում ընտրելու համար։" + "Կրկնակի հպեք և պահեք՝ դյուրանցում ընտրելու համար կամ օգտվեք հարմարեցրած գործողություններից:" + "Դյուրանցումներ" + "%1$s դյուրանցումներ" + diff --git a/go/res/values-is-rIS/strings.xml b/go/res/values-is-rIS/strings.xml new file mode 100644 index 0000000000..b8bb923746 --- /dev/null +++ b/go/res/values-is-rIS/strings.xml @@ -0,0 +1,26 @@ + + + + + "Haltu fingri á flýtileið til að grípa hana." + "Ýttu tvisvar og haltu fingri á flýtileið til að grípa hana eða notaðu sérsniðnar aðgerðir." + "Flýtileiðir" + "%1$s flýtileiðir" + diff --git a/go/res/values-ka-rGE/strings.xml b/go/res/values-ka-rGE/strings.xml new file mode 100644 index 0000000000..1b46534788 --- /dev/null +++ b/go/res/values-ka-rGE/strings.xml @@ -0,0 +1,26 @@ + + + + + "შეეხეთ და დააყოვნეთ მალსახმობის ასარჩევად." + "ორმაგად შეეხეთ და გეჭიროთ მალსახმობის ასარჩევად ან მორგებული მოქმედებების გამოსაყენებლად." + "მალსახმობები" + "%1$s-ის მალსახმობები" + diff --git a/go/res/values-kk-rKZ/strings.xml b/go/res/values-kk-rKZ/strings.xml new file mode 100644 index 0000000000..e909818afc --- /dev/null +++ b/go/res/values-kk-rKZ/strings.xml @@ -0,0 +1,26 @@ + + + + + "Таңбашаны таңдау үшін оны түртіп, ұстап тұрыңыз." + "Таңбашаны таңдау немесе арнаулы әрекеттерді пайдалану үшін екі рет түртіп, ұстап тұрыңыз." + "Таңбашалар" + "%1$s таңбаша" + diff --git a/go/res/values-km-rKH/strings.xml b/go/res/values-km-rKH/strings.xml new file mode 100644 index 0000000000..40082a4b9d --- /dev/null +++ b/go/res/values-km-rKH/strings.xml @@ -0,0 +1,26 @@ + + + + + "ប៉ះ ហើយចុចឲ្យជាប់ដើម្បីរើសផ្លូវកាត់មួយ។" + "ប៉ះពីរដង ហើយចុចឱ្យជាប់ដើម្បីរើសផ្លូវកាត់មួយ ឬប្រើសកម្មភាពផ្ទាល់ខ្លួន។" + "ផ្លូវកាត់" + "ផ្លូវកាត់សម្រាប់ %1$s" + diff --git a/go/res/values-kn-rIN/strings.xml b/go/res/values-kn-rIN/strings.xml new file mode 100644 index 0000000000..9c121fd294 --- /dev/null +++ b/go/res/values-kn-rIN/strings.xml @@ -0,0 +1,26 @@ + + + + + "ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್ ಆರಿಸಲು ಹೋಲ್ಡ್ ಮಾಡಿ." + "ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್ ಆರಿಸಿಕೊಳ್ಳಲು ಹೋಲ್ಡ್ ಮಾಡಿ ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಿ." + "ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು" + "%1$s ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು" + diff --git a/go/res/values-ky-rKG/strings.xml b/go/res/values-ky-rKG/strings.xml new file mode 100644 index 0000000000..4c7e973cef --- /dev/null +++ b/go/res/values-ky-rKG/strings.xml @@ -0,0 +1,26 @@ + + + + + "Кыска жолду тандоо үчүн басып туруңуз." + "Кыска жолду тандоо үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз." + "Кыска жолдор" + "%1$s кыска жол" + diff --git a/go/res/values-lo-rLA/strings.xml b/go/res/values-lo-rLA/strings.xml new file mode 100644 index 0000000000..7864884acc --- /dev/null +++ b/go/res/values-lo-rLA/strings.xml @@ -0,0 +1,26 @@ + + + + + "ແຕະຄ້າງໄວ້ເພື່ອຮັບປຸ່ມລັດ." + "ແຕະສອງເທື່ອຄ້າງໄວ້ເພື່ອຮັບປຸ່ມລັດ ຫຼື ໃຊ້ຄຳສັ່ງແບບກຳນົດເອງ." + "ປຸ່ມລັດ" + "ປຸ່ມລັດ %1$s" + diff --git a/go/res/values-mk-rMK/strings.xml b/go/res/values-mk-rMK/strings.xml new file mode 100644 index 0000000000..52d66b5e28 --- /dev/null +++ b/go/res/values-mk-rMK/strings.xml @@ -0,0 +1,26 @@ + + + + + "Допрете двапати и задржете за да изберете кратенка." + "Допрете двапати и задржете за да изберете кратенка или да користите приспособени дејства." + "Кратенки" + "Кратенки за %1$s" + diff --git a/go/res/values-ml-rIN/strings.xml b/go/res/values-ml-rIN/strings.xml new file mode 100644 index 0000000000..b3c12e16e1 --- /dev/null +++ b/go/res/values-ml-rIN/strings.xml @@ -0,0 +1,26 @@ + + + + + "ഒരു കുറുക്കുവഴി ചേർക്കുന്നതിന് അത് സ്‌പർശിച്ച് പിടിക്കുക." + "ഒരു കുറുക്കുവഴി തിരഞ്ഞെടുക്കാനോ ഇഷ്ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കാനോ രണ്ടുതവണ ടാപ്പുചെയ്ത് പിടിക്കുക." + "കുറുക്കുവഴികൾ" + "%1$s കുറുക്കുവഴികൾ" + diff --git a/go/res/values-mn-rMN/strings.xml b/go/res/values-mn-rMN/strings.xml new file mode 100644 index 0000000000..c89dfd1bdc --- /dev/null +++ b/go/res/values-mn-rMN/strings.xml @@ -0,0 +1,26 @@ + + + + + "Товчлол авах бол удаан дарна уу." + "Товчлол авах болон тохируулсан үйлдлийг ашиглахын тулд хоёр товшоод хүлээнэ үү." + "Товчлол" + "%1$s-н товчлол" + diff --git a/go/res/values-mr-rIN/strings.xml b/go/res/values-mr-rIN/strings.xml new file mode 100644 index 0000000000..2c767b4f19 --- /dev/null +++ b/go/res/values-mr-rIN/strings.xml @@ -0,0 +1,26 @@ + + + + + "शॉर्टकट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा." + "शॉर्टकट निवडण्यासाठी किंवा कस्टम क्रिया वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा." + "शॉर्टकट" + "%1$s शॉर्टकट" + diff --git a/go/res/values-ms-rMY/strings.xml b/go/res/values-ms-rMY/strings.xml new file mode 100644 index 0000000000..42add9a197 --- /dev/null +++ b/go/res/values-ms-rMY/strings.xml @@ -0,0 +1,26 @@ + + + + + "Sentuh & tahan untuk mengambil pintasan." + "Ketik dua kali & tahan untuk mengambil pintasan atau menggunakan tindakan tersuai." + "Pintasan" + "Pintasan %1$s" + diff --git a/go/res/values-my-rMM/strings.xml b/go/res/values-my-rMM/strings.xml new file mode 100644 index 0000000000..5784df63bf --- /dev/null +++ b/go/res/values-my-rMM/strings.xml @@ -0,0 +1,26 @@ + + + + + "လက်ကွက်ဖြတ်လမ်းတစ်ခုကို ရွေးရန် ထိပြီး ဖိထားပါ" + "လက်ကွက်ဖြတ်လမ်းကို ရွေးရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန်နှစ်ချက်တို့ပြီး ဖိထားပါ။" + "ဖြတ်လမ်းလင့်ခ်များ" + "%1$s ဖြတ်လမ်းလင့်ခ်များ" + diff --git a/go/res/values-ne-rNP/strings.xml b/go/res/values-ne-rNP/strings.xml new file mode 100644 index 0000000000..0be0375f3a --- /dev/null +++ b/go/res/values-ne-rNP/strings.xml @@ -0,0 +1,26 @@ + + + + + "कुनै सटकर्ट छनौट गर्न छोइराख्नुहोस्।" + "कुनै सर्टकट छनौट गर्न दुईपटक ट्याप गरेर होल्ड गर्नुहोस् वा रोजेका कारबाहीहरू प्रयोग गर्नुहोस्।" + "सर्टकटहरू" + "%1$s सर्टकटहरू" + diff --git a/go/res/values-or/strings.xml b/go/res/values-or/strings.xml new file mode 100644 index 0000000000..3ec8a72038 --- /dev/null +++ b/go/res/values-or/strings.xml @@ -0,0 +1,26 @@ + + + + + "ଏକ ଶର୍ଟକଟ୍ ଚୟନ କରିବାକୁ ଦାବି ଧରନ୍ତୁ।" + "ଡବଲ୍‌-ଟାପ୍‌ କରନ୍ତୁ ଏବଂ ଏକ ଶର୍ଟକଟ୍ ଚୟନ କରିବାକୁ ଧରି ରଖନ୍ତୁ କିମ୍ୱା କଷ୍ଟମ୍ ପ୍ରକ୍ରିୟା ବ୍ୟବହାର କରନ୍ତୁ।" + "ଶର୍ଟକଟ୍‍" + "%1$sର ଶର୍ଟକଟ୍" + diff --git a/go/res/values-pa-rIN/strings.xml b/go/res/values-pa-rIN/strings.xml new file mode 100644 index 0000000000..c7e4abf3a8 --- /dev/null +++ b/go/res/values-pa-rIN/strings.xml @@ -0,0 +1,26 @@ + + + + + "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।" + "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ ਜਾਂ ਵਿਉਂਂਤੀ ਕਾਰਵਾਈਆਂ ਵਰਤੋ।" + "ਸ਼ਾਰਟਕੱਟ" + "%1$s ਸ਼ਾਰਟਕੱਟ" + diff --git a/go/res/values-si-rLK/strings.xml b/go/res/values-si-rLK/strings.xml new file mode 100644 index 0000000000..4b25c90b0b --- /dev/null +++ b/go/res/values-si-rLK/strings.xml @@ -0,0 +1,26 @@ + + + + + "කෙටි මගක් තෝරා ගැනීමට ස්පර්ශ කර අල්ලාගෙන සිටින්න." + "විජට් එකක් තෝරා ගැනීමට හෝ අභිරුචි භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න." + "කෙටි මං" + "කෙටි මං %1$s" + diff --git a/go/res/values-sq-rAL/strings.xml b/go/res/values-sq-rAL/strings.xml new file mode 100644 index 0000000000..bb74db6b55 --- /dev/null +++ b/go/res/values-sq-rAL/strings.xml @@ -0,0 +1,26 @@ + + + + + "Prek dhe mbaj prekur për të zgjedhur një shkurtore." + "Prek dy herë dhe mbaj prekur për të zgjedhur një shkurtore ose për të përdorur veprimet e personalizuara." + "Shkurtoret" + "%1$s shkurtore" + diff --git a/go/res/values-ta-rIN/strings.xml b/go/res/values-ta-rIN/strings.xml new file mode 100644 index 0000000000..50059b65f9 --- /dev/null +++ b/go/res/values-ta-rIN/strings.xml @@ -0,0 +1,26 @@ + + + + + "குறுக்குவழியைச் சேர்க்க, தொட்டு பிடித்திருக்கவும்." + "குறுக்குவழியை சேர்க்க, இருமுறை தட்டிப் பிடித்திருக்கவும் அல்லது தனிப்பயன் செயல்களைப் பயன்படுத்தவும்." + "குறுக்குவழிகள்" + "%1$s குறுக்குவழிகள்" + diff --git a/go/res/values-te-rIN/strings.xml b/go/res/values-te-rIN/strings.xml new file mode 100644 index 0000000000..0bdf743342 --- /dev/null +++ b/go/res/values-te-rIN/strings.xml @@ -0,0 +1,26 @@ + + + + + "సత్వరమార్గాన్ని ఎంచుకోవడానికి తాకి & నొక్కి ఉంచండి." + "సత్వరమార్గాన్ని ఎంచుకోవడానికి లేదా అనుకూల చర్యలను ఉపయోగించడానికి రెండుసార్లు నొక్కి &ఉంచండి." + "సత్వరమార్గాలు" + "%1$s సత్వరమార్గాలు" + diff --git a/go/res/values-ur-rPK/strings.xml b/go/res/values-ur-rPK/strings.xml new file mode 100644 index 0000000000..46bd823d8e --- /dev/null +++ b/go/res/values-ur-rPK/strings.xml @@ -0,0 +1,26 @@ + + + + + "کوئی شارٹ کٹ منتخب کرنے کیلئے ٹچ کریں اور دبائے رکھیں۔" + "کوئی شارٹ کٹ منتخب کرنے یا حسب ضرورت کاروائیاں استعمال کرنے کیلئے دو بار تھپتھپائیں اور دبائے رکھیں۔" + "شارٹ کٹس" + "%1$s شارٹ کٹس" + diff --git a/go/res/values-uz-rUZ/strings.xml b/go/res/values-uz-rUZ/strings.xml new file mode 100644 index 0000000000..318bc15722 --- /dev/null +++ b/go/res/values-uz-rUZ/strings.xml @@ -0,0 +1,26 @@ + + + + + "Yorliqni tanlab olish uchun bosib turing." + "Ikki marta bosib va bosib turgan holatda yorliqni tanlang yoki maxsus amaldan foydalaning." + "Yorliqlar" + "%1$s ilovasi yorliqlari" + diff --git a/protos/launcher_log.proto b/protos/launcher_log.proto index 4013429b17..cab20a3bee 100644 --- a/protos/launcher_log.proto +++ b/protos/launcher_log.proto @@ -55,6 +55,7 @@ message Target { optional int32 span_y = 14 [default = 1];// Used for ItemType.WIDGET optional int32 predictedRank = 15; optional TargetExtension extension = 16; + optional TipType tip_type = 17; } // Used to define what type of item a Target would represent. @@ -88,6 +89,8 @@ enum ContainerType { NAVBAR = 11; TASKSWITCHER = 12; // Recents UI Container (QuickStep) APP = 13; // Foreground activity is another app (QuickStep) + TIP = 14; // Onboarding texts (QuickStep) + SIDELOADED_LAUNCHER = 15; } // Used to define what type of control a Target would represent. @@ -104,8 +107,17 @@ enum ControlType { VERTICAL_SCROLL = 9; HOME_INTENT = 10; // Deprecated, use enum Command instead BACK_BUTTON = 11; // Deprecated, use enum Command instead - // GO_TO_PLAYSTORE QUICK_SCRUB_BUTTON = 12; + CLEAR_ALL_BUTTON = 13; + CANCEL_TARGET = 14; +} + +enum TipType { + DEFAULT_NONE = 0; + BOUNCE = 1; + SWIPE_UP_TEXT = 2; + QUICK_SCRUB_TEXT = 3; + PREDICTION_TEXT = 4; } // Used to define the action component of the LauncherEvent. @@ -114,8 +126,10 @@ message Action { TOUCH = 0; AUTOMATED = 1; COMMAND = 2; + TIP = 3; // SOFT_KEYBOARD, HARD_KEYBOARD, ASSIST } + enum Touch { TAP = 0; LONGPRESS = 1; @@ -124,7 +138,8 @@ message Action { FLING = 4; PINCH = 5; } - enum Direction { + + enum Direction { NONE = 0; UP = 1; DOWN = 2; @@ -134,11 +149,13 @@ message Action { enum Command { HOME_INTENT = 0; BACK = 1; - ENTRY = 2; // Indicates entry to one of Launcher container type target - // not using the HOME_INTENT - CANCEL = 3; // Indicates that a confirmation screen was cancelled - CONFIRM = 4; // Indicates thata confirmation screen was accepted - STOP = 5; // Indicates onStop() was called (screen time out, power off) + ENTRY = 2; // Indicates entry to one of Launcher container type target + // not using the HOME_INTENT + CANCEL = 3; // Indicates that a confirmation screen was cancelled + CONFIRM = 4; // Indicates thata confirmation screen was accepted + STOP = 5; // Indicates onStop() was called (screen time out, power off) + RECENTS_BUTTON = 6; // Indicates that Recents button was pressed + RESUME = 7; // Indicates onResume() was called } optional Type type = 1; diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index f62d1d6ed5..778866d5ea 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -19,10 +19,10 @@ --> - - + @@ -71,6 +71,12 @@ + + + + diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar index cebeea2b46..53a6ceb4d0 100644 Binary files a/quickstep/libs/sysui_shared.jar and b/quickstep/libs/sysui_shared.jar differ diff --git a/quickstep/res/layout/fallback_recents_activity.xml b/quickstep/res/layout/fallback_recents_activity.xml index 22f8b55a2a..7ecab32016 100644 --- a/quickstep/res/layout/fallback_recents_activity.xml +++ b/quickstep/res/layout/fallback_recents_activity.xml @@ -20,13 +20,23 @@ android:layout_height="match_parent" android:fitsSystemWindows="true"> - + > + - \ No newline at end of file + + + + + diff --git a/quickstep/res/layout/overview_clear_all_button.xml b/quickstep/res/layout/overview_clear_all_button.xml new file mode 100644 index 0000000000..25615e0e2d --- /dev/null +++ b/quickstep/res/layout/overview_clear_all_button.xml @@ -0,0 +1,15 @@ + + + \ No newline at end of file diff --git a/quickstep/res/layout/overview_panel.xml b/quickstep/res/layout/overview_panel.xml index 89e057148f..919afdb37f 100644 --- a/quickstep/res/layout/overview_panel.xml +++ b/quickstep/res/layout/overview_panel.xml @@ -14,14 +14,24 @@ See the License for the specific language governing permissions and limitations under the License. --> - +> + - \ No newline at end of file + + + + \ No newline at end of file diff --git a/res/layout/drag_handle_indicator.xml b/quickstep/res/layout/scrim_view.xml similarity index 69% rename from res/layout/drag_handle_indicator.xml rename to quickstep/res/layout/scrim_view.xml index d5a7b8a038..2cc37f9cc4 100644 --- a/res/layout/drag_handle_indicator.xml +++ b/quickstep/res/layout/scrim_view.xml @@ -13,11 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> - + android:layout_width="match_parent" + android:layout_height="match_parent" + android:id="@+id/scrim_view" /> \ No newline at end of file diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml index b8b360a48e..429f3a28ea 100644 --- a/quickstep/res/layout/task.xml +++ b/quickstep/res/layout/task.xml @@ -24,7 +24,7 @@ android:layout_height="match_parent" android:layout_marginTop="@dimen/task_thumbnail_top_margin" /> - "Verdeelde skerm" "Speld vas" - "Swiep van onder af op om programme te wissel" "Oorsig" "Geen onlangse items nie" - + "Maak toe" + "Vee alles uit" + diff --git a/quickstep/res/values-am/strings.xml b/quickstep/res/values-am/strings.xml index d14e06c9e0..2f303c078b 100644 --- a/quickstep/res/values-am/strings.xml +++ b/quickstep/res/values-am/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "የተከፈለ ማያ ገጽ" "ሰካ" - "መተግበሪያዎችን ለመቀያየር ከግርጌ ወደ ላይ በጣት ጠረግ ያድርጉ" "ማጠቃለያ" "ምንም የቅርብ ጊዜ ንጥሎች የሉም" - + "ዝጋ" + "ሁሉንም አጽዳ" + diff --git a/quickstep/res/values-ar/strings.xml b/quickstep/res/values-ar/strings.xml index 8efffd26db..e22bef47e5 100644 --- a/quickstep/res/values-ar/strings.xml +++ b/quickstep/res/values-ar/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "تقسيم الشاشة" "تثبيت" - "التمرير سريعًا لأعلى من أسفل للتبديل بين التطبيقات" "نظرة عامة" "ليست هناك عناصر تم استخدامها مؤخرًا" - + "إغلاق" + "محو الكل" + diff --git a/quickstep/res/values-as/strings.xml b/quickstep/res/values-as/strings.xml new file mode 100644 index 0000000000..7294f142dd --- /dev/null +++ b/quickstep/res/values-as/strings.xml @@ -0,0 +1,30 @@ + + + + + "বিভাজিত স্ক্ৰীণ" + "পিন" + "অৱলোকন" + "কোনো শেহতীয়া বস্তু নাই" + "বন্ধ কৰক" + "সকলো মচক" + + + diff --git a/quickstep/res/values-az-rAZ/strings.xml b/quickstep/res/values-az-rAZ/strings.xml new file mode 100644 index 0000000000..0546f46508 --- /dev/null +++ b/quickstep/res/values-az-rAZ/strings.xml @@ -0,0 +1,28 @@ + + + + + "Bölünmüş ekran" + "Sancın" + "İcmal" + "Son elementlər yoxdur" + "Bağlayın" + "Hamısını silin" + diff --git a/quickstep/res/values-az/strings.xml b/quickstep/res/values-az/strings.xml index a832f9aa0e..4c2f8ec717 100644 --- a/quickstep/res/values-az/strings.xml +++ b/quickstep/res/values-az/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Bölünmüş ekran" "Sancın" - "Tətbiqləri dəyişmək üçün aşağıdan yuxarı doğru sürüşdürün" "İcmal" "Son elementlər yoxdur" - + "Bağlayın" + "Hamısını silin" + diff --git a/quickstep/res/values-b+sr+Latn/strings.xml b/quickstep/res/values-b+sr+Latn/strings.xml index ba44830be4..bf66aef80e 100644 --- a/quickstep/res/values-b+sr+Latn/strings.xml +++ b/quickstep/res/values-b+sr+Latn/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Podeljeni ekran" "Zakači" - "Prevucite nagore da biste prešli na drugu aplikaciju" "Pregled" "Nema nedavnih stavki" - + "Zatvori" + "Obriši sve" + diff --git a/quickstep/res/values-be-rBY/strings.xml b/quickstep/res/values-be-rBY/strings.xml new file mode 100644 index 0000000000..1e60dd36fd --- /dev/null +++ b/quickstep/res/values-be-rBY/strings.xml @@ -0,0 +1,28 @@ + + + + + "Падзяліць экран" + "Замацаваць" + "Агляд" + "Няма новых элементаў" + "Закрыць" + "Ачысціць усё" + diff --git a/quickstep/res/values-be/strings.xml b/quickstep/res/values-be/strings.xml index df55803afe..48ed4c579b 100644 --- a/quickstep/res/values-be/strings.xml +++ b/quickstep/res/values-be/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Падзяліць экран" "Замацаваць" - "Для пераключэння праграм правядзіце па экране пальцам знізу ўверх" "Агляд" "Няма новых элементаў" - + "Закрыць" + "Ачысціць усё" + diff --git a/quickstep/res/values-bg/strings.xml b/quickstep/res/values-bg/strings.xml index c46245c83b..30308ad0ca 100644 --- a/quickstep/res/values-bg/strings.xml +++ b/quickstep/res/values-bg/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Разделен екран" "Фиксиране" - "Прекарайте пръст нагоре от долната част, за да превключите между приложенията" "Общ преглед" "Няма скорошни елементи" - + "Затваряне" + "Изчистване на всички" + diff --git a/quickstep/res/values-bn-rBD/strings.xml b/quickstep/res/values-bn-rBD/strings.xml new file mode 100644 index 0000000000..a0605d8317 --- /dev/null +++ b/quickstep/res/values-bn-rBD/strings.xml @@ -0,0 +1,28 @@ + + + + + "স্ক্রিন স্প্লিট করুন" + "পিন করুন" + "এক নজরে" + "কোনো সাম্প্রতিক আইটেম নেই" + "বন্ধ করুন" + "সবকিছু খালি করুন" + diff --git a/quickstep/res/values-bn/strings.xml b/quickstep/res/values-bn/strings.xml index 9080072316..80eb639056 100644 --- a/quickstep/res/values-bn/strings.xml +++ b/quickstep/res/values-bn/strings.xml @@ -21,11 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "স্ক্রিন স্প্লিট করুন" "পিন করুন" - "অ্যাপগুলির মধ্যে সুইচ করতে উপর থেকে নিচের দিকে সোয়াইপ করুন" - - - - - + "এক নজরে" + "কোনো সাম্প্রতিক আইটেম নেই" + "বন্ধ করুন" + "সবকিছু খালি করুন" + diff --git a/quickstep/res/values-bs-rBA/strings.xml b/quickstep/res/values-bs-rBA/strings.xml new file mode 100644 index 0000000000..9ffa84806c --- /dev/null +++ b/quickstep/res/values-bs-rBA/strings.xml @@ -0,0 +1,28 @@ + + + + + "Način rada podijeljenog ekrana" + "Zakači" + "Pregled" + "Nema nedavnih stavki" + "Zatvaranje" + "Obriši sve" + diff --git a/quickstep/res/values-bs/strings.xml b/quickstep/res/values-bs/strings.xml index 7e61277d59..201f46144b 100644 --- a/quickstep/res/values-bs/strings.xml +++ b/quickstep/res/values-bs/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Način rada podijeljenog ekrana" "Zakači" - "Prevucite od dolje prema gore za promjenu aplikacije" "Pregled" "Nema nedavnih stavki" - + "Zatvaranje" + "Obriši sve" + diff --git a/quickstep/res/values-ca/strings.xml b/quickstep/res/values-ca/strings.xml index ac77992132..c6b93e3712 100644 --- a/quickstep/res/values-ca/strings.xml +++ b/quickstep/res/values-ca/strings.xml @@ -21,11 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Divideix la pantalla" "Fixa" - "Llisca cap amunt des de la part inferior per canviar d\'aplicació" - - - - - + "Aplicacions recents" + "No hi ha cap element recent" + "Tanca" + "Esborra-ho tot" + diff --git a/quickstep/res/values-cs/strings.xml b/quickstep/res/values-cs/strings.xml index e8c0cb055e..023244c554 100644 --- a/quickstep/res/values-cs/strings.xml +++ b/quickstep/res/values-cs/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Rozdělená obrazovka" "PIN" - "Aplikace můžete přepínat přejetím zdola nahoru" "Přehled" "Žádné nedávné položky" - + "Zavřít" + "Vymazat vše" + diff --git a/quickstep/res/values-da/strings.xml b/quickstep/res/values-da/strings.xml index 6ddb31b364..5d1e763732 100644 --- a/quickstep/res/values-da/strings.xml +++ b/quickstep/res/values-da/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Delt skærm" "Fastgør" - "Stryg opad fra bunden for at skifte apps" "Oversigt" "Ingen nye elementer" - + "Luk" + "Ryd alt" + diff --git a/quickstep/res/values-de/strings.xml b/quickstep/res/values-de/strings.xml index 01c785e60a..cf2f1940ac 100644 --- a/quickstep/res/values-de/strings.xml +++ b/quickstep/res/values-de/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Bildschirm teilen" "Fixieren" - "Zum Wechseln zwischen Apps vom unteren Bildschirmrand nach oben wischen" "Übersicht" "Keine kürzlich verwendeten Elemente" - + "Schließen" + "Alle Apps schließen" + diff --git a/quickstep/res/values-el/strings.xml b/quickstep/res/values-el/strings.xml index 6b2a25f909..9cf05763d6 100644 --- a/quickstep/res/values-el/strings.xml +++ b/quickstep/res/values-el/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Διαχωρισμός οθόνης" "Καρφίτσωμα" - "Σύρετε από κάτω προς τα επάνω για εναλλαγή εφαρμογών" "Επισκόπηση" "Δεν υπάρχουν πρόσφατα στοιχεία" - + "Κλείσιμο" + "Διαγραφή όλων" + diff --git a/quickstep/res/values-en-rAU/strings.xml b/quickstep/res/values-en-rAU/strings.xml index 402499e65d..61d031b5d0 100644 --- a/quickstep/res/values-en-rAU/strings.xml +++ b/quickstep/res/values-en-rAU/strings.xml @@ -21,9 +21,8 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Split screen" "Pin" - "Swipe up from the bottom to switch apps" "Overview" "No recent items" - - + "Close" + "Clear all" diff --git a/quickstep/res/values-en-rGB/strings.xml b/quickstep/res/values-en-rGB/strings.xml index 402499e65d..61d031b5d0 100644 --- a/quickstep/res/values-en-rGB/strings.xml +++ b/quickstep/res/values-en-rGB/strings.xml @@ -21,9 +21,8 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Split screen" "Pin" - "Swipe up from the bottom to switch apps" "Overview" "No recent items" - - + "Close" + "Clear all" diff --git a/quickstep/res/values-en-rIN/strings.xml b/quickstep/res/values-en-rIN/strings.xml index 402499e65d..61d031b5d0 100644 --- a/quickstep/res/values-en-rIN/strings.xml +++ b/quickstep/res/values-en-rIN/strings.xml @@ -21,9 +21,8 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Split screen" "Pin" - "Swipe up from the bottom to switch apps" "Overview" "No recent items" - - + "Close" + "Clear all" diff --git a/quickstep/res/values-es-rUS/strings.xml b/quickstep/res/values-es-rUS/strings.xml index 1b9f926dbb..320892abae 100644 --- a/quickstep/res/values-es-rUS/strings.xml +++ b/quickstep/res/values-es-rUS/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Pantalla dividida" "Fijar" - "Desliza el dedo hacia arriba para cambiar de app" "Recientes" "No hay elementos recientes" - + "Cerrar" + "Borrar todo" + diff --git a/quickstep/res/values-es/strings.xml b/quickstep/res/values-es/strings.xml index c63f1d3ea5..abccec881b 100644 --- a/quickstep/res/values-es/strings.xml +++ b/quickstep/res/values-es/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Dividir pantalla" "Fijar" - "Desliza el dedo hacia arriba desde la parte inferior para cambiar de aplicación" "Aplicaciones recientes" "No hay elementos recientes" - + "Cerrar" + "Borrar todo" + diff --git a/quickstep/res/values-et-rEE/strings.xml b/quickstep/res/values-et-rEE/strings.xml new file mode 100644 index 0000000000..efa68f9c43 --- /dev/null +++ b/quickstep/res/values-et-rEE/strings.xml @@ -0,0 +1,28 @@ + + + + + "Jagatud ekraan" + "Kinnita" + "Ülevaade" + "Hiljutisi üksusi pole" + "Sule" + "Sule kõik" + diff --git a/quickstep/res/values-et/strings.xml b/quickstep/res/values-et/strings.xml index 30199b91ca..5143406ce1 100644 --- a/quickstep/res/values-et/strings.xml +++ b/quickstep/res/values-et/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Jagatud ekraan" "Kinnita" - "Rakenduste vahetamiseks pühkige alaosast üles" "Ülevaade" "Hiljutisi üksusi pole" - + "Sule" + "Sule kõik" + diff --git a/quickstep/res/values-eu-rES/strings.xml b/quickstep/res/values-eu-rES/strings.xml new file mode 100644 index 0000000000..d22242efab --- /dev/null +++ b/quickstep/res/values-eu-rES/strings.xml @@ -0,0 +1,28 @@ + + + + + "Zatitu pantaila" + "Ainguratu" + "Ikuspegi orokorra" + "Ez dago azkenaldi honetako ezer" + "Itxi" + "Garbitu guztiak" + diff --git a/quickstep/res/values-eu/strings.xml b/quickstep/res/values-eu/strings.xml index b6386cd48d..879aa28ceb 100644 --- a/quickstep/res/values-eu/strings.xml +++ b/quickstep/res/values-eu/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Zatitu pantaila" "Ainguratu" - "Aplikazioak aldatzeko, pasatu hatza pantailako behealdetik gora" "Ikuspegi orokorra" "Ez dago azkenaldi honetako ezer" - + "Itxi" + "Garbitu guztiak" + diff --git a/quickstep/res/values-fa/strings.xml b/quickstep/res/values-fa/strings.xml index 52beadd791..b76e9a5656 100644 --- a/quickstep/res/values-fa/strings.xml +++ b/quickstep/res/values-fa/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "تقسیم صفحه" "پین" - "برای تغییر برنامه‌ها،‌ از پایین تند به بالا بکشید" "نمای کلی" "بدون موارد اخیر" - + "بستن" + "پاک کردن همه" + diff --git a/quickstep/res/values-fi/strings.xml b/quickstep/res/values-fi/strings.xml index a27a9cb497..bbfaa11e10 100644 --- a/quickstep/res/values-fi/strings.xml +++ b/quickstep/res/values-fi/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Jaettu näyttö" "Kiinnitä" - "Vaihda sovellusta pyyhkäisemällä alareunasta ylös." "Viimeisimmät" "Ei viimeaikaisia kohteita" - + "Sulje" + "Poista kaikki" + diff --git a/quickstep/res/values-fr-rCA/strings.xml b/quickstep/res/values-fr-rCA/strings.xml index 8a603e98ea..7cad9fca95 100644 --- a/quickstep/res/values-fr-rCA/strings.xml +++ b/quickstep/res/values-fr-rCA/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Écran divisé" "Épingler" - "Balayez l\'écran du bas vers le haut pour changer d\'application" "Aperçu" "Aucun élément récent" - + "Fermer" + "Tout effacer" + diff --git a/quickstep/res/values-fr/strings.xml b/quickstep/res/values-fr/strings.xml index 91922872c6..078ab2b5cd 100644 --- a/quickstep/res/values-fr/strings.xml +++ b/quickstep/res/values-fr/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Écran partagé" "Épingler" - "Balayer l\'écran de bas en haut pour changer d\'application" "Aperçu" "Aucun élément récent" - + "Fermer" + "Tout effacer" + diff --git a/quickstep/res/values-gl-rES/strings.xml b/quickstep/res/values-gl-rES/strings.xml new file mode 100644 index 0000000000..8efc773f49 --- /dev/null +++ b/quickstep/res/values-gl-rES/strings.xml @@ -0,0 +1,28 @@ + + + + + "Pantalla dividida" + "Fixar" + "Visión xeral" + "Non hai elementos recentes" + "Pecha a aplicación" + "Borrar todo" + diff --git a/quickstep/res/values-gl/strings.xml b/quickstep/res/values-gl/strings.xml index 25d3796b49..549d804771 100644 --- a/quickstep/res/values-gl/strings.xml +++ b/quickstep/res/values-gl/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Pantalla dividida" "Fixar" - "Pasa o dedo cara arriba desde a parte inferior para cambiar de aplicacións" "Visión xeral" "Non hai elementos recentes" - + "Pecha a aplicación" + "Borrar todo" + diff --git a/quickstep/res/values-gu-rIN/strings.xml b/quickstep/res/values-gu-rIN/strings.xml new file mode 100644 index 0000000000..cdae86feba --- /dev/null +++ b/quickstep/res/values-gu-rIN/strings.xml @@ -0,0 +1,28 @@ + + + + + "સ્ક્રીનને વિભાજિત કરો" + "પિન કરો" + "ઝલક" + "તાજેતરની કોઈ આઇટમ નથી" + "બંધ કરો" + "બધું સાફ કરો" + diff --git a/quickstep/res/values-gu/strings.xml b/quickstep/res/values-gu/strings.xml index f463e130c9..27235f2bcf 100644 --- a/quickstep/res/values-gu/strings.xml +++ b/quickstep/res/values-gu/strings.xml @@ -21,11 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "સ્ક્રીનને વિભાજિત કરો" "પિન કરો" - "ઍપને સ્વિચ કરવા માટે નીચેથી ઉપર સ્વાઇપ કરો" - - - - - + "ઝલક" + "તાજેતરની કોઈ આઇટમ નથી" + "બંધ કરો" + "બધું સાફ કરો" + diff --git a/quickstep/res/values-hi/strings.xml b/quickstep/res/values-hi/strings.xml index ee933d1bd0..46b404f529 100644 --- a/quickstep/res/values-hi/strings.xml +++ b/quickstep/res/values-hi/strings.xml @@ -21,11 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "स्क्रीन को दो हिस्सों में बाँटना (स्प्लिट स्क्रीन)" "पिन करना" - "ऐप्लिकेशन स्विच करने के लिए सबसे नीचे से ऊपर की ओर स्वाइप करें" - - - - - + "खास जानकारी" + "हाल ही में इस्तेमाल किया गया कोई ऐप्लिकेशन नहीं है" + "बंद करें" + "सभी ऐप्लिकेशन बंद करें" + diff --git a/quickstep/res/values-hr/strings.xml b/quickstep/res/values-hr/strings.xml index a0b734f5ef..b8682608f2 100644 --- a/quickstep/res/values-hr/strings.xml +++ b/quickstep/res/values-hr/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Podijeljeni zaslon" "Prikvači" - "Prijeđite prstom od dna prema gore da biste promijenili aplikaciju" "Pregled" "Nema nedavnih stavki" - + "Zatvori" + "Izbriši sve" + diff --git a/quickstep/res/values-hu/strings.xml b/quickstep/res/values-hu/strings.xml index 8a465e2a3c..60cd6a1ddc 100644 --- a/quickstep/res/values-hu/strings.xml +++ b/quickstep/res/values-hu/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Osztott képernyő" "Rögzítés" - "Ha váltani szeretne az alkalmazások között, csúsztassa gyorsan az ujját a képernyő aljától felfelé" "Áttekintés" "Nincsenek mostanában használt elemek" - + "Bezárás" + "Összes törlése" + diff --git a/quickstep/res/values-hy-rAM/strings.xml b/quickstep/res/values-hy-rAM/strings.xml new file mode 100644 index 0000000000..4afae7de7d --- /dev/null +++ b/quickstep/res/values-hy-rAM/strings.xml @@ -0,0 +1,28 @@ + + + + + "Տրոհել էկրանը" + "Ամրացնել" + "Ընդհանուր տեղեկություններ" + "Վերջին տարրեր չկան" + "Փակել" + "Փակել բոլորը" + diff --git a/quickstep/res/values-hy/strings.xml b/quickstep/res/values-hy/strings.xml index fdfe81895e..c908263b6d 100644 --- a/quickstep/res/values-hy/strings.xml +++ b/quickstep/res/values-hy/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Տրոհել էկրանը" "Ամրացնել" - "Սահեցրեք ներքևից վերև՝ մյուս հավելվածին անցնելու համար" "Ընդհանուր տեղեկություններ" "Վերջին տարրեր չկան" - + "Փակել" + "Փակել բոլորը" + diff --git a/quickstep/res/values-in/strings.xml b/quickstep/res/values-in/strings.xml index 786a10ccda..ff6267c9b3 100644 --- a/quickstep/res/values-in/strings.xml +++ b/quickstep/res/values-in/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Layar terpisah" "Pasang pin" - "Geser dari bawah ke atas untuk beralih aplikasi" "Ringkasan" - "Tidak ada item baru-baru ini" - + "Tidak ada item yang baru dibuka" + "Tutup" + "Hapus semua" + diff --git a/quickstep/res/values-is-rIS/strings.xml b/quickstep/res/values-is-rIS/strings.xml new file mode 100644 index 0000000000..88a92ed96e --- /dev/null +++ b/quickstep/res/values-is-rIS/strings.xml @@ -0,0 +1,28 @@ + + + + + "Skipta skjá" + "Festa" + "Yfirlit" + "Engin nýleg atriði" + "Loka" + "Hreinsa allt" + diff --git a/quickstep/res/values-is/strings.xml b/quickstep/res/values-is/strings.xml index b01a749245..bbb460729c 100644 --- a/quickstep/res/values-is/strings.xml +++ b/quickstep/res/values-is/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Skipta skjá" "Festa" - "Strjúktu upp til að skipta um forrit" - - - + "Yfirlit" + "Engin nýleg atriði" + "Loka" + "Hreinsa allt" + diff --git a/quickstep/res/values-it/strings.xml b/quickstep/res/values-it/strings.xml index 0da2251be2..6175a4720c 100644 --- a/quickstep/res/values-it/strings.xml +++ b/quickstep/res/values-it/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Schermo diviso" "Blocca" - "Scorri verso l\'alto dalla parte inferiore per cambiare app" "Panoramica" "Nessun elemento recente" - + "Chiudi" + "Cancella tutto" + diff --git a/quickstep/res/values-iw/strings.xml b/quickstep/res/values-iw/strings.xml index f7e8338781..9afb842e32 100644 --- a/quickstep/res/values-iw/strings.xml +++ b/quickstep/res/values-iw/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "מסך מפוצל" "הצמדה" - "יש להחליק כלפי מעלה מהחלק התחתון כדי לעבור בין אפליקציות" "מסכים אחרונים" "אין פריטים אחרונים" - + "סגירה" + "ניקוי הכול" + diff --git a/quickstep/res/values-ja/strings.xml b/quickstep/res/values-ja/strings.xml index 7e14d2c689..e478d4acc1 100644 --- a/quickstep/res/values-ja/strings.xml +++ b/quickstep/res/values-ja/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "分割画面" "固定" - "アプリを切り替えるには、下から上にスワイプします" "概要" "最近のアイテムはありません" - + "閉じる" + "すべてクリア" + diff --git a/quickstep/res/values-ka-rGE/strings.xml b/quickstep/res/values-ka-rGE/strings.xml new file mode 100644 index 0000000000..6de8ed9222 --- /dev/null +++ b/quickstep/res/values-ka-rGE/strings.xml @@ -0,0 +1,28 @@ + + + + + "ეკრანის გაყოფა" + "ჩამაგრება" + "მიმოხილვა" + "ბოლოს გამოყენებული ერთეულები არ არის" + "დახურვა" + "ყველას გასუფთავება" + diff --git a/quickstep/res/values-ka/strings.xml b/quickstep/res/values-ka/strings.xml index cf4c661d3d..3d9726c790 100644 --- a/quickstep/res/values-ka/strings.xml +++ b/quickstep/res/values-ka/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ეკრანის გაყოფა" "ჩამაგრება" - "აპების გადასართავად გადაფურცლეთ ქვედა კიდედან ზემოთ" "მიმოხილვა" "ბოლოს გამოყენებული ერთეულები არ არის" - + "დახურვა" + "ყველას გასუფთავება" + diff --git a/quickstep/res/values-kk-rKZ/strings.xml b/quickstep/res/values-kk-rKZ/strings.xml new file mode 100644 index 0000000000..ddd4a77196 --- /dev/null +++ b/quickstep/res/values-kk-rKZ/strings.xml @@ -0,0 +1,28 @@ + + + + + "Экранды бөлу" + "Бекіту" + "Шолу" + "Соңғы элементтер жоқ" + "Жабу" + "Барлығын өшіру" + diff --git a/quickstep/res/values-kk/strings.xml b/quickstep/res/values-kk/strings.xml index f865a0405e..80cab46bbd 100644 --- a/quickstep/res/values-kk/strings.xml +++ b/quickstep/res/values-kk/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Экранды бөлу" "Бекіту" - "Қолданбалар арасында ауысу үшін төменнен жоғары қарай саусақпен сырғытыңыз" "Шолу" "Соңғы элементтер жоқ" - + "Жабу" + "Барлығын өшіру" + diff --git a/quickstep/res/values-km-rKH/strings.xml b/quickstep/res/values-km-rKH/strings.xml new file mode 100644 index 0000000000..65c1dccee3 --- /dev/null +++ b/quickstep/res/values-km-rKH/strings.xml @@ -0,0 +1,28 @@ + + + + + "មុខងារ​បំបែកអេក្រង់" + "ដៅ" + "ទិដ្ឋភាពរួម" + "មិនមានធាតុថ្មីៗទេ" + "បិទ" + "សម្អាត​ទាំងអស់" + diff --git a/quickstep/res/values-km/strings.xml b/quickstep/res/values-km/strings.xml index a35ab26aad..36a9ad98db 100644 --- a/quickstep/res/values-km/strings.xml +++ b/quickstep/res/values-km/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "មុខងារ​បំបែកអេក្រង់" "ដៅ" - "អូស​ពី​ក្រោម​ឡើង​លើ ដើម្បី​ប្ដូរ​កម្មវិធី" "ទិដ្ឋភាពរួម" "មិនមានធាតុថ្មីៗទេ" - + "បិទ" + "សម្អាត​ទាំងអស់" + diff --git a/quickstep/res/values-kn-rIN/strings.xml b/quickstep/res/values-kn-rIN/strings.xml new file mode 100644 index 0000000000..55ccbb0260 --- /dev/null +++ b/quickstep/res/values-kn-rIN/strings.xml @@ -0,0 +1,28 @@ + + + + + "ಪರದೆಯನ್ನು ಬೇರ್ಪಡಿಸಿ" + "ಪಿನ್ ಮಾಡಿ" + "ಅವಲೋಕನ" + "ಯಾವುದೇ ಇತ್ತೀಚಿನ ಐಟಂಗಳಿಲ್ಲ" + "ಮುಚ್ಚಿ" + "ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ" + diff --git a/quickstep/res/values-kn/strings.xml b/quickstep/res/values-kn/strings.xml index dc57df1d35..314638cab2 100644 --- a/quickstep/res/values-kn/strings.xml +++ b/quickstep/res/values-kn/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ಪರದೆಯನ್ನು ಬೇರ್ಪಡಿಸಿ" "ಪಿನ್ ಮಾಡಿ" - "ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಬದಲಿಸಲು ಕೆಳಗಿನಿಂದ ಮೇಲಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ" "ಅವಲೋಕನ" "ಯಾವುದೇ ಇತ್ತೀಚಿನ ಐಟಂಗಳಿಲ್ಲ" - + "ಮುಚ್ಚಿ" + "ಎಲ್ಲವನ್ನೂ ತೆರವುಗೊಳಿಸಿ" + diff --git a/quickstep/res/values-ko/strings.xml b/quickstep/res/values-ko/strings.xml index 36fd122d73..557ee4a01c 100644 --- a/quickstep/res/values-ko/strings.xml +++ b/quickstep/res/values-ko/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "화면 분할" "고정" - "아래에서 위로 스와이프하여 앱을 전환합니다." "최근 사용" "최근 항목이 없습니다." - + "닫기" + "모두 삭제" + diff --git a/quickstep/res/values-ky-rKG/strings.xml b/quickstep/res/values-ky-rKG/strings.xml new file mode 100644 index 0000000000..b788693824 --- /dev/null +++ b/quickstep/res/values-ky-rKG/strings.xml @@ -0,0 +1,28 @@ + + + + + "Экранды бөлүү" + "Кадап коюу" + "Сереп салуу" + "Акыркы колдонмолор жок" + "Жабуу" + "Баарын тазалоо" + diff --git a/quickstep/res/values-ky/strings.xml b/quickstep/res/values-ky/strings.xml index 060a8dd21c..1575af6506 100644 --- a/quickstep/res/values-ky/strings.xml +++ b/quickstep/res/values-ky/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Экранды бөлүү" "Кадап коюу" - "Колдонмолорду которуштуруу үчүн экранды төмөндөн жогору карай сүрүңүз" "Сереп салуу" "Акыркы колдонмолор жок" - + "Жабуу" + "Баарын тазалоо" + diff --git a/quickstep/res/values-lo-rLA/strings.xml b/quickstep/res/values-lo-rLA/strings.xml new file mode 100644 index 0000000000..a83743a7e9 --- /dev/null +++ b/quickstep/res/values-lo-rLA/strings.xml @@ -0,0 +1,28 @@ + + + + + "ແບ່ງໜ້າຈໍ" + "ປັກໝຸດ" + "ພາບຮວມ" + "ບໍ່ມີລາຍການຫຼ້າສຸດ" + "ປິດ" + "ລຶບລ້າງທັງໝົດ" + diff --git a/quickstep/res/values-lo/strings.xml b/quickstep/res/values-lo/strings.xml index 1abb856d97..3e332be0b2 100644 --- a/quickstep/res/values-lo/strings.xml +++ b/quickstep/res/values-lo/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ແບ່ງໜ້າຈໍ" "ປັກໝຸດ" - "ປັດຂຶ້ນຈາກລຸ່ມສຸດເພື່ອສະຫຼັບແອັບ" "ພາບຮວມ" "ບໍ່ມີລາຍການຫຼ້າສຸດ" - + "ປິດ" + "ລຶບລ້າງທັງໝົດ" + diff --git a/quickstep/res/values-lt/strings.xml b/quickstep/res/values-lt/strings.xml index 0c09a94500..4dd2680230 100644 --- a/quickstep/res/values-lt/strings.xml +++ b/quickstep/res/values-lt/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Skaidyti ekraną" "Prisegti" - "Perbraukite aukštyn iš apačios, kad perjungtumėte programas" "Apžvalga" "Nėra jokių naujausių elementų" - + "Uždaryti" + "Išvalyti viską" + diff --git a/quickstep/res/values-lv/strings.xml b/quickstep/res/values-lv/strings.xml index 72d1cb575d..7eb385fa8d 100644 --- a/quickstep/res/values-lv/strings.xml +++ b/quickstep/res/values-lv/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Sadalīt ekrānu" "Piespraust" - "Lai pārslēgtu lietotnes, velciet augšup no apakšdaļas." "Pārskats" "Nav nesenu vienumu." - + "Aizvērt" + "Notīrīt visu" + diff --git a/quickstep/res/values-mk-rMK/strings.xml b/quickstep/res/values-mk-rMK/strings.xml new file mode 100644 index 0000000000..e428b4e1f8 --- /dev/null +++ b/quickstep/res/values-mk-rMK/strings.xml @@ -0,0 +1,28 @@ + + + + + "Поделен екран" + "Прикачување" + "Преглед" + "Нема неодамнешни ставки" + "Затвори" + "Исчисти ги сите" + diff --git a/quickstep/res/values-mk/strings.xml b/quickstep/res/values-mk/strings.xml index 06bf5d0c11..9e959d3170 100644 --- a/quickstep/res/values-mk/strings.xml +++ b/quickstep/res/values-mk/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Поделен екран" "Прикачување" - "Повлечете нагоре од дното за да ги смените апликациите" "Преглед" "Нема неодамнешни ставки" - + "Затвори" + "Исчисти ги сите" + diff --git a/quickstep/res/values-ml-rIN/strings.xml b/quickstep/res/values-ml-rIN/strings.xml new file mode 100644 index 0000000000..4cca447e7d --- /dev/null +++ b/quickstep/res/values-ml-rIN/strings.xml @@ -0,0 +1,28 @@ + + + + + "സ്‌ക്രീൻ വിഭജിക്കുക" + "പിൻ ചെയ്യുക" + "അവലോകനം" + "സമീപകാല ഇനങ്ങൾ ഒന്നുമില്ല" + "അവസാനിപ്പിക്കുക" + "എല്ലാം മായ്‌ക്കുക" + diff --git a/quickstep/res/values-ml/strings.xml b/quickstep/res/values-ml/strings.xml index b936906560..1d7b927a9c 100644 --- a/quickstep/res/values-ml/strings.xml +++ b/quickstep/res/values-ml/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "സ്‌ക്രീൻ വിഭജിക്കുക" "പിൻ ചെയ്യുക" - "ആപ്പുകൾ മാറാൻ താഴെ നിന്ന് മുകളിലേക്ക് സ്വൈപ്പ് ചെയ്യുക" "അവലോകനം" "സമീപകാല ഇനങ്ങൾ ഒന്നുമില്ല" - + "അവസാനിപ്പിക്കുക" + "എല്ലാം മായ്‌ക്കുക" + diff --git a/quickstep/res/values-mn-rMN/strings.xml b/quickstep/res/values-mn-rMN/strings.xml new file mode 100644 index 0000000000..f40f69e315 --- /dev/null +++ b/quickstep/res/values-mn-rMN/strings.xml @@ -0,0 +1,28 @@ + + + + + "Дэлгэцийг хуваах" + "Тогтоох" + "Тойм" + "Сүүлийн үеийн зүйл алга" + "Хаах" + "Бүгдийг устгах" + diff --git a/quickstep/res/values-mn/strings.xml b/quickstep/res/values-mn/strings.xml index 8b92214916..5031388f96 100644 --- a/quickstep/res/values-mn/strings.xml +++ b/quickstep/res/values-mn/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Дэлгэцийг хуваах" "Тогтоох" - "Аппыг сэлгэхийн тулд доороос дээш шударна уу" "Тойм" "Сүүлийн үеийн зүйл алга" - + "Хаах" + "Бүгдийг устгах" + diff --git a/quickstep/res/values-mr-rIN/strings.xml b/quickstep/res/values-mr-rIN/strings.xml new file mode 100644 index 0000000000..938363db0f --- /dev/null +++ b/quickstep/res/values-mr-rIN/strings.xml @@ -0,0 +1,28 @@ + + + + + "विभाजित स्क्रीन" + "पिन करा" + "अवलोकन" + "कोणतेही अलीकडील आयटम नाहीत" + "बंद" + "सर्व साफ करा" + diff --git a/quickstep/res/values-mr/strings.xml b/quickstep/res/values-mr/strings.xml index 596792d103..939963e46e 100644 --- a/quickstep/res/values-mr/strings.xml +++ b/quickstep/res/values-mr/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "विभाजित स्क्रीन" "पिन करा" - "अ‍ॅप्स स्विच करण्यासाठी तळापासून वर स्वाइप करा" "अवलोकन" "कोणतेही अलीकडील आयटम नाहीत" - + "बंद" + "सर्व साफ करा" + diff --git a/quickstep/res/values-ms-rMY/strings.xml b/quickstep/res/values-ms-rMY/strings.xml new file mode 100644 index 0000000000..236fab25c8 --- /dev/null +++ b/quickstep/res/values-ms-rMY/strings.xml @@ -0,0 +1,28 @@ + + + + + "Skrin pisah" + "Semat" + "Ikhtisar" + "Tiada item terbaharu" + "Tutup" + "Kosongkan semua" + diff --git a/quickstep/res/values-ms/strings.xml b/quickstep/res/values-ms/strings.xml index 336aaf6594..0e93bf6c1a 100644 --- a/quickstep/res/values-ms/strings.xml +++ b/quickstep/res/values-ms/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Skrin pisah" "Semat" - "Leret ke atas dari bawah untuk menukar apl" "Ikhtisar" "Tiada item terbaharu" - + "Tutup" + "Kosongkan semua" + diff --git a/quickstep/res/values-my-rMM/strings.xml b/quickstep/res/values-my-rMM/strings.xml new file mode 100644 index 0000000000..e44b904beb --- /dev/null +++ b/quickstep/res/values-my-rMM/strings.xml @@ -0,0 +1,28 @@ + + + + + "မျက်နှာပြင် ခွဲ၍ပြသခြင်း" + "ပင်ထိုးခြင်း" + "အနှစ်ချုပ်" + "မကြာမီကဖွင့်ထားသည်များ မရှိပါ" + "ပိတ်ရန်" + "အားလုံးကို ရှင်းရန်" + diff --git a/quickstep/res/values-my/strings.xml b/quickstep/res/values-my/strings.xml index d71e5fc93f..ebffc3c3b4 100644 --- a/quickstep/res/values-my/strings.xml +++ b/quickstep/res/values-my/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "မျက်နှာပြင် ခွဲ၍ပြသခြင်း" "ပင်ထိုးခြင်း" - "အက်ပ်များပြောင်းရန် အောက်ခြေမှ အပေါ်သို့ပွတ်ဆွဲပါ" "အနှစ်ချုပ်" "မကြာမီကဖွင့်ထားသည်များ မရှိပါ" - + "ပိတ်ရန်" + "အားလုံးကို ရှင်းရန်" + diff --git a/quickstep/res/values-nb/strings.xml b/quickstep/res/values-nb/strings.xml index 504f43ae80..97870b15cc 100644 --- a/quickstep/res/values-nb/strings.xml +++ b/quickstep/res/values-nb/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Delt skjerm" "Fest" - "Sveip opp fra bunnen for å bytte app" "Oversikt" "Ingen nylige elementer" - + "Lukk" + "Fjern alt" + diff --git a/quickstep/res/values-ne-rNP/strings.xml b/quickstep/res/values-ne-rNP/strings.xml new file mode 100644 index 0000000000..bf52604fd2 --- /dev/null +++ b/quickstep/res/values-ne-rNP/strings.xml @@ -0,0 +1,28 @@ + + + + + "स्क्रिन विभाजन गर्नुहोस्" + "पिन गर्नुहोस्" + "परिदृश्य" + "हालसालैको कुनै पनि वस्तु छैन" + "बन्द गर्नुहोस्" + "सबै खाली गर्नुहोस्" + diff --git a/quickstep/res/values-ne/strings.xml b/quickstep/res/values-ne/strings.xml index 7500213890..c9a6c6b894 100644 --- a/quickstep/res/values-ne/strings.xml +++ b/quickstep/res/values-ne/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "स्क्रिन विभाजन गर्नुहोस्" "पिन गर्नुहोस्" - "अनुप्रयोगहरू बदल्न तलबाट माथितिर स्वाइप गर्नुहोस्" "परिदृश्य" "हालसालैको कुनै पनि वस्तु छैन" - + "बन्द गर्नुहोस्" + "सबै खाली गर्नुहोस्" + diff --git a/quickstep/res/values-nl/strings.xml b/quickstep/res/values-nl/strings.xml index 2ba24a6e28..e3acf0dc36 100644 --- a/quickstep/res/values-nl/strings.xml +++ b/quickstep/res/values-nl/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Gesplitst scherm" "Vastzetten" - "Veeg omhoog vanaf de onderkant om tussen apps te wisselen" "Overzicht" "Geen recente items" - + "Sluiten" + "Alles wissen" + diff --git a/quickstep/res/values-or/strings.xml b/quickstep/res/values-or/strings.xml new file mode 100644 index 0000000000..5e5e420ff6 --- /dev/null +++ b/quickstep/res/values-or/strings.xml @@ -0,0 +1,30 @@ + + + + + "ସ୍କ୍ରୀନ୍‌କୁ ଭାଗ କରନ୍ତୁ" + "ପିନ୍‍" + "ସଂକ୍ଷିପ୍ତ ବିବରଣ" + "କୌଣସି ସାମ୍ପ୍ରତିକ ଆଇଟମ୍ ନାହିଁ" + "ବନ୍ଦ କରନ୍ତୁ" + "ସବୁ ଖାଲି କରନ୍ତୁ" + + + diff --git a/quickstep/res/values-pa-rIN/strings.xml b/quickstep/res/values-pa-rIN/strings.xml new file mode 100644 index 0000000000..bc044c808f --- /dev/null +++ b/quickstep/res/values-pa-rIN/strings.xml @@ -0,0 +1,28 @@ + + + + + "ਸਪਲਿਟ ਸਕ੍ਰੀਨ" + "ਪਿੰਨ ਕਰੋ" + "ਰੂਪ-ਰੇਖਾ" + "ਕੋਈ ਹਾਲੀਆ ਆਈਟਮਾਂ ਨਹੀਂ" + "ਬੰਦ ਕਰੋ" + "ਸਭ ਕਲੀਅਰ ਕਰੋ" + diff --git a/quickstep/res/values-pa/strings.xml b/quickstep/res/values-pa/strings.xml index fbcb60cd6f..fec9f03fbe 100644 --- a/quickstep/res/values-pa/strings.xml +++ b/quickstep/res/values-pa/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "ਸਪਲਿਟ ਸਕ੍ਰੀਨ" "ਪਿੰਨ ਕਰੋ" - "ਐਪਾਂ ਵਿੱਚ ਅਦਲਾ-ਬਦਲੀ ਕਰਨ ਲਈ ਹੇਠਾਂ ਤੋਂ ਉੱਪਰ ਵੱਲ ਸਵਾਈਪ ਕਰੋ" "ਰੂਪ-ਰੇਖਾ" "ਕੋਈ ਹਾਲੀਆ ਆਈਟਮਾਂ ਨਹੀਂ" - + "ਬੰਦ ਕਰੋ" + "ਸਭ ਕਲੀਅਰ ਕਰੋ" + diff --git a/quickstep/res/values-pl/strings.xml b/quickstep/res/values-pl/strings.xml index 1ad7070bd5..54196e8465 100644 --- a/quickstep/res/values-pl/strings.xml +++ b/quickstep/res/values-pl/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Podziel ekran" "Przypnij" - "Przesuń palcem z dołu ekranu, by przełączać aplikacje" "Przegląd" "Brak ostatnich elementów" - + "Zamknij" + "Wyczyść wszystko" + diff --git a/quickstep/res/values-pt-rPT/strings.xml b/quickstep/res/values-pt-rPT/strings.xml index a63d32998d..afc6295373 100644 --- a/quickstep/res/values-pt-rPT/strings.xml +++ b/quickstep/res/values-pt-rPT/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Ecrã dividido" "Fixar" - "Deslize rapidamente para cima a partir da parte inferior para alternar entre aplicações." "Vista geral" "Nenhum item recente" - + "Fechar" + "Limpar tudo" + diff --git a/quickstep/res/values-pt/strings.xml b/quickstep/res/values-pt/strings.xml index 05d20e08e0..9e43cd7c0a 100644 --- a/quickstep/res/values-pt/strings.xml +++ b/quickstep/res/values-pt/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Tela dividida" "Fixar" - "Deslize de baixo para cima para alternar entre apps" "Visão geral" "Nenhum item recente" - + "Fechar" + "Limpar tudo" + diff --git a/quickstep/res/values-ro/strings.xml b/quickstep/res/values-ro/strings.xml index 4264370f40..a8889d4b4a 100644 --- a/quickstep/res/values-ro/strings.xml +++ b/quickstep/res/values-ro/strings.xml @@ -21,9 +21,8 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Ecran divizat" "Fixați" - "Glisați de jos în sus pentru a schimba aplicațiile" "Recente" "Niciun element recent" - - + "Închideți" + "Ștergeți tot" diff --git a/quickstep/res/values-ru/strings.xml b/quickstep/res/values-ru/strings.xml index 47ddff53ca..832aa0aa19 100644 --- a/quickstep/res/values-ru/strings.xml +++ b/quickstep/res/values-ru/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Разделить экран" "Блокировать" - "Чтобы переключить приложение, проведите по экрану снизу вверх" "Обзор" - "Недавних приложений нет." - + "Здесь пока ничего нет." + "Закрыть" + "Очистить все" + diff --git a/quickstep/res/values-si-rLK/strings.xml b/quickstep/res/values-si-rLK/strings.xml new file mode 100644 index 0000000000..61bb8ba81c --- /dev/null +++ b/quickstep/res/values-si-rLK/strings.xml @@ -0,0 +1,28 @@ + + + + + "බෙදුම් තිරය" + "අමුණන්න" + "දළ විශ්ලේෂණය" + "මෑත අයිතම නැත" + "වසන්න" + "සියල්ල හිස් කරන්න" + diff --git a/quickstep/res/values-si/strings.xml b/quickstep/res/values-si/strings.xml index a9b1493bb5..61bb8ba81c 100644 --- a/quickstep/res/values-si/strings.xml +++ b/quickstep/res/values-si/strings.xml @@ -21,9 +21,8 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "බෙදුම් තිරය" "අමුණන්න" - "යෙදුම් මාරු කිරීම සඳහා පහළ සිට ස්වයිප් කරන්න" "දළ විශ්ලේෂණය" "මෑත අයිතම නැත" - - + "වසන්න" + "සියල්ල හිස් කරන්න" diff --git a/quickstep/res/values-sk/strings.xml b/quickstep/res/values-sk/strings.xml index fe028554f6..da4585bf1d 100644 --- a/quickstep/res/values-sk/strings.xml +++ b/quickstep/res/values-sk/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Rozdeliť obrazovku" "Pripnúť" - "Aplikácie môžete prepínať potiahnutím prstom zdola nahor" "Prehľad" "Žiadne nedávne položky" - + "Zavrieť" + "Vymazať všetko" + diff --git a/quickstep/res/values-sl/strings.xml b/quickstep/res/values-sl/strings.xml index 72d52a51c6..6a25e9d834 100644 --- a/quickstep/res/values-sl/strings.xml +++ b/quickstep/res/values-sl/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Razdeljen zaslon" "Pripni" - "Če želite preklopiti med aplikacijami, z dna zaslona s prstom povlecite navzgor" "Pregled" "Ni nedavnih elementov" - + "Zapri" + "Počisti vse" + diff --git a/quickstep/res/values-sq-rAL/strings.xml b/quickstep/res/values-sq-rAL/strings.xml new file mode 100644 index 0000000000..a0c3d781d0 --- /dev/null +++ b/quickstep/res/values-sq-rAL/strings.xml @@ -0,0 +1,28 @@ + + + + + "Ekrani i ndarë" + "Gozhdo" + "Përmbledhja" + "Nuk ka asnjë artikull të fundit" + "Mbyll" + "Pastroji të gjitha" + diff --git a/quickstep/res/values-sq/strings.xml b/quickstep/res/values-sq/strings.xml index 954342cd93..521b8c75cc 100644 --- a/quickstep/res/values-sq/strings.xml +++ b/quickstep/res/values-sq/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Ekrani i ndarë" "Gozhdo" - "Rrëshqit larg nga poshtë për të ndryshuar aplikacionet" "Përmbledhja" "Nuk ka asnjë artikull të fundit" - + "Mbyll" + "Pastroji të gjitha" + diff --git a/quickstep/res/values-sr/strings.xml b/quickstep/res/values-sr/strings.xml index 51a9586e64..054cda5945 100644 --- a/quickstep/res/values-sr/strings.xml +++ b/quickstep/res/values-sr/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Подељени екран" "Закачи" - "Превуците нагоре да бисте прешли на другу апликацију" "Преглед" "Нема недавних ставки" - + "Затвори" + "Обриши све" + diff --git a/quickstep/res/values-sv/strings.xml b/quickstep/res/values-sv/strings.xml index 266cf60ef7..1a0ecc13e1 100644 --- a/quickstep/res/values-sv/strings.xml +++ b/quickstep/res/values-sv/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Delad skärm" "Fäst" - "Växla mellan appar genom att svepa uppåt från nederkanten" "Översikt" "Listan med de senaste åtgärderna är tom" - + "Stäng" + "Rensa alla" + diff --git a/quickstep/res/values-sw/strings.xml b/quickstep/res/values-sw/strings.xml index e85fa45bbd..be26e8bc66 100644 --- a/quickstep/res/values-sw/strings.xml +++ b/quickstep/res/values-sw/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Gawa skrini" "Bandika" - "Telezesha kidole juu kuanzia chini ili ubadilishe programu" "Muhtasari" "Hakuna vipengee vya hivi karibuni" - + "Funga" + "Ondoa zote" + diff --git a/quickstep/res/values-ta-rIN/strings.xml b/quickstep/res/values-ta-rIN/strings.xml new file mode 100644 index 0000000000..0c800ca720 --- /dev/null +++ b/quickstep/res/values-ta-rIN/strings.xml @@ -0,0 +1,28 @@ + + + + + "திரைப் பிரிப்பு" + "பின் செய்தல்" + "மேலோட்டப் பார்வை" + "சமீபத்தியவை எதுவுமில்லை" + "மூடும்" + "எல்லாம் அழி" + diff --git a/quickstep/res/values-ta/strings.xml b/quickstep/res/values-ta/strings.xml index de03ae62e8..886b017a8f 100644 --- a/quickstep/res/values-ta/strings.xml +++ b/quickstep/res/values-ta/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "திரைப் பிரிப்பு" "பின் செய்தல்" - "ஆப்ஸிற்கு இடையே மாற்றுவதற்கு, கீழிருந்து மேல்நோக்கி ஸ்வைப் செய்க" - - - + "மேலோட்டப் பார்வை" + "சமீபத்தியவை எதுவுமில்லை" + "மூடும்" + "எல்லாம் அழி" + diff --git a/quickstep/res/values-te-rIN/strings.xml b/quickstep/res/values-te-rIN/strings.xml new file mode 100644 index 0000000000..416fbb848d --- /dev/null +++ b/quickstep/res/values-te-rIN/strings.xml @@ -0,0 +1,28 @@ + + + + + "స్క్రీన్‌ని విభజించు" + "పిన్ చేయి" + "అవలోకనం" + "ఇటీవలి అంశాలు ఏవీ లేవు" + "మూసివేయండి" + "అన్నీ తీసివేయండి" + diff --git a/quickstep/res/values-te/strings.xml b/quickstep/res/values-te/strings.xml index 108f35042c..a0a818cf61 100644 --- a/quickstep/res/values-te/strings.xml +++ b/quickstep/res/values-te/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "స్క్రీన్‌ని విభజించు" "పిన్ చేయి" - "యాప్‌లను మార్చడానికి దిగువ నుండి పైకి స్వైప్ చేయండి" "అవలోకనం" "ఇటీవలి అంశాలు ఏవీ లేవు" - + "మూసివేయండి" + "అన్నీ తీసివేయండి" + diff --git a/quickstep/res/values-th/strings.xml b/quickstep/res/values-th/strings.xml index 80f91b087b..5a162b729d 100644 --- a/quickstep/res/values-th/strings.xml +++ b/quickstep/res/values-th/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "แยกหน้าจอ" "ตรึง" - "เลื่อนขึ้นจากด้านล่างเพื่อสลับแอป" "ภาพรวม" "ไม่มีรายการล่าสุด" - + "ปิด" + "ล้างทั้งหมด" + diff --git a/quickstep/res/values-tl/strings.xml b/quickstep/res/values-tl/strings.xml index b28e04e72d..af7ff97fa7 100644 --- a/quickstep/res/values-tl/strings.xml +++ b/quickstep/res/values-tl/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Hatiin ang screen" "I-pin" - "Mag-swipe pataas mula sa ibaba para lumipat ng app" "Overview" "Walang kamakailang item" - + "Isara" + "I-clear lahat" + diff --git a/quickstep/res/values-tr/strings.xml b/quickstep/res/values-tr/strings.xml index 1399353561..760a61ffd5 100644 --- a/quickstep/res/values-tr/strings.xml +++ b/quickstep/res/values-tr/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Bölünmüş ekran" "Sabitle" - "Uygulamaları değiştirmek için alttan yukarı kaydırın" "Genel bakış" "Yeni öğe yok" - + "Kapat" + "Tümünü temizle" + diff --git a/quickstep/res/values-uk/strings.xml b/quickstep/res/values-uk/strings.xml index 929bbe795d..41babaa879 100644 --- a/quickstep/res/values-uk/strings.xml +++ b/quickstep/res/values-uk/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Розділити екран" "Закріпити" - "Щоб переходити між додатками, проводьте пальцем знизу вгору" "Огляд" "Немає нещодавніх додатків" - + "Закрити" + "Очистити все" + diff --git a/quickstep/res/values-ur-rPK/strings.xml b/quickstep/res/values-ur-rPK/strings.xml new file mode 100644 index 0000000000..0a546fd603 --- /dev/null +++ b/quickstep/res/values-ur-rPK/strings.xml @@ -0,0 +1,28 @@ + + + + + "اسپلٹ اسکرین وضع" + "پن کریں" + "مجموعی جائزہ" + "کوئی حالیہ آئٹم نہیں" + "بند کریں" + "سبھی کو صاف کریں" + diff --git a/quickstep/res/values-ur/strings.xml b/quickstep/res/values-ur/strings.xml index 0271fe4d24..9dd7b8d33c 100644 --- a/quickstep/res/values-ur/strings.xml +++ b/quickstep/res/values-ur/strings.xml @@ -21,11 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "اسپلٹ اسکرین وضع" "پن کریں" - "ایپس کو سوئچ کرنے کیلئے نیچے سے اوپر سوائپ کریں" - - - - - + "مجموعی جائزہ" + "کوئی حالیہ آئٹم نہیں" + "بند کریں" + "سبھی کو صاف کریں" + diff --git a/quickstep/res/values-uz-rUZ/strings.xml b/quickstep/res/values-uz-rUZ/strings.xml new file mode 100644 index 0000000000..efea34117f --- /dev/null +++ b/quickstep/res/values-uz-rUZ/strings.xml @@ -0,0 +1,28 @@ + + + + + "Ekranni ikkiga ajratish" + "Mahkamlash" + "Nazar" + "Yaqinda ishlatilgan ilovalar yo‘q" + "Yopish" + "Hammasini tozalash" + diff --git a/quickstep/res/values-uz/strings.xml b/quickstep/res/values-uz/strings.xml index 91e11d3dca..c78f000ca5 100644 --- a/quickstep/res/values-uz/strings.xml +++ b/quickstep/res/values-uz/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Ekranni ikkiga ajratish" "Mahkamlash" - "Ilovalarni almashtirish uchun pastdan yuqoriga suring" "Nazar" "Yaqinda ishlatilgan ilovalar yo‘q" - + "Yopish" + "Hammasini tozalash" + diff --git a/quickstep/res/values-vi/strings.xml b/quickstep/res/values-vi/strings.xml index 809517a58b..4b1d1c0257 100644 --- a/quickstep/res/values-vi/strings.xml +++ b/quickstep/res/values-vi/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Chia đôi màn hình" "Ghim" - "Vuốt từ dưới lên để chuyển đổi ứng dụng" "Tổng quan" "Không có mục gần đây nào" - + "Đóng" + "Xóa tất cả" + diff --git a/quickstep/res/values-zh-rCN/strings.xml b/quickstep/res/values-zh-rCN/strings.xml index a44dd2db06..17cf6c31a1 100644 --- a/quickstep/res/values-zh-rCN/strings.xml +++ b/quickstep/res/values-zh-rCN/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "分屏" "固定" - "从屏幕底部向上滑动即可切换应用" "概览" "近期没有任何内容" - + "关闭" + "全部清除" + diff --git a/quickstep/res/values-zh-rHK/strings.xml b/quickstep/res/values-zh-rHK/strings.xml index 3879bc568e..1203cf01fc 100644 --- a/quickstep/res/values-zh-rHK/strings.xml +++ b/quickstep/res/values-zh-rHK/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "分割畫面" "固定" - "從螢幕底部向上快速滑動,即可切換應用程式" "概覽" "最近沒有任何項目" - + "關閉" + "全部清除" + diff --git a/quickstep/res/values-zh-rTW/strings.xml b/quickstep/res/values-zh-rTW/strings.xml index f275168f67..ed708b4950 100644 --- a/quickstep/res/values-zh-rTW/strings.xml +++ b/quickstep/res/values-zh-rTW/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "分割畫面" "固定" - "從畫面底部向上滑動以切換應用程式" "總覽" "最近沒有任何項目" - + "關閉" + "全部清除" + diff --git a/quickstep/res/values-zu/strings.xml b/quickstep/res/values-zu/strings.xml index 206718eff8..1aa34b6b6d 100644 --- a/quickstep/res/values-zu/strings.xml +++ b/quickstep/res/values-zu/strings.xml @@ -21,9 +21,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> "Hlukanisa isikrini" "Phina" - "Swayiphela phezulu kusukela phansi ukuze ushintshe izinhlelo zokusebenza" "Buka konke" "Azikho izinto zakamuva" - + "Vala" + "Sula konke" + diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml index 94211c62fe..7673f69940 100644 --- a/quickstep/res/values/config.xml +++ b/quickstep/res/values/config.xml @@ -16,4 +16,7 @@ + + + com.google.quickstep.logging.UserEventDispatcherExtension diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index c741913953..ad5f767be0 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -30,8 +30,9 @@ 250dp - 25dp - 80dp + 50dp + 50dp + 115dp 16sp 16dp @@ -45,4 +46,9 @@ 10dp + + + 168dp + + 16dp diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml index 7ba91b3db5..a76899d3da 100644 --- a/quickstep/res/values/strings.xml +++ b/quickstep/res/values/strings.xml @@ -27,9 +27,6 @@ Pin - - Swipe up from the bottom to switch apps - Overview @@ -38,4 +35,10 @@ Close + + + Clear all + + + Recent apps \ No newline at end of file diff --git a/quickstep/res/xml/indexable_launcher_prefs.xml b/quickstep/res/xml/indexable_launcher_prefs.xml index 2655402015..30f310021f 100644 --- a/quickstep/res/xml/indexable_launcher_prefs.xml +++ b/quickstep/res/xml/indexable_launcher_prefs.xml @@ -20,8 +20,14 @@ android:key="pref_add_icon_to_home" android:title="@string/auto_add_shortcuts_label" android:summary="@string/auto_add_shortcuts_description" - android:defaultValue="true" - /> + android:defaultValue="true" /> + + { - // Finish any previous animation - finishSystemAnimation(); - - mSysFinishRunnable = runnable; - mAnimator = getAnimator(targetCompats); - if (mAnimator == null) { - finishSystemAnimation(); - return; - } - mAnimator.addListener(this); - mAnimator.start(); - // Because t=0 has the app icon in its original spot, we can skip the - // first frame and have the same movement one frame earlier. - mAnimator.setCurrentPlayTime(REFRESH_RATE_MS); - - }); + Runnable r = () -> { + finishExistingAnimation(); + mAnimationResult = new AnimationResult(runnable); + onCreateAnimation(targetCompats, mAnimationResult); + }; + if (mStartAtFrontOfQueue) { + postAtFrontOfQueueAsynchronously(mHandler, r); + } else { + postAsyncCallback(mHandler, r); + } } + /** + * Called on the UI thread when the animation targets are received. The implementation must + * call {@link AnimationResult#setAnimation(AnimatorSet)} with the target animation to be run. + */ + @UiThread + public abstract void onCreateAnimation( + RemoteAnimationTargetCompat[] targetCompats, AnimationResult result); @UiThread - public abstract AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats); - - @UiThread - @Override - public void onAnimationEnd(Animator animation) { - if (animation == mAnimator) { - mAnimator = null; - finishSystemAnimation(); + private void finishExistingAnimation() { + if (mAnimationResult != null) { + mAnimationResult.finish(); + mAnimationResult = null; } } @@ -87,20 +84,56 @@ public abstract class LauncherAnimationRunner extends AnimatorListenerAdapter @BinderThread @Override public void onAnimationCancelled() { - postAtFrontOfQueueAsynchronously(mHandler, () -> { - if (mAnimator != null) { - mAnimator.removeListener(this); - mAnimator.end(); - mAnimator = null; - } - }); + postAsyncCallback(mHandler, this::finishExistingAnimation); } - @UiThread - private void finishSystemAnimation() { - if (mSysFinishRunnable != null) { - mSysFinishRunnable.run(); - mSysFinishRunnable = null; + public static final class AnimationResult { + + private final Runnable mFinishRunnable; + + private AnimatorSet mAnimator; + private boolean mFinished = false; + private boolean mInitialized = false; + + private AnimationResult(Runnable finishRunnable) { + mFinishRunnable = finishRunnable; + } + + @UiThread + private void finish() { + if (!mFinished) { + mFinishRunnable.run(); + mFinished = true; + } + } + + @UiThread + public void setAnimation(AnimatorSet animation) { + if (mInitialized) { + throw new IllegalStateException("Animation already initialized"); + } + mInitialized = true; + mAnimator = animation; + if (mAnimator == null) { + finish(); + } else if (mFinished) { + // Animation callback was already finished, skip the animation. + mAnimator.start(); + mAnimator.end(); + } else { + // Start the animation + mAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + finish(); + } + }); + mAnimator.start(); + + // Because t=0 has the app icon in its original spot, we can skip the + // first frame and have the same movement one frame earlier. + mAnimator.setCurrentPlayTime(SINGLE_FRAME_MS); + } } } } \ No newline at end of file diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java index ad0b7344b6..2e31ef239e 100644 --- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java @@ -16,9 +16,21 @@ package com.android.launcher3; +import static com.android.launcher3.BaseActivity.INVISIBLE_ALL; +import static com.android.launcher3.BaseActivity.INVISIBLE_BY_APP_TRANSITIONS; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; +import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; +import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.launcher3.Utilities.postAsyncCallback; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; +import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; +import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7; +import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_TRANSITIONS; +import static com.android.quickstep.TaskUtils.findTaskViewToLaunch; +import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator; +import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber; import static com.android.systemui.shared.recents.utilities.Utilities.getSurface; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; @@ -31,7 +43,6 @@ import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.app.ActivityOptions; -import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; @@ -42,10 +53,10 @@ import android.os.Build; import android.os.Handler; import android.os.Looper; import android.util.Log; +import android.util.Pair; import android.view.Surface; import android.view.View; import android.view.ViewGroup; -import android.view.animation.Interpolator; import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener; import com.android.launcher3.InsettableFrameLayout.LayoutParams; @@ -55,12 +66,13 @@ import com.android.launcher3.anim.Interpolators; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.graphics.DrawableFactory; import com.android.launcher3.shortcuts.DeepShortcutView; -import com.android.quickstep.RecentsAnimationInterpolator; -import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds; +import com.android.launcher3.util.MultiValueAlpha; +import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; +import com.android.quickstep.util.ClipAnimationHelper; +import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; -import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ActivityCompat; import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; @@ -79,54 +91,66 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag implements OnDeviceProfileChangeListener { private static final String TAG = "LauncherTransition"; - private static final int STATUS_BAR_TRANSITION_DURATION = 120; + public static final int STATUS_BAR_TRANSITION_DURATION = 120; private static final String CONTROL_REMOTE_APP_TRANSITION_PERMISSION = "android.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS"; private static final int APP_LAUNCH_DURATION = 500; // Use a shorter duration for x or y translation to create a curve effect - private static final int APP_LAUNCH_CURVED_DURATION = 233; - private static final int RECENTS_LAUNCH_DURATION = 336; + private static final int APP_LAUNCH_CURVED_DURATION = APP_LAUNCH_DURATION / 2; + // We scale the durations for the downward app launch animations (minus the scale animation). + private static final float APP_LAUNCH_DOWN_DUR_SCALE_FACTOR = 0.8f; + private static final int APP_LAUNCH_ALPHA_START_DELAY = 32; + private static final int APP_LAUNCH_ALPHA_DURATION = 50; + + public static final int RECENTS_LAUNCH_DURATION = 336; private static final int LAUNCHER_RESUME_START_DELAY = 100; - private static final int CLOSING_TRANSITION_DURATION_MS = 350; + private static final int CLOSING_TRANSITION_DURATION_MS = 250; // Progress = 0: All apps is fully pulled up, Progress = 1: All apps is fully pulled down. public static final float ALL_APPS_PROGRESS_OFF_SCREEN = 1.3059858f; - public static final float ALL_APPS_PROGRESS_OVERSHOOT = 0.99581414f; - private final DragLayer mDragLayer; private final Launcher mLauncher; + private final DragLayer mDragLayer; + private final AlphaProperty mDragLayerAlpha; private final Handler mHandler; private final boolean mIsRtl; private final float mContentTransY; private final float mWorkspaceTransY; + private final float mClosingWindowTransY; private DeviceProfile mDeviceProfile; private View mFloatingView; private RemoteAnimationProvider mRemoteAnimationProvider; - private final AnimatorListenerAdapter mReapplyStateListener = new AnimatorListenerAdapter() { + private final AnimatorListenerAdapter mForceInvisibleListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + mLauncher.addForceInvisibleFlag(INVISIBLE_BY_APP_TRANSITIONS); + } + @Override public void onAnimationEnd(Animator animation) { - mLauncher.getStateManager().reapplyState(); + mLauncher.clearForceInvisibleFlag(INVISIBLE_BY_APP_TRANSITIONS); } }; public LauncherAppTransitionManagerImpl(Context context) { mLauncher = Launcher.getLauncher(context); mDragLayer = mLauncher.getDragLayer(); + mDragLayerAlpha = mDragLayer.getAlphaProperty(ALPHA_INDEX_TRANSITIONS); mHandler = new Handler(Looper.getMainLooper()); mIsRtl = Utilities.isRtl(mLauncher.getResources()); mDeviceProfile = mLauncher.getDeviceProfile(); - Resources res = mLauncher.getResources(); mContentTransY = res.getDimensionPixelSize(R.dimen.content_trans_y); mWorkspaceTransY = res.getDimensionPixelSize(R.dimen.workspace_trans_y); + mClosingWindowTransY = res.getDimensionPixelSize(R.dimen.closing_window_trans_y); mLauncher.addOnDeviceProfileChangeListener(this); registerRemoteAnimations(); @@ -144,38 +168,50 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag @Override public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) { if (hasControlRemoteAppTransitionPermission()) { - try { - RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler) { + RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler, + true /* startAtFrontOfQueue */) { - @Override - public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) { - AnimatorSet anim = new AnimatorSet(); + @Override + public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, + AnimationResult result) { + AnimatorSet anim = new AnimatorSet(); + boolean launcherClosing = + launcherIsATargetWithMode(targetCompats, MODE_CLOSING); - if (!composeRecentsLaunchAnimator(v, targetCompats, anim)) { - // Set the state animation first so that any state listeners are called - // before our internal listeners. - mLauncher.getStateManager().setCurrentAnimation(anim); + if (!composeRecentsLaunchAnimator(v, targetCompats, anim)) { + // Set the state animation first so that any state listeners are called + // before our internal listeners. + mLauncher.getStateManager().setCurrentAnimation(anim); - anim.play(getIconAnimator(v)); - if (launcherIsATargetWithMode(targetCompats, MODE_CLOSING)) { - anim.play(getLauncherContentAnimator(false /* show */)); - } - anim.play(getWindowAnimators(v, targetCompats)); + anim.play(getIconAnimator(v)); + if (launcherClosing) { + Pair launcherContentAnimator = + getLauncherContentAnimator(true /* isAppOpening */); + anim.play(launcherContentAnimator.first); + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + launcherContentAnimator.second.run(); + } + }); } - return anim; + anim.play(getOpeningWindowAnimators(v, targetCompats)); } - }; - int duration = findTaskViewToLaunch(launcher, v, null) != null - ? RECENTS_LAUNCH_DURATION : APP_LAUNCH_DURATION; - int statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION; - return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat( - runner, duration, statusBarTransitionDelay)); - } catch (NoClassDefFoundError e) { - // Gracefully fall back to default launch options if the user's platform doesn't - // have the latest changes. - } + if (launcherClosing) { + anim.addListener(mForceInvisibleListener); + } + + result.setAnimation(anim); + } + }; + + int duration = findTaskViewToLaunch(launcher, v, null) != null + ? RECENTS_LAUNCH_DURATION : APP_LAUNCH_DURATION; + int statusBarTransitionDelay = duration - STATUS_BAR_TRANSITION_DURATION; + return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat( + runner, duration, statusBarTransitionDelay)); } return getDefaultActivityLaunchOptions(launcher, v); } @@ -184,64 +220,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag mRemoteAnimationProvider = animationProvider; } - /** - * Try to find a TaskView that corresponds with the component of the launched view. - * - * If this method returns a non-null TaskView, it will be used in composeRecentsLaunchAnimation. - * Otherwise, we will assume we are using a normal app transition, but it's possible that the - * opening remote target (which we don't get until onAnimationStart) will resolve to a TaskView. - */ - private TaskView findTaskViewToLaunch( - BaseDraggingActivity activity, View v, RemoteAnimationTargetCompat[] targets) { - if (v instanceof TaskView) { - return (TaskView) v; - } - RecentsView recentsView = activity.getOverviewPanel(); - - // It's possible that the launched view can still be resolved to a visible task view, check - // the task id of the opening task and see if we can find a match. - if (v.getTag() instanceof ItemInfo) { - ItemInfo itemInfo = (ItemInfo) v.getTag(); - ComponentName componentName = itemInfo.getTargetComponent(); - if (componentName != null) { - for (int i = 0; i < recentsView.getChildCount(); i++) { - TaskView taskView = (TaskView) recentsView.getPageAt(i); - if (recentsView.isTaskViewVisible(taskView)) { - Task task = taskView.getTask(); - if (componentName.equals(task.key.getComponent())) { - return taskView; - } - } - } - } - } - - if (targets == null) { - return null; - } - // Resolve the opening task id - int openingTaskId = -1; - for (RemoteAnimationTargetCompat target : targets) { - if (target.mode == MODE_OPENING) { - openingTaskId = target.taskId; - break; - } - } - - // If there is no opening task id, fall back to the normal app icon launch animation - if (openingTaskId == -1) { - return null; - } - - // If the opening task id is not currently visible in overview, then fall back to normal app - // icon launch animation - TaskView taskView = recentsView.getTaskView(openingTaskId); - if (taskView == null || !recentsView.isTaskViewVisible(taskView)) { - return null; - } - return taskView; - } - /** * Composes the animations for a launch from the recents list if possible. */ @@ -261,21 +239,33 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag return false; } + ClipAnimationHelper helper = new ClipAnimationHelper(); + target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper) + .setDuration(RECENTS_LAUNCH_DURATION)); + + Animator childStateAnimation = null; // Found a visible recents task that matches the opening app, lets launch the app from there Animator launcherAnim; final AnimatorListenerAdapter windowAnimEndListener; if (launcherClosing) { - launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView); + launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper); launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); launcherAnim.setDuration(RECENTS_LAUNCH_DURATION); // Make sure recents gets fixed up by resetting task alphas and scales, etc. - windowAnimEndListener = mReapplyStateListener; + windowAnimEndListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mLauncher.getStateManager().moveToRestState(); + mLauncher.getStateManager().reapplyState(); + } + }; } else { AnimatorPlaybackController controller = mLauncher.getStateManager() .createAnimationToNewWorkspace(NORMAL, RECENTS_LAUNCH_DURATION); controller.dispatchOnStart(); + childStateAnimation = controller.getTarget(); launcherAnim = controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION); windowAnimEndListener = new AnimatorListenerAdapter() { @Override @@ -284,112 +274,34 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } }; } - - target.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets)); target.play(launcherAnim); // Set the current animation first, before adding windowAnimEndListener. Setting current // animation adds some listeners which need to be called before windowAnimEndListener // (the ordering of listeners matter in this case). - mLauncher.getStateManager().setCurrentAnimation(target); + mLauncher.getStateManager().setCurrentAnimation(target, childStateAnimation); target.addListener(windowAnimEndListener); return true; } - /** - * @return Animator that controls the window of the opening targets for the recents launch - * animation. - */ - private ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipLauncherChanges, - RemoteAnimationTargetCompat[] targets) { - final RecentsAnimationInterpolator recentsInterpolator = v.getRecentsInterpolator(); - - Rect crop = new Rect(); - Matrix matrix = new Matrix(); - - ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); - appAnimator.setDuration(RECENTS_LAUNCH_DURATION); - appAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); - appAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { - boolean isFirstFrame = true; - - @Override - public void onAnimationUpdate(ValueAnimator animation) { - final Surface surface = getSurface(v); - final long frameNumber = surface != null ? getNextFrameNumber(surface) : -1; - if (frameNumber == -1) { - // Booo, not cool! Our surface got destroyed, so no reason to animate anything. - Log.w(TAG, "Failed to animate, surface got destroyed."); - return; - } - final float percent = animation.getAnimatedFraction(); - TaskWindowBounds tw = recentsInterpolator.interpolate(percent); - - float alphaDuration = 75; - if (!skipLauncherChanges) { - v.setScaleX(tw.taskScale); - v.setScaleY(tw.taskScale); - v.setTranslationX(tw.taskX); - v.setTranslationY(tw.taskY); - // Defer fading out the view until after the app window gets faded in - v.setAlpha(getValue(1f, 0f, alphaDuration, alphaDuration, - appAnimator.getDuration() * percent, Interpolators.LINEAR)); - } - - matrix.setScale(tw.winScale, tw.winScale); - matrix.postTranslate(tw.winX, tw.winY); - crop.set(tw.winCrop); - - // Fade in the app window. - float alpha = getValue(0f, 1f, 0, alphaDuration, - appAnimator.getDuration() * percent, Interpolators.LINEAR); - - TransactionCompat t = new TransactionCompat(); - for (RemoteAnimationTargetCompat target : targets) { - if (target.mode == RemoteAnimationTargetCompat.MODE_OPENING) { - t.setAlpha(target.leash, alpha); - - // TODO: This isn't correct at the beginning of the animation, but better - // than nothing. - matrix.postTranslate(target.position.x, target.position.y); - t.setMatrix(target.leash, matrix); - t.setWindowCrop(target.leash, crop); - - if (!skipLauncherChanges) { - t.deferTransactionUntil(target.leash, surface, frameNumber); - } - } - if (isFirstFrame) { - t.show(target.leash); - } - } - t.setEarlyWakeup(); - t.apply(); - - matrix.reset(); - isFirstFrame = false; - } - }); - return appAnimator; - } - /** * Content is everything on screen except the background and the floating view (if any). * - * @param show If true: Animate the content so that it moves upwards and fades in. - * Else: Animate the content so that it moves downwards and fades out. + * @param isAppOpening True when this is called when an app is opening. + * False when this is called when an app is closing. */ - private AnimatorSet getLauncherContentAnimator(boolean show) { + private Pair getLauncherContentAnimator(boolean isAppOpening) { AnimatorSet launcherAnimator = new AnimatorSet(); + Runnable endListener; - float[] alphas = show - ? new float[] {0, 1} - : new float[] {1, 0}; - float[] trans = show - ? new float[] {mContentTransY, 0,} - : new float[] {0, mContentTransY}; + float[] alphas = isAppOpening + ? new float[] {1, 0} + : new float[] {0, 1}; + float[] trans = isAppOpening + ? new float[] {0, mContentTransY} + : new float[] {-mContentTransY, 0}; - if (mLauncher.isInState(LauncherState.ALL_APPS) && !mDeviceProfile.isVerticalBarLayout()) { + if (mLauncher.isInState(ALL_APPS)) { // All Apps in portrait mode is full screen, so we only animate AllAppsContainerView. final View appsView = mLauncher.getAppsView(); final float startAlpha = appsView.getAlpha(); @@ -399,44 +311,72 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas); alpha.setDuration(217); - alpha.setInterpolator(Interpolators.LINEAR); + alpha.setInterpolator(LINEAR); + appsView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + alpha.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + appsView.setLayerType(View.LAYER_TYPE_NONE, null); + } + }); ObjectAnimator transY = ObjectAnimator.ofFloat(appsView, View.TRANSLATION_Y, trans); - transY.setInterpolator(Interpolators.AGGRESSIVE_EASE); + transY.setInterpolator(AGGRESSIVE_EASE); transY.setDuration(350); launcherAnimator.play(alpha); launcherAnimator.play(transY); - launcherAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - appsView.setAlpha(startAlpha); - appsView.setTranslationY(startY); - } - }); + endListener = () -> { + appsView.setAlpha(startAlpha); + appsView.setTranslationY(startY); + appsView.setLayerType(View.LAYER_TYPE_NONE, null); + }; + } else if (mLauncher.isInState(OVERVIEW)) { + AllAppsTransitionController allAppsController = mLauncher.getAllAppsController(); + launcherAnimator.play(ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS, + allAppsController.getProgress(), ALL_APPS_PROGRESS_OFF_SCREEN)); + + View overview = mLauncher.getOverviewPanelContainer(); + ObjectAnimator alpha = ObjectAnimator.ofFloat(overview, View.ALPHA, alphas); + alpha.setDuration(217); + alpha.setInterpolator(LINEAR); + launcherAnimator.play(alpha); + + ObjectAnimator transY = ObjectAnimator.ofFloat(overview, View.TRANSLATION_Y, trans); + transY.setInterpolator(AGGRESSIVE_EASE); + transY.setDuration(350); + launcherAnimator.play(transY); + + overview.setLayerType(View.LAYER_TYPE_HARDWARE, null); + + endListener = () -> { + overview.setLayerType(View.LAYER_TYPE_NONE, null); + overview.setAlpha(1f); + overview.setTranslationY(0f); + mLauncher.getStateManager().reapplyState(); + }; } else { - mDragLayer.setAlpha(alphas[0]); + mDragLayerAlpha.setValue(alphas[0]); + ObjectAnimator alpha = + ObjectAnimator.ofFloat(mDragLayerAlpha, MultiValueAlpha.VALUE, alphas); + alpha.setDuration(217); + alpha.setInterpolator(LINEAR); + launcherAnimator.play(alpha); + mDragLayer.setTranslationY(trans[0]); + ObjectAnimator transY = ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y, trans); + transY.setInterpolator(AGGRESSIVE_EASE); + transY.setDuration(350); + launcherAnimator.play(transY); - ObjectAnimator dragLayerAlpha = ObjectAnimator.ofFloat(mDragLayer, View.ALPHA, alphas); - dragLayerAlpha.setDuration(217); - dragLayerAlpha.setInterpolator(Interpolators.LINEAR); - ObjectAnimator dragLayerTransY = ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y, - trans); - dragLayerTransY.setInterpolator(Interpolators.AGGRESSIVE_EASE); - dragLayerTransY.setDuration(350); + mDragLayer.getScrim().hideSysUiScrim(true); + // Pause page indicator animations as they lead to layer trashing. + mLauncher.getWorkspace().getPageIndicator().pauseAnimations(); + mDragLayer.setLayerType(View.LAYER_TYPE_HARDWARE, null); - launcherAnimator.play(dragLayerAlpha); - launcherAnimator.play(dragLayerTransY); - launcherAnimator.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mDragLayer.setAlpha(1); - mDragLayer.setTranslationY(0); - } - }); + endListener = this::resetContentView; } - return launcherAnimator; + return new Pair<>(launcherAnimator, endListener); } /** @@ -511,12 +451,19 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ObjectAnimator x = ObjectAnimator.ofFloat(mFloatingView, View.TRANSLATION_X, 0f, dX); ObjectAnimator y = ObjectAnimator.ofFloat(mFloatingView, View.TRANSLATION_Y, 0f, dY); - // Adjust the duration to change the "curve" of the app icon to the center. - boolean isBelowCenterY = lp.topMargin < centerY; - x.setDuration(isBelowCenterY ? APP_LAUNCH_DURATION : APP_LAUNCH_CURVED_DURATION); - y.setDuration(isBelowCenterY ? APP_LAUNCH_CURVED_DURATION : APP_LAUNCH_DURATION); - x.setInterpolator(Interpolators.AGGRESSIVE_EASE); - y.setInterpolator(Interpolators.AGGRESSIVE_EASE); + // Use upward animation for apps that are either on the bottom half of the screen, or are + // relatively close to the center. + boolean useUpwardAnimation = lp.topMargin > centerY + || Math.abs(dY) < mLauncher.getDeviceProfile().cellHeightPx; + if (useUpwardAnimation) { + x.setDuration(APP_LAUNCH_CURVED_DURATION); + y.setDuration(APP_LAUNCH_DURATION); + } else { + x.setDuration((long) (APP_LAUNCH_DOWN_DUR_SCALE_FACTOR * APP_LAUNCH_DURATION)); + y.setDuration((long) (APP_LAUNCH_DOWN_DUR_SCALE_FACTOR * APP_LAUNCH_CURVED_DURATION)); + } + x.setInterpolator(AGGRESSIVE_EASE); + y.setInterpolator(AGGRESSIVE_EASE); appIconAnimatorSet.play(x); appIconAnimatorSet.play(y); @@ -527,14 +474,21 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag float scale = Math.max(maxScaleX, maxScaleY); ObjectAnimator scaleAnim = ObjectAnimator .ofFloat(mFloatingView, SCALE_PROPERTY, startScale, scale); - scaleAnim.setDuration(APP_LAUNCH_DURATION).setInterpolator(Interpolators.EXAGGERATED_EASE); + scaleAnim.setDuration(APP_LAUNCH_DURATION) + .setInterpolator(Interpolators.EXAGGERATED_EASE); appIconAnimatorSet.play(scaleAnim); // Fade out the app icon. ObjectAnimator alpha = ObjectAnimator.ofFloat(mFloatingView, View.ALPHA, 1f, 0f); - alpha.setStartDelay(32); - alpha.setDuration(50); - alpha.setInterpolator(Interpolators.LINEAR); + if (useUpwardAnimation) { + alpha.setStartDelay(APP_LAUNCH_ALPHA_START_DELAY); + alpha.setDuration(APP_LAUNCH_ALPHA_DURATION); + } else { + alpha.setStartDelay((long) (APP_LAUNCH_DOWN_DUR_SCALE_FACTOR + * APP_LAUNCH_ALPHA_START_DELAY)); + alpha.setDuration((long) (APP_LAUNCH_DOWN_DUR_SCALE_FACTOR * APP_LAUNCH_ALPHA_DURATION)); + } + alpha.setInterpolator(LINEAR); appIconAnimatorSet.play(alpha); appIconAnimatorSet.addListener(new AnimatorListenerAdapter() { @@ -551,7 +505,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag /** * @return Animator that controls the window of the opening targets. */ - private ValueAnimator getWindowAnimators(View v, RemoteAnimationTargetCompat[] targets) { + private ValueAnimator getOpeningWindowAnimators(View v, RemoteAnimationTargetCompat[] targets) { Rect bounds = new Rect(); if (v.getParent() instanceof DeepShortcutView) { // Deep shortcut views have their icon drawn in a separate view. @@ -569,11 +523,13 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); appAnimator.setDuration(APP_LAUNCH_DURATION); - appAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { + appAnimator.addUpdateListener(new MultiValueUpdateListener() { + // Fade alpha for the app window. + FloatProp mAlpha = new FloatProp(0f, 1f, 0, 60, LINEAR); boolean isFirstFrame = true; @Override - public void onAnimationUpdate(ValueAnimator animation) { + public void onUpdate(float percent) { final Surface surface = getSurface(mFloatingView); final long frameNumber = surface != null ? getNextFrameNumber(surface) : -1; if (frameNumber == -1) { @@ -581,8 +537,7 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag Log.w(TAG, "Failed to animate, surface got destroyed."); return; } - final float percent = animation.getAnimatedFraction(); - final float easePercent = Interpolators.AGGRESSIVE_EASE.getInterpolation(percent); + final float easePercent = AGGRESSIVE_EASE.getInterpolation(percent); // Calculate app icon size. float iconWidth = bounds.width() * mFloatingView.getScaleX(); @@ -607,11 +562,6 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag float transY0 = floatingViewBounds[1] - offsetY; matrix.postTranslate(transX0, transY0); - // Fade in the app window. - float alphaDuration = 60; - float alpha = getValue(0f, 1f, 0, alphaDuration, - appAnimator.getDuration() * percent, Interpolators.LINEAR); - // Animate the window crop so that it starts off as a square, and then reveals // horizontally. float cropHeight = deviceHeight * easePercent + deviceWidth * (1 - easePercent); @@ -622,9 +572,13 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag crop.bottom = (int) (crop.top + cropHeight); TransactionCompat t = new TransactionCompat(); + if (isFirstFrame) { + RemoteAnimationProvider.prepareTargetsForFirstFrame(targets, t, MODE_OPENING); + isFirstFrame = false; + } for (RemoteAnimationTargetCompat target : targets) { if (target.mode == MODE_OPENING) { - t.setAlpha(target.leash, alpha); + t.setAlpha(target.leash, mAlpha.value); // TODO: This isn't correct at the beginning of the animation, but better // than nothing. @@ -633,15 +587,11 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag t.setWindowCrop(target.leash, crop); t.deferTransactionUntil(target.leash, surface, getNextFrameNumber(surface)); } - if (isFirstFrame) { - t.show(target.leash); - } } t.setEarlyWakeup(); t.apply(); matrix.reset(); - isFirstFrame = false; } }); return appAnimator; @@ -653,30 +603,19 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag private void registerRemoteAnimations() { // Unregister this if (hasControlRemoteAppTransitionPermission()) { - try { - RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat(); - definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN, - WindowManagerWrapper.ACTIVITY_TYPE_STANDARD, - new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(), - CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */)); + RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat(); + definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN, + WindowManagerWrapper.ACTIVITY_TYPE_STANDARD, + new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(), + CLOSING_TRANSITION_DURATION_MS, 0 /* statusBarTransitionDelay */)); -// TODO: App controlled transition for unlock to home TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER - - new ActivityCompat(mLauncher).registerRemoteAnimations(definition); - } catch (NoClassDefFoundError e) { - // Gracefully fall back if the user's platform doesn't have the latest changes - } + // TODO: Transition for unlock to home TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER + new ActivityCompat(mLauncher).registerRemoteAnimations(definition); } } private boolean launcherIsATargetWithMode(RemoteAnimationTargetCompat[] targets, int mode) { - int launcherTaskId = mLauncher.getTaskId(); - for (RemoteAnimationTargetCompat target : targets) { - if (target.mode == mode && target.taskId == launcherTaskId) { - return true; - } - } - return false; + return taskIsATargetWithMode(targets, mLauncher.getTaskId(), mode); } /** @@ -684,9 +623,18 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag * ie. pressing home, swiping up from nav bar. */ private RemoteAnimationRunnerCompat getWallpaperOpenRunner() { - return new LauncherAnimationRunner(mHandler) { + return new LauncherAnimationRunner(mHandler, false /* startAtFrontOfQueue */) { @Override - public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) { + public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, + AnimationResult result) { + if (!mLauncher.hasBeenResumed()) { + // If launcher is not resumed, wait until new async-frame after resume + mLauncher.setOnResumeCallback(() -> + postAsyncCallback(mHandler, () -> + onCreateAnimation(targetCompats, result))); + return; + } + AnimatorSet anim = null; RemoteAnimationProvider provider = mRemoteAnimationProvider; if (provider != null) { @@ -713,8 +661,8 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag } } - mLauncher.setForceInvisible(false); - return anim; + mLauncher.clearForceInvisibleFlag(INVISIBLE_ALL); + result.setAnimation(anim); } }; } @@ -724,54 +672,41 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag */ private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] targets) { Matrix matrix = new Matrix(); - float height = mLauncher.getDeviceProfile().heightPx; - float width = mLauncher.getDeviceProfile().widthPx; - float endX = (mLauncher.getOverviewPanel().isRtl() ? -width : width) * 1.16f; - ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1); - closingAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS); + int duration = CLOSING_TRANSITION_DURATION_MS; + closingAnimator.setDuration(duration); + closingAnimator.addUpdateListener(new MultiValueUpdateListener() { + FloatProp mDy = new FloatProp(0, mClosingWindowTransY, 0, duration, DEACCEL_1_7); + FloatProp mScale = new FloatProp(1f, 1f, 0, duration, DEACCEL_1_7); + FloatProp mAlpha = new FloatProp(1f, 0f, 25, 125, LINEAR); - closingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { boolean isFirstFrame = true; @Override - public void onAnimationUpdate(ValueAnimator animation) { - final float percent = animation.getAnimatedFraction(); - float currentPlayTime = percent * closingAnimator.getDuration(); - - float scale = getValue(1f, 0.8f, 0, 267, currentPlayTime, - Interpolators.AGGRESSIVE_EASE); - - float dX = getValue(0, endX, 0, 350, currentPlayTime, - Interpolators.AGGRESSIVE_EASE_IN_OUT); - + public void onUpdate(float percent) { TransactionCompat t = new TransactionCompat(); + if (isFirstFrame) { + RemoteAnimationProvider.prepareTargetsForFirstFrame(targets, t, MODE_CLOSING); + isFirstFrame = false; + } for (RemoteAnimationTargetCompat app : targets) { if (app.mode == RemoteAnimationTargetCompat.MODE_CLOSING) { - t.setAlpha(app.leash, getValue(1f, 0f, 0, 350, currentPlayTime, - Interpolators.APP_CLOSE_ALPHA)); - matrix.setScale(scale, scale, + t.setAlpha(app.leash, mAlpha.value); + matrix.setScale(mScale.value, mScale.value, app.sourceContainerBounds.centerX(), app.sourceContainerBounds.centerY()); - matrix.postTranslate(dX, 0); + matrix.postTranslate(0, mDy.value); matrix.postTranslate(app.position.x, app.position.y); t.setMatrix(app.leash, matrix); } - if (isFirstFrame) { - int layer = app.mode == RemoteAnimationTargetCompat.MODE_CLOSING - ? Integer.MAX_VALUE - : app.prefixOrderIndex; - t.setLayer(app.leash, layer); - t.show(app.leash); - } } t.setEarlyWakeup(); t.apply(); matrix.reset(); - isFirstFrame = false; } }); + return closingAnimator; } @@ -779,69 +714,58 @@ public class LauncherAppTransitionManagerImpl extends LauncherAppTransitionManag * Creates an animator that modifies Launcher as a result from {@link #getWallpaperOpenRunner}. */ private void createLauncherResumeAnimation(AnimatorSet anim) { - if (mLauncher.isInState(LauncherState.ALL_APPS) - || mLauncher.getDeviceProfile().isVerticalBarLayout()) { - AnimatorSet contentAnimator = getLauncherContentAnimator(true /* show */); - contentAnimator.setStartDelay(LAUNCHER_RESUME_START_DELAY); - anim.play(contentAnimator); + if (mLauncher.isInState(LauncherState.ALL_APPS)) { + Pair contentAnimator = + getLauncherContentAnimator(false /* isAppOpening */); + contentAnimator.first.setStartDelay(LAUNCHER_RESUME_START_DELAY); + anim.play(contentAnimator.first); + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + contentAnimator.second.run(); + } + }); } else { AnimatorSet workspaceAnimator = new AnimatorSet(); - mLauncher.getWorkspace().setTranslationY(mWorkspaceTransY); - workspaceAnimator.play(ObjectAnimator.ofFloat(mLauncher.getWorkspace(), - View.TRANSLATION_Y, mWorkspaceTransY, 0)); + mDragLayer.setTranslationY(-mWorkspaceTransY);; + workspaceAnimator.play(ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y, + -mWorkspaceTransY, 0)); - View currentPage = ((CellLayout) mLauncher.getWorkspace() - .getChildAt(mLauncher.getWorkspace().getCurrentPage())) - .getShortcutsAndWidgets(); - currentPage.setAlpha(0f); - workspaceAnimator.play(ObjectAnimator.ofFloat(currentPage, View.ALPHA, 0, 1f)); + mDragLayerAlpha.setValue(0); + workspaceAnimator.play(ObjectAnimator.ofFloat( + mDragLayerAlpha, MultiValueAlpha.VALUE, 0, 1f)); workspaceAnimator.setStartDelay(LAUNCHER_RESUME_START_DELAY); workspaceAnimator.setDuration(333); - workspaceAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); + workspaceAnimator.setInterpolator(Interpolators.DEACCEL_1_7); - // Animate the shelf in two parts: slide in, and overeshoot. - AllAppsTransitionController allAppsController = mLauncher.getAllAppsController(); - // The shelf will start offscreen - final float startY = ALL_APPS_PROGRESS_OFF_SCREEN; - // And will end slightly pulled up, so that there is something to overshoot back to 1f. - final float slideEnd = ALL_APPS_PROGRESS_OVERSHOOT; - - allAppsController.setProgress(startY); - - Animator allAppsSlideIn = - ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS, startY, slideEnd); - allAppsSlideIn.setStartDelay(LAUNCHER_RESUME_START_DELAY); - allAppsSlideIn.setDuration(317); - allAppsSlideIn.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); - - Animator allAppsOvershoot = - ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS, slideEnd, 1f); - allAppsOvershoot.setDuration(153); - allAppsOvershoot.setInterpolator(Interpolators.OVERSHOOT_0); + mDragLayer.getScrim().hideSysUiScrim(true); + // Pause page indicator animations as they lead to layer trashing. + mLauncher.getWorkspace().getPageIndicator().pauseAnimations(); + mDragLayer.setLayerType(View.LAYER_TYPE_HARDWARE, null); + workspaceAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + resetContentView(); + } + }); anim.play(workspaceAnimator); - anim.playSequentially(allAppsSlideIn, allAppsOvershoot); - anim.addListener(mReapplyStateListener); } } + private void resetContentView() { + mLauncher.getWorkspace().getPageIndicator().skipAnimationsToEnd(); + mDragLayerAlpha.setValue(1f); + mDragLayer.setLayerType(View.LAYER_TYPE_NONE, null); + mDragLayer.setTranslationY(0f); + mDragLayer.getScrim().hideSysUiScrim(false); + } + private boolean hasControlRemoteAppTransitionPermission() { return mLauncher.checkSelfPermission(CONTROL_REMOTE_APP_TRANSITION_PERMISSION) == PackageManager.PERMISSION_GRANTED; } - - /** - * Helper method that allows us to get interpolated values for embedded - * animations with a delay and/or different duration. - */ - private static float getValue(float start, float end, float delay, float duration, - float currentPlayTime, Interpolator i) { - float time = Math.max(0, currentPlayTime - delay); - float newPercent = Math.min(1f, time / duration); - newPercent = i.getInterpolation(newPercent); - return end * newPercent + start * (1 - newPercent); - } } diff --git a/quickstep/src/com/android/launcher3/LauncherInitListener.java b/quickstep/src/com/android/launcher3/LauncherInitListener.java index 27f169834d..e5e377f83b 100644 --- a/quickstep/src/com/android/launcher3/LauncherInitListener.java +++ b/quickstep/src/com/android/launcher3/LauncherInitListener.java @@ -24,6 +24,7 @@ import android.os.Handler; import com.android.launcher3.states.InternalStateHandler; import com.android.quickstep.ActivityControlHelper.ActivityInitListener; +import com.android.quickstep.OverviewCallbacks; import com.android.quickstep.util.RemoteAnimationProvider; import java.util.function.BiPredicate; @@ -60,6 +61,7 @@ public class LauncherInitListener extends InternalStateHandler implements Activi return null; }); } + OverviewCallbacks.get(launcher).onInitOverviewTransition(); return mOnInitListener.test(launcher, alreadyOnHome); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java index d2f54874f5..d86ba6aa6c 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/AllAppsState.java @@ -16,7 +16,6 @@ package com.android.launcher3.uioverrides; import static com.android.launcher3.LauncherAnimUtils.ALL_APPS_TRANSITION_MS; -import static com.android.launcher3.allapps.DiscoveryBounce.APPS_VIEW_SHOWN; import static com.android.launcher3.anim.Interpolators.DEACCEL_2; import android.view.View; @@ -32,7 +31,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; */ public class AllAppsState extends LauncherState { - private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY | FLAG_ALL_APPS_SCRIM; + private static final int STATE_FLAGS = FLAG_DISABLE_ACCESSIBILITY; private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) { @Override @@ -47,10 +46,6 @@ public class AllAppsState extends LauncherState { @Override public void onStateEnabled(Launcher launcher) { - if (!launcher.getSharedPrefs().getBoolean(APPS_VIEW_SHOWN, false)) { - launcher.getSharedPrefs().edit().putBoolean(APPS_VIEW_SHOWN, true).apply(); - } - AbstractFloatingView.closeAllOpenViews(launcher); dispatchWindowStateChanged(launcher); } @@ -73,8 +68,10 @@ public class AllAppsState extends LauncherState { @Override public float[] getWorkspaceScaleAndTranslation(Launcher launcher) { - // TODO: interpolate - return LauncherState.OVERVIEW.getWorkspaceScaleAndTranslation(launcher); + float[] scaleAndTranslation = LauncherState.OVERVIEW.getWorkspaceScaleAndTranslation( + launcher); + scaleAndTranslation[0] = 1; + return scaleAndTranslation; } @Override @@ -89,7 +86,7 @@ public class AllAppsState extends LauncherState { @Override public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) { - return new float[] {1f, -0.2f}; + return new float[] {0.9f, -0.2f}; } @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/DisplayRotationListener.java b/quickstep/src/com/android/launcher3/uioverrides/DisplayRotationListener.java new file mode 100644 index 0000000000..2d9a161475 --- /dev/null +++ b/quickstep/src/com/android/launcher3/uioverrides/DisplayRotationListener.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.uioverrides; + +import android.content.Context; +import android.os.Handler; + +import com.android.systemui.shared.system.RotationWatcher; + +/** + * Utility class for listening for rotation changes + */ +public class DisplayRotationListener extends RotationWatcher { + + private final Runnable mCallback; + private Handler mHandler; + + public DisplayRotationListener(Context context, Runnable callback) { + super(context); + mCallback = callback; + } + + @Override + public void enable() { + if (mHandler == null) { + mHandler = new Handler(); + } + super.enable(); + } + + @Override + protected void onRotationChanged(int i) { + mHandler.post(mCallback); + } +} diff --git a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java index f98f7a5ffa..a11625a346 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/FastOverviewState.java @@ -15,7 +15,6 @@ */ package com.android.launcher3.uioverrides; -import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Launcher; import com.android.quickstep.QuickScrubController; import com.android.quickstep.views.RecentsView; @@ -25,11 +24,11 @@ import com.android.quickstep.views.RecentsView; */ public class FastOverviewState extends OverviewState { - private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_DISABLE_RESTORE - | FLAG_DISABLE_INTERACTION | FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON; + private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_DISABLE_INTERACTION + | FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON | FLAG_DISABLE_ACCESSIBILITY; public FastOverviewState(int id) { - super(id, QuickScrubController.QUICK_SCRUB_START_DURATION, STATE_FLAGS); + super(id, QuickScrubController.QUICK_SCRUB_FROM_HOME_START_DURATION, STATE_FLAGS); } @Override @@ -39,11 +38,6 @@ public class FastOverviewState extends OverviewState { recentsView.getQuickScrubController().onFinishedTransitionToQuickScrub(); } - public void onStateEnabled(Launcher launcher) { - super.onStateEnabled(launcher); - AbstractFloatingView.closeAllOpenViews(launcher); - } - @Override public int getVisibleElements(Launcher launcher) { return NONE; diff --git a/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java index 3622fc4250..68773b4188 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/LandscapeEdgeSwipeController.java @@ -9,16 +9,20 @@ import android.view.MotionEvent; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.launcher3.LauncherStateManager.AnimationComponents; import com.android.launcher3.touch.AbstractStateChangeTouchController; import com.android.launcher3.touch.SwipeDetector; +import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; -import com.android.quickstep.util.SysuiEventLogger; +import com.android.quickstep.RecentsModel; /** * Touch controller for handling edge swipes in landscape/seascape UI */ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchController { + private static final String TAG = "LandscapeEdgeSwipeCtrl"; + public LandscapeEdgeSwipeController(Launcher l) { super(l, SwipeDetector.HORIZONTAL); } @@ -35,28 +39,28 @@ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchContro return mLauncher.isInState(NORMAL) && (ev.getEdgeFlags() & EDGE_NAV_BAR) != 0; } - @Override - protected int getSwipeDirection(MotionEvent ev) { - return SwipeDetector.DIRECTION_BOTH; - } - @Override protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) { boolean draggingFromNav = mLauncher.getDeviceProfile().isSeascape() != isDragTowardPositive; return draggingFromNav ? OVERVIEW : NORMAL; } + @Override + protected int getLogContainerTypeForNormalState() { + return LauncherLogProto.ContainerType.NAVBAR; + } + @Override protected float getShiftRange() { return mLauncher.getDragLayer().getWidth(); } @Override - protected float initCurrentAnimation() { + protected float initCurrentAnimation(@AnimationComponents int animComponent) { float range = getShiftRange(); long maxAccuracy = (long) (2 * range); - mCurrentAnimation = mLauncher.getStateManager() - .createAnimationToNewWorkspace(mToState, maxAccuracy); + mCurrentAnimation = mLauncher.getStateManager().createAnimationToNewWorkspace(mToState, + maxAccuracy, animComponent); return (mLauncher.getDeviceProfile().isSeascape() ? 2 : -2) / range; } @@ -69,7 +73,7 @@ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchContro protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { super.onSwipeInteractionCompleted(targetState, logAction); if (mFromState == NORMAL && targetState == OVERVIEW) { - SysuiEventLogger.writeDummyRecentsTransition(0); + RecentsModel.getInstance(mLauncher).onOverviewShown(true, TAG); } } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java index 9c7db3093a..3a49294c51 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewState.java @@ -21,9 +21,12 @@ import static com.android.launcher3.states.RotationHelper.REQUEST_ROTATE; import android.view.View; +import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.launcher3.Workspace; +import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.quickstep.views.RecentsView; @@ -32,8 +35,8 @@ import com.android.quickstep.views.RecentsView; */ public class OverviewState extends LauncherState { - private static final int STATE_FLAGS = FLAG_SHOW_SCRIM | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED - | FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI; + private static final int STATE_FLAGS = FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED + | FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY; public OverviewState(int id) { this(id, OVERVIEW_TRANSITION_MS, STATE_FLAGS); @@ -45,8 +48,15 @@ public class OverviewState extends LauncherState { @Override public float[] getWorkspaceScaleAndTranslation(Launcher launcher) { - // TODO: provide a valid value - return new float[]{1, 0, -launcher.getDeviceProfile().hotseatBarSizePx / 2}; + RecentsView recentsView = launcher.getOverviewPanel(); + Workspace workspace = launcher.getWorkspace(); + View workspacePage = workspace.getPageAt(workspace.getCurrentPage()); + float workspacePageWidth = workspacePage != null && workspacePage.getWidth() != 0 + ? workspacePage.getWidth() : launcher.getDeviceProfile().availableWidthPx; + recentsView.getTaskSize(sTempRect); + float scale = (float) sTempRect.width() / workspacePageWidth; + float parallaxFactor = 0.5f; + return new float[]{scale, 0, -getDefaultSwipeHeight(launcher) * parallaxFactor}; } @Override @@ -58,6 +68,7 @@ public class OverviewState extends LauncherState { public void onStateEnabled(Launcher launcher) { RecentsView rv = launcher.getOverviewPanel(); rv.setOverviewStateEnabled(true); + AbstractFloatingView.closeAllOpenViews(launcher); } @Override @@ -69,6 +80,7 @@ public class OverviewState extends LauncherState { @Override public void onStateTransitionEnd(Launcher launcher) { launcher.getRotationHelper().setCurrentStateRequest(REQUEST_ROTATE); + DiscoveryBounce.showForOverviewIfNeeded(launcher); } @Override @@ -88,14 +100,19 @@ public class OverviewState extends LauncherState { @Override public int getVisibleElements(Launcher launcher) { if (launcher.getDeviceProfile().isVerticalBarLayout()) { - return DRAG_HANDLE_INDICATOR; + return 0; } else { - return HOTSEAT_SEARCH_BOX | DRAG_HANDLE_INDICATOR | + return HOTSEAT_SEARCH_BOX | (launcher.getAppsView().getFloatingHeaderView().hasVisibleContent() ? ALL_APPS_HEADER_EXTRA : HOTSEAT_ICONS); } } + @Override + public float getWorkspaceScrimAlpha(Launcher launcher) { + return 0.5f; + } + @Override public float getVerticalProgress(Launcher launcher) { if ((getVisibleElements(launcher) & ALL_APPS_HEADER_EXTRA) == 0) { diff --git a/quickstep/src/com/android/launcher3/uioverrides/LandscapeStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/OverviewToAllAppsTouchController.java similarity index 83% rename from quickstep/src/com/android/launcher3/uioverrides/LandscapeStatesTouchController.java rename to quickstep/src/com/android/launcher3/uioverrides/OverviewToAllAppsTouchController.java index 30ceb43f93..0f9b57f033 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/LandscapeStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/OverviewToAllAppsTouchController.java @@ -24,15 +24,18 @@ import android.view.MotionEvent; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.quickstep.TouchInteractionService; import com.android.quickstep.views.RecentsView; /** - * Touch controller from going from OVERVIEW to ALL_APPS + * Touch controller from going from OVERVIEW to ALL_APPS. + * + * This is used in landscape mode. It is also used in portrait mode for the fallback recents. */ -public class LandscapeStatesTouchController extends PortraitStatesTouchController { +public class OverviewToAllAppsTouchController extends PortraitStatesTouchController { - public LandscapeStatesTouchController(Launcher l) { + public OverviewToAllAppsTouchController(Launcher l) { super(l); } @@ -69,4 +72,9 @@ public class LandscapeStatesTouchController extends PortraitStatesTouchControlle } return fromState; } + + @Override + protected int getLogContainerTypeForNormalState() { + return LauncherLogProto.ContainerType.WORKSPACE; + } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java index 012b545212..987f952baf 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/PortraitStatesTouchController.java @@ -18,20 +18,20 @@ package com.android.launcher3.uioverrides; import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; -import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATION; import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS; -import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.view.MotionEvent; import android.view.animation.Interpolator; +import android.view.animation.OvershootInterpolator; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.launcher3.LauncherStateManager.AnimationComponents; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.anim.Interpolators; @@ -39,8 +39,8 @@ import com.android.launcher3.touch.AbstractStateChangeTouchController; import com.android.launcher3.touch.SwipeDetector; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; +import com.android.quickstep.RecentsModel; import com.android.quickstep.TouchInteractionService; -import com.android.quickstep.util.SysuiEventLogger; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; @@ -49,43 +49,13 @@ import com.android.quickstep.views.TaskView; */ public class PortraitStatesTouchController extends AbstractStateChangeTouchController { - private static final float TOTAL_DISTANCE_MULTIPLIER = 3f; - private static final float LINEAR_SCALE_LIMIT = 1 / TOTAL_DISTANCE_MULTIPLIER; - - // Must be greater than LINEAR_SCALE_LIMIT; - private static final float MAXIMUM_DISTANCE_FACTOR = 0.9f; - - // Maximum amount to overshoot. - private static final float MAX_OVERSHOOT = 0.3f; - - private static final double PI_BY_2 = Math.PI / 2; + private static final String TAG = "PortraitStatesTouchCtrl"; private InterpolatorWrapper mAllAppsInterpolatorWrapper = new InterpolatorWrapper(); // If true, we will finish the current animation instantly on second touch. private boolean mFinishFastOnSecondTouch; - private final Interpolator mAllAppsDampedInterpolator = new Interpolator() { - - private final double mAngleMultiplier = Math.PI / - (2 * (MAXIMUM_DISTANCE_FACTOR - LINEAR_SCALE_LIMIT)); - - @Override - public float getInterpolation(float v) { - if (v <= LINEAR_SCALE_LIMIT) { - return v * TOTAL_DISTANCE_MULTIPLIER; - } - float overshoot = (v - LINEAR_SCALE_LIMIT); - return (float) (1 + MAX_OVERSHOOT * Math.sin(overshoot * mAngleMultiplier)); - } - }; - - private final Interpolator mOverviewBoundInterpolator = (v) -> { - if (v >= MAXIMUM_DISTANCE_FACTOR) { - return 1; - } - return FAST_OUT_SLOW_IN.getInterpolation(v / MAXIMUM_DISTANCE_FACTOR); - }; public PortraitStatesTouchController(Launcher l) { super(l, SwipeDetector.VERTICAL); @@ -121,24 +91,6 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr return true; } - @Override - protected int getSwipeDirection(MotionEvent ev) { - final int directionsToDetectScroll; - if (mLauncher.isInState(ALL_APPS)) { - directionsToDetectScroll = SwipeDetector.DIRECTION_NEGATIVE; - mStartContainerType = ContainerType.ALLAPPS; - } else if (mLauncher.isInState(NORMAL)) { - directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE; - mStartContainerType = ContainerType.HOTSEAT; - } else if (mLauncher.isInState(OVERVIEW)) { - directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH; - mStartContainerType = ContainerType.TASKSWITCHER; - } else { - return 0; - } - return directionsToDetectScroll; - } - @Override protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) { if (fromState == ALL_APPS && !isDragTowardPositive) { @@ -147,24 +99,28 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr mLauncher.getStateManager().getLastState() : NORMAL; } else if (fromState == OVERVIEW) { return isDragTowardPositive ? ALL_APPS : NORMAL; - } else if (isDragTowardPositive) { + } else if (fromState == NORMAL && isDragTowardPositive) { return TouchInteractionService.isConnected() ? OVERVIEW : ALL_APPS; } return fromState; } + @Override + protected int getLogContainerTypeForNormalState() { + return ContainerType.HOTSEAT; + } + private AnimatorSetBuilder getNormalToOverviewAnimation() { - mAllAppsInterpolatorWrapper.baseInterpolator = mAllAppsDampedInterpolator; + mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR; AnimatorSetBuilder builder = new AnimatorSetBuilder(); builder.setInterpolator(ANIM_VERTICAL_PROGRESS, mAllAppsInterpolatorWrapper); - builder.setInterpolator(ANIM_OVERVIEW_TRANSLATION, mOverviewBoundInterpolator); return builder; } @Override - protected float initCurrentAnimation() { + protected float initCurrentAnimation(@AnimationComponents int animComponents) { float range = getShiftRange(); long maxAccuracy = (long) (2 * range); @@ -177,15 +133,11 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr if (mFromState == NORMAL && mToState == OVERVIEW && totalShift != 0) { builder = getNormalToOverviewAnimation(); - totalShift = totalShift * TOTAL_DISTANCE_MULTIPLIER; } else { builder = new AnimatorSetBuilder(); } - if (mPendingAnimation != null) { - mPendingAnimation.finish(false, Touch.SWIPE); - mPendingAnimation = null; - } + cancelPendingAnim(); RecentsView recentsView = mLauncher.getOverviewPanel(); TaskView taskView = (TaskView) recentsView.getChildAt(recentsView.getNextPage()); @@ -194,10 +146,17 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr mPendingAnimation = recentsView.createTaskLauncherAnimation(taskView, maxAccuracy); mPendingAnimation.anim.setInterpolator(Interpolators.ZOOM_IN); - mCurrentAnimation = AnimatorPlaybackController.wrap(mPendingAnimation.anim, maxAccuracy); + Runnable onCancelRunnable = () -> { + cancelPendingAnim(); + clearState(); + }; + mCurrentAnimation = AnimatorPlaybackController.wrap(mPendingAnimation.anim, maxAccuracy, + onCancelRunnable); + mLauncher.getStateManager().setCurrentUserControlledAnimation(mCurrentAnimation); } else { mCurrentAnimation = mLauncher.getStateManager() - .createAnimationToNewWorkspace(mToState, builder, maxAccuracy); + .createAnimationToNewWorkspace(mToState, builder, maxAccuracy, this::clearState, + animComponents); } if (totalShift == 0) { @@ -207,12 +166,19 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr return 1 / totalShift; } + private void cancelPendingAnim() { + if (mPendingAnimation != null) { + mPendingAnimation.finish(false, Touch.SWIPE); + mPendingAnimation = null; + } + } + @Override protected void updateSwipeCompleteAnimation(ValueAnimator animator, long expectedDuration, LauncherState targetState, float velocity, boolean isFling) { - handleFirstSwipeToOverview(animator, expectedDuration, targetState, velocity, isFling); super.updateSwipeCompleteAnimation(animator, expectedDuration, targetState, velocity, isFling); + handleFirstSwipeToOverview(animator, expectedDuration, targetState, velocity, isFling); } private void handleFirstSwipeToOverview(final ValueAnimator animator, @@ -220,69 +186,24 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr final boolean isFling) { if (mFromState == NORMAL && mToState == OVERVIEW && targetState == OVERVIEW) { mFinishFastOnSecondTouch = true; - - // Update all apps interpolator - float currentFraction = mCurrentAnimation.getProgressFraction(); - float absVelocity = Math.abs(velocity); - float currentValue = mAllAppsDampedInterpolator.getInterpolation(currentFraction); - - if (isFling && absVelocity > 1 && currentFraction < LINEAR_SCALE_LIMIT) { - - // TODO: Clean up these magic calculations - // Linearly interpolate the max value based on the velocity. - float maxValue = Math.max(absVelocity > 4 ? 1 + MAX_OVERSHOOT : - 1 + (absVelocity - 1) * MAX_OVERSHOOT / 3, - currentValue); - double angleToPeak = PI_BY_2 - Math.asin(currentValue / maxValue); - - if (expectedDuration != 0 && angleToPeak != 0) { - - float distanceLeft = 1 - currentFraction; - mAllAppsInterpolatorWrapper.baseInterpolator = (f) -> { - float scaledF = (f - currentFraction) / distanceLeft; - - if (scaledF < 0.5f) { - double angle = PI_BY_2 - angleToPeak + scaledF * angleToPeak / 0.5f; - return (float) (maxValue * Math.sin(angle)); - } - - scaledF = ((scaledF - .5f) / .5f); - double angle = PI_BY_2 + 3 * scaledF * PI_BY_2; - float amplitude = (1 - scaledF) * (1 - scaledF) * (maxValue - 1); - return 1 + (float) (amplitude * Math.sin(angle)); - }; - - animator.setDuration(expectedDuration).setInterpolator(LINEAR); - return; - } + if (isFling && expectedDuration != 0) { + // Update all apps interpolator to add a bit of overshoot starting from currFraction + final float currFraction = mCurrentAnimation.getProgressFraction(); + mAllAppsInterpolatorWrapper.baseInterpolator = Interpolators.clampToProgress( + new OvershootInterpolator(Math.min(Math.abs(velocity), 3f)), currFraction, 1); + animator.setDuration(Math.min(expectedDuration, ATOMIC_DURATION)) + .setInterpolator(LINEAR); } - - if (currentFraction < LINEAR_SCALE_LIMIT) { - mAllAppsInterpolatorWrapper.baseInterpolator = LINEAR; - return; - } - float extraValue = mAllAppsDampedInterpolator.getInterpolation(currentFraction) - 1; - float distanceLeft = 1 - currentFraction; - - animator.setFloatValues(currentFraction, 1); - mAllAppsInterpolatorWrapper.baseInterpolator = (f) -> { - float scaledF = (f - currentFraction) / distanceLeft; - - double angle = scaledF * 1.5 * Math.PI; - float amplitude = (1 - scaledF) * (1 - scaledF) * extraValue; - return 1 + (float) (amplitude * Math.sin(angle)); - }; - animator.setDuration(200).setInterpolator(LINEAR); - return; + } else { + mFinishFastOnSecondTouch = false; } - mFinishFastOnSecondTouch = false; } @Override protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) { super.onSwipeInteractionCompleted(targetState, logAction); if (mFromState == NORMAL && targetState == OVERVIEW) { - SysuiEventLogger.writeDummyRecentsTransition(0); + RecentsModel.getInstance(mLauncher).onOverviewShown(true, TAG); } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 124ec202d1..e43b24a6af 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -15,39 +15,49 @@ */ package com.android.launcher3.uioverrides; -import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATION; +import static com.android.launcher3.LauncherState.FAST_OVERVIEW; +import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE; +import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR; +import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR; import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR; import static com.android.quickstep.views.RecentsView.ADJACENT_SCALE; -import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA; +import static com.android.quickstep.views.RecentsViewContainer.CONTENT_ALPHA; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.os.Build; +import android.view.animation.Interpolator; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherStateManager.AnimationConfig; import com.android.launcher3.LauncherStateManager.StateHandler; import com.android.launcher3.anim.AnimatorSetBuilder; +import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.PropertySetter; import com.android.quickstep.views.LauncherRecentsView; +import com.android.quickstep.views.RecentsViewContainer; @TargetApi(Build.VERSION_CODES.O) public class RecentsViewStateController implements StateHandler { private final Launcher mLauncher; private final LauncherRecentsView mRecentsView; + private final RecentsViewContainer mRecentsViewContainer; public RecentsViewStateController(Launcher launcher) { mLauncher = launcher; mRecentsView = launcher.getOverviewPanel(); + mRecentsViewContainer = launcher.getOverviewPanelContainer(); } @Override public void setState(LauncherState state) { - mRecentsView.setContentAlpha(state.overviewUi ? 1 : 0); + mRecentsViewContainer.setContentAlpha(state.overviewUi ? 1 : 0); float[] scaleTranslationYFactor = state.getOverviewScaleAndTranslationYFactor(mLauncher); mRecentsView.setAdjacentScale(scaleTranslationYFactor[0]); mRecentsView.setTranslationYFactor(scaleTranslationYFactor[1]); @@ -60,14 +70,23 @@ public class RecentsViewStateController implements StateHandler { @Override public void setStateWithAnimation(final LauncherState toState, AnimatorSetBuilder builder, AnimationConfig config) { - PropertySetter setter = config.getProperSetter(builder); + if (!config.playAtomicComponent()) { + // The entire recents animation is played atomically. + return; + } + PropertySetter setter = config.getPropertySetter(builder); float[] scaleTranslationYFactor = toState.getOverviewScaleAndTranslationYFactor(mLauncher); - setter.setFloat(mRecentsView, ADJACENT_SCALE, scaleTranslationYFactor[0], - builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR)); + Interpolator scaleInterpolator = builder.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR); + setter.setFloat(mRecentsView, ADJACENT_SCALE, scaleTranslationYFactor[0], scaleInterpolator); + Interpolator transYInterpolator = scaleInterpolator; + if (mLauncher.getStateManager().getState() == OVERVIEW && toState == FAST_OVERVIEW) { + transYInterpolator = Interpolators.clampToProgress(QUICK_SCRUB_START_INTERPOLATOR, 0, + QUICK_SCRUB_TRANSLATION_Y_FACTOR); + } setter.setFloat(mRecentsView, TRANSLATION_Y_FACTOR, scaleTranslationYFactor[1], - builder.getInterpolator(ANIM_OVERVIEW_TRANSLATION, LINEAR)); - setter.setFloat(mRecentsView, CONTENT_ALPHA, toState.overviewUi ? 1 : 0, - AGGRESSIVE_EASE_IN_OUT); + transYInterpolator); + setter.setFloat(mRecentsViewContainer, CONTENT_ALPHA, toState.overviewUi ? 1 : 0, + builder.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT)); if (!toState.overviewUi) { builder.addOnFinishRunnable(mRecentsView::resetTaskVisuals); diff --git a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java index 84a60bd9a0..a40573500f 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/TaskViewTouchController.java @@ -15,25 +15,27 @@ */ package com.android.launcher3.uioverrides; +import static com.android.launcher3.Utilities.SINGLE_FRAME_MS; import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; -import android.util.Log; import android.view.MotionEvent; -import android.view.View; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.LauncherAnimUtils; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.touch.SwipeDetector; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; +import com.android.launcher3.util.FlingBlockCheck; import com.android.launcher3.util.PendingAnimation; import com.android.launcher3.util.TouchController; import com.android.launcher3.views.BaseDragLayer; +import com.android.quickstep.OverviewInteractionState; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; @@ -45,9 +47,6 @@ public abstract class TaskViewTouchController private static final String TAG = "OverviewSwipeController"; - private static final float ALLOWED_FLING_DIRECTION_CHANGE_PROGRESS = 0.1f; - private static final int SINGLE_FRAME_MS = 16; - // Progress after which the transition is assumed to be a success in case user does not fling private static final float SUCCESS_TRANSITION_PROGRESS = 0.5f; @@ -65,6 +64,7 @@ public abstract class TaskViewTouchController private float mDisplacementShift; private float mProgressMultiplier; private float mEndDisplacement; + private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck(); private TaskView mTaskBeingDragged; @@ -87,12 +87,13 @@ public abstract class TaskViewTouchController protected abstract boolean isRecentsInteractive(); + protected void onUserControlledAnimationCreated(AnimatorPlaybackController animController) { + } + @Override public void onAnimationCancel(Animator animation) { if (mCurrentAnimation != null && animation == mCurrentAnimation.getTarget()) { - Log.e(TAG, "Who dare cancel the animation when I am in control", new Exception()); - mDetector.finishedScrolling(); - mCurrentAnimation = null; + clearState(); } } @@ -106,7 +107,7 @@ public abstract class TaskViewTouchController // Now figure out which direction scroll events the controller will start // calling the callbacks. - final int directionsToDetectScroll; + int directionsToDetectScroll = 0; boolean ignoreSlopWhenSettling = false; if (mCurrentAnimation != null) { directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH; @@ -114,12 +115,26 @@ public abstract class TaskViewTouchController } else { mTaskBeingDragged = null; - View view = mRecentsView.getChildAt(mRecentsView.getCurrentPage()); - if (view instanceof TaskView && mActivity.getDragLayer().isEventOverView(view, ev)) { - // The tile can be dragged down to open the task. - mTaskBeingDragged = (TaskView) view; - directionsToDetectScroll = SwipeDetector.DIRECTION_BOTH; - } else { + for (int i = 0; i < mRecentsView.getChildCount(); i++) { + TaskView view = mRecentsView.getPageAt(i); + if (mRecentsView.isTaskViewVisible(view) && mActivity.getDragLayer() + .isEventOverView(view, ev)) { + mTaskBeingDragged = view; + if (!OverviewInteractionState.getInstance(mActivity) + .isSwipeUpGestureEnabled()) { + // Don't allow swipe down to open if we don't support swipe up + // to enter overview. + directionsToDetectScroll = SwipeDetector.DIRECTION_POSITIVE; + } else { + // The task can be dragged up to dismiss it, + // and down to open if it's the current page. + directionsToDetectScroll = i == mRecentsView.getCurrentPage() + ? SwipeDetector.DIRECTION_BOTH : SwipeDetector.DIRECTION_POSITIVE; + } + break; + } + } + if (mTaskBeingDragged == null) { mNoIntercept = true; return false; } @@ -147,6 +162,12 @@ public abstract class TaskViewTouchController // No need to init return; } + int scrollDirections = mDetector.getScrollDirections(); + if (goingUp && ((scrollDirections & SwipeDetector.DIRECTION_POSITIVE) == 0) + || !goingUp && ((scrollDirections & SwipeDetector.DIRECTION_NEGATIVE) == 0)) { + // Trying to re-init in an unsupported direction. + return; + } if (mCurrentAnimation != null) { mCurrentAnimation.setPlayFraction(0); } @@ -174,8 +195,12 @@ public abstract class TaskViewTouchController mEndDisplacement = dl.getHeight() - mTempCords[1]; } + if (mCurrentAnimation != null) { + mCurrentAnimation.setOnCancelRunnable(null); + } mCurrentAnimation = AnimatorPlaybackController - .wrap(mPendingAnimation.anim, maxDuration); + .wrap(mPendingAnimation.anim, maxDuration, this::clearState); + onUserControlledAnimationCreated(mCurrentAnimation); mCurrentAnimation.getTarget().addListener(this); mCurrentAnimation.dispatchOnStart(); mProgressMultiplier = 1 / mEndDisplacement; @@ -190,6 +215,7 @@ public abstract class TaskViewTouchController mDisplacementShift = mCurrentAnimation.getProgressFraction() / mProgressMultiplier; mCurrentAnimation.pause(); } + mFlingBlockCheck.unblockFling(); } @Override @@ -199,6 +225,9 @@ public abstract class TaskViewTouchController totalDisplacement == 0 ? mCurrentAnimationIsGoingUp : totalDisplacement < 0; if (isGoingUp != mCurrentAnimationIsGoingUp) { reInitAnimationController(isGoingUp); + mFlingBlockCheck.blockFling(); + } else { + mFlingBlockCheck.onEvent(); } mCurrentAnimation.setPlayFraction(totalDisplacement * mProgressMultiplier); return true; @@ -208,23 +237,14 @@ public abstract class TaskViewTouchController public void onDragEnd(float velocity, boolean fling) { final boolean goingToEnd; final int logAction; + boolean blockedFling = fling && mFlingBlockCheck.isBlocked(); + if (blockedFling) { + fling = false; + } if (fling) { logAction = Touch.FLING; boolean goingUp = velocity < 0; - if (goingUp != mCurrentAnimationIsGoingUp) { - // In case the fling is in opposite direction, make sure if is close enough - // from the start position - if (mCurrentAnimation.getProgressFraction() - >= ALLOWED_FLING_DIRECTION_CHANGE_PROGRESS) { - // Not allowed - goingToEnd = false; - } else { - reInitAnimationController(goingUp); - goingToEnd = true; - } - } else { - goingToEnd = true; - } + goingToEnd = goingUp == mCurrentAnimationIsGoingUp; } else { logAction = Touch.SWIPE; goingToEnd = mCurrentAnimation.getProgressFraction() > SUCCESS_TRANSITION_PROGRESS; @@ -233,6 +253,9 @@ public abstract class TaskViewTouchController float progress = mCurrentAnimation.getProgressFraction(); long animationDuration = SwipeDetector.calculateDuration( velocity, goingToEnd ? (1 - progress) : progress); + if (blockedFling && !goingToEnd) { + animationDuration *= LauncherAnimUtils.blockedFlingDurationFactor(velocity); + } float nextFrameProgress = Utilities.boundToRange( progress + velocity * SINGLE_FRAME_MS / Math.abs(mEndDisplacement), 0f, 1f); @@ -251,8 +274,17 @@ public abstract class TaskViewTouchController mPendingAnimation.finish(wasSuccess, logAction); mPendingAnimation = null; } + clearState(); + } + + private void clearState() { mDetector.finishedScrolling(); + mDetector.setDetectableScrollConditions(0, false); mTaskBeingDragged = null; mCurrentAnimation = null; + if (mPendingAnimation != null) { + mPendingAnimation.finish(false, Touch.SWIPE); + mPendingAnimation = null; + } } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java index c1590f63de..b371677f39 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java @@ -16,51 +16,67 @@ package com.android.launcher3.uioverrides; +import static android.view.View.VISIBLE; +import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; +import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_BACK_BUTTON; +import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; -import static com.android.launcher3.Utilities.getPrefs; -import static com.android.quickstep.OverviewInteractionState.KEY_SWIPE_UP_ENABLED; -import static com.android.launcher3.LauncherState.ALL_APPS; +import static com.android.launcher3.allapps.DiscoveryBounce.HOME_BOUNCE_SEEN; +import static com.android.launcher3.allapps.DiscoveryBounce.SHELF_BOUNCE_SEEN; +import android.app.Activity; import android.content.Context; -import android.content.SharedPreferences; +import android.util.Base64; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.launcher3.LauncherStateManager; import com.android.launcher3.LauncherStateManager.StateHandler; +import com.android.launcher3.Utilities; +import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.util.TouchController; import com.android.quickstep.OverviewInteractionState; import com.android.quickstep.RecentsModel; import com.android.quickstep.views.RecentsView; +import com.android.systemui.shared.system.ActivityCompat; import com.android.systemui.shared.system.WindowManagerWrapper; +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; +import java.util.zip.Deflater; + public class UiFactory { public static TouchController[] createTouchControllers(Launcher launcher) { - SharedPreferences prefs = getPrefs(launcher); - boolean swipeUpEnabled = prefs.getBoolean(KEY_SWIPE_UP_ENABLED, true); + boolean swipeUpEnabled = OverviewInteractionState.getInstance(launcher) + .isSwipeUpGestureEnabled(); if (!swipeUpEnabled) { return new TouchController[] { launcher.getDragController(), - new LandscapeStatesTouchController(launcher), - new LauncherTaskViewcontroller(launcher)}; + new OverviewToAllAppsTouchController(launcher), + new LauncherTaskViewController(launcher)}; } if (launcher.getDeviceProfile().isVerticalBarLayout()) { return new TouchController[] { launcher.getDragController(), - new LandscapeStatesTouchController(launcher), + new OverviewToAllAppsTouchController(launcher), new LandscapeEdgeSwipeController(launcher), - new LauncherTaskViewcontroller(launcher)}; + new LauncherTaskViewController(launcher)}; } else { return new TouchController[] { launcher.getDragController(), new PortraitStatesTouchController(launcher), - new LauncherTaskViewcontroller(launcher)}; + new LauncherTaskViewController(launcher)}; } } + public static void setOnTouchControllersChangedListener(Context context, Runnable listener) { + OverviewInteractionState.getInstance(context).setOnSwipeUpSettingChangedListener(listener); + } + public static StateHandler[] getStateHandler(Launcher launcher) { return new StateHandler[] { launcher.getAllAppsController(), launcher.getWorkspace(), @@ -73,10 +89,15 @@ public class UiFactory { && launcher.hasWindowFocus(); if (shouldBackButtonBeHidden) { // Show the back button if there is a floating view visible. - shouldBackButtonBeHidden = AbstractFloatingView.getTopOpenView(launcher) == null; + shouldBackButtonBeHidden = AbstractFloatingView.getTopOpenViewWithType(launcher, + TYPE_ALL & ~TYPE_HIDE_BACK_BUTTON) == null; } OverviewInteractionState.getInstance(launcher) - .setBackButtonVisible(!shouldBackButtonBeHidden); + .setBackButtonAlpha(shouldBackButtonBeHidden ? 0 : 1, true /* animate */); + } + + public static void setBackButtonAlpha(Launcher launcher, float alpha, boolean animate) { + OverviewInteractionState.getInstance(launcher).setBackButtonAlpha(alpha,animate); } public static void resetOverview(Launcher launcher) { @@ -84,6 +105,55 @@ public class UiFactory { recents.reset(); } + public static void onCreate(Launcher launcher) { + if (!launcher.getSharedPrefs().getBoolean(HOME_BOUNCE_SEEN, false)) { + launcher.getStateManager().addStateListener(new LauncherStateManager.StateListener() { + @Override + public void onStateSetImmediately(LauncherState state) { + } + + @Override + public void onStateTransitionStart(LauncherState toState) { + } + + @Override + public void onStateTransitionComplete(LauncherState finalState) { + boolean swipeUpEnabled = OverviewInteractionState.getInstance(launcher) + .isSwipeUpGestureEnabled(); + LauncherState prevState = launcher.getStateManager().getLastState(); + + if (((swipeUpEnabled && finalState == OVERVIEW) || (!swipeUpEnabled + && finalState == ALL_APPS && prevState == NORMAL))) { + launcher.getSharedPrefs().edit().putBoolean(HOME_BOUNCE_SEEN, true).apply(); + launcher.getStateManager().removeStateListener(this); + } + } + }); + } + + if (!launcher.getSharedPrefs().getBoolean(SHELF_BOUNCE_SEEN, false)) { + launcher.getStateManager().addStateListener(new LauncherStateManager.StateListener() { + @Override + public void onStateSetImmediately(LauncherState state) { + } + + @Override + public void onStateTransitionStart(LauncherState toState) { + } + + @Override + public void onStateTransitionComplete(LauncherState finalState) { + LauncherState prevState = launcher.getStateManager().getLastState(); + + if (finalState == ALL_APPS && prevState == OVERVIEW) { + launcher.getSharedPrefs().edit().putBoolean(SHELF_BOUNCE_SEEN, true).apply(); + launcher.getStateManager().removeStateListener(this); + } + } + }); + } + } + public static void onStart(Context context) { RecentsModel model = RecentsModel.getInstance(context); if (model != null) { @@ -110,9 +180,42 @@ public class UiFactory { } } - private static class LauncherTaskViewcontroller extends TaskViewTouchController { + public static boolean dumpActivity(Activity activity, PrintWriter writer) { + if (!Utilities.IS_DEBUG_DEVICE) { + return false; + } + ByteArrayOutputStream out = new ByteArrayOutputStream(); + if (!(new ActivityCompat(activity).encodeViewHierarchy(out))) { + return false; + } - public LauncherTaskViewcontroller(Launcher activity) { + Deflater deflater = new Deflater(); + deflater.setInput(out.toByteArray()); + deflater.finish(); + + out.reset(); + byte[] buffer = new byte[1024]; + while (!deflater.finished()) { + int count = deflater.deflate(buffer); // returns the generated code... index + out.write(buffer, 0, count); + } + + writer.println("--encoded-view-dump-v0--"); + writer.println(Base64.encodeToString( + out.toByteArray(), Base64.NO_WRAP | Base64.NO_PADDING)); + return true; + } + + public static void prepareToShowOverview(Launcher launcher) { + RecentsView overview = launcher.getOverviewPanel(); + if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) { + overview.setAdjacentScale(1.33f); + } + } + + private static class LauncherTaskViewController extends TaskViewTouchController { + + public LauncherTaskViewController(Launcher activity) { super(activity); } @@ -120,5 +223,10 @@ public class UiFactory { protected boolean isRecentsInteractive() { return mActivity.isInState(OVERVIEW); } + + @Override + protected void onUserControlledAnimationCreated(AnimatorPlaybackController animController) { + mActivity.getStateManager().setCurrentUserControlledAnimation(animController); + } } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/WallpaperColorInfo.java b/quickstep/src/com/android/launcher3/uioverrides/WallpaperColorInfo.java new file mode 100644 index 0000000000..8218517dcc --- /dev/null +++ b/quickstep/src/com/android/launcher3/uioverrides/WallpaperColorInfo.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.uioverrides; + +import static android.app.WallpaperManager.FLAG_SYSTEM; + +import android.annotation.TargetApi; +import android.app.WallpaperColors; +import android.app.WallpaperManager; +import android.app.WallpaperManager.OnColorsChangedListener; +import android.content.Context; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; + +import com.android.systemui.shared.system.TonalCompat; +import com.android.systemui.shared.system.TonalCompat.ExtractionInfo; + +import java.util.ArrayList; + +@TargetApi(Build.VERSION_CODES.P) +public class WallpaperColorInfo implements OnColorsChangedListener { + + private static final Object sInstanceLock = new Object(); + private static WallpaperColorInfo sInstance; + + public static WallpaperColorInfo getInstance(Context context) { + synchronized (sInstanceLock) { + if (sInstance == null) { + sInstance = new WallpaperColorInfo(context.getApplicationContext()); + } + return sInstance; + } + } + + private final ArrayList mListeners = new ArrayList<>(); + private final WallpaperManager mWallpaperManager; + private final TonalCompat mTonalCompat; + + private ExtractionInfo mExtractionInfo; + + private OnChangeListener[] mTempListeners = new OnChangeListener[0]; + + private WallpaperColorInfo(Context context) { + mWallpaperManager = context.getSystemService(WallpaperManager.class); + mTonalCompat = new TonalCompat(context); + + mWallpaperManager.addOnColorsChangedListener(this, new Handler(Looper.getMainLooper())); + update(mWallpaperManager.getWallpaperColors(FLAG_SYSTEM)); + } + + public int getMainColor() { + return mExtractionInfo.mainColor; + } + + public int getSecondaryColor() { + return mExtractionInfo.secondaryColor; + } + + public boolean isDark() { + return mExtractionInfo.supportsDarkTheme; + } + + public boolean supportsDarkText() { + return mExtractionInfo.supportsDarkText; + } + + @Override + public void onColorsChanged(WallpaperColors colors, int which) { + if ((which & FLAG_SYSTEM) != 0) { + update(colors); + notifyChange(); + } + } + + private void update(WallpaperColors wallpaperColors) { + mExtractionInfo = mTonalCompat.extractDarkColors(wallpaperColors); + } + + public void addOnChangeListener(OnChangeListener listener) { + mListeners.add(listener); + } + + public void removeOnChangeListener(OnChangeListener listener) { + mListeners.remove(listener); + } + + private void notifyChange() { + // Create a new array to avoid concurrent modification when the activity destroys itself. + mTempListeners = mListeners.toArray(mTempListeners); + for (OnChangeListener listener : mTempListeners) { + if (listener != null) { + listener.onExtractedColorsChanged(this); + } + } + } + + public interface OnChangeListener { + void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo); + } +} diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java index 584128585f..ae0affee04 100644 --- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java +++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java @@ -15,16 +15,23 @@ */ package com.android.quickstep; +import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS; import static com.android.launcher3.LauncherState.FAST_OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK; +import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; +import android.annotation.TargetApi; +import android.app.ActivityManager.RunningTaskInfo; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.Rect; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.support.annotation.Nullable; @@ -38,56 +45,53 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherInitListener; import com.android.launcher3.LauncherState; import com.android.launcher3.allapps.AllAppsTransitionController; +import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.anim.AnimatorPlaybackController; -import com.android.launcher3.util.ViewOnDrawExecutor; -import com.android.quickstep.fallback.FallbackRecentsView; +import com.android.launcher3.dragndrop.DragLayer; +import com.android.launcher3.userevent.nano.LauncherLogProto; +import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; +import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.util.RemoteAnimationProvider; +import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.views.LauncherLayoutListener; import com.android.quickstep.views.LauncherRecentsView; import com.android.quickstep.views.RecentsView; -import com.android.quickstep.views.TaskView; -import com.android.systemui.shared.system.ActivityManagerWrapper; -import com.android.systemui.shared.system.AssistDataReceiver; -import com.android.systemui.shared.system.RecentsAnimationListener; +import com.android.quickstep.views.RecentsViewContainer; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import java.util.Objects; import java.util.function.BiPredicate; +import java.util.function.Consumer; /** * Utility class which abstracts out the logical differences between Launcher and RecentsActivity. */ +@TargetApi(Build.VERSION_CODES.P) public interface ActivityControlHelper { LayoutListener createLayoutListener(T activity); - void onQuickstepGestureStarted(T activity, boolean activityVisible); - /** * Updates the UI to indicate quick interaction. - * @return true if there any any UI change as a result of this */ - boolean onQuickInteractionStart(T activity, boolean activityVisible); + void onQuickInteractionStart(T activity, @Nullable RunningTaskInfo taskInfo, + boolean activityVisible); + + float getTranslationYForQuickScrub(T activity); void executeOnWindowAvailable(T activity, Runnable action); - void executeOnNextDraw(T activity, TaskView targetView, Runnable action); - void onTransitionCancelled(T activity, boolean activityVisible); int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect); void onSwipeUpComplete(T activity); - void prepareRecentsUI(T activity, boolean activityVisible); - - AnimatorPlaybackController createControllerForVisibleActivity(T activity); - - AnimatorPlaybackController createControllerForHiddenActivity(T activity, int transitionLength); + AnimationFactory prepareRecentsUI(T activity, boolean activityVisible, + Consumer callback); ActivityInitListener createActivityInitListener(BiPredicate onInitListener); - void startRecentsFromSwipe(Intent intent, AssistDataReceiver assistDataReceiver, - final RecentsAnimationListener remoteAnimationListener); - @Nullable T getCreatedActivity(); @@ -96,7 +100,31 @@ public interface ActivityControlHelper { RecentsView getVisibleRecentsView(); @UiThread - boolean switchToRecentsIfVisible(); + boolean switchToRecentsIfVisible(boolean fromRecentsButton); + + Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target); + + boolean shouldMinimizeSplitScreen(); + + /** + * @return {@code true} if recents activity should be started immediately on touchDown, + * {@code false} if it should deferred until some threshold is crossed. + */ + boolean deferStartingActivity(int downHitTarget); + + boolean supportsLongSwipe(T activity); + + AlphaProperty getAlphaProperty(T activity); + + /** + * Must return a non-null controller is supportsLongSwipe was true. + */ + LongSwipeHelper getLongSwipeController(T activity, RemoteAnimationTargetSet targetSet); + + /** + * Used for containerType in {@link com.android.launcher3.logging.UserEventDispatcher} + */ + int getContainerType(); class LauncherActivityControllerHelper implements ActivityControlHelper { @@ -106,42 +134,31 @@ public interface ActivityControlHelper { } @Override - public void onQuickstepGestureStarted(Launcher activity, boolean activityVisible) { - activity.onQuickstepGestureStarted(activityVisible); + public void onQuickInteractionStart(Launcher activity, RunningTaskInfo taskInfo, + boolean activityVisible) { + LauncherState fromState = activity.getStateManager().getState(); + activity.getStateManager().goToState(FAST_OVERVIEW, activityVisible); + + QuickScrubController controller = activity.getOverviewPanel() + .getQuickScrubController(); + controller.onQuickScrubStart(activityVisible && !fromState.overviewUi, this); } @Override - public boolean onQuickInteractionStart(Launcher activity, boolean activityVisible) { - LauncherState fromState = activity.getStateManager().getState(); - activity.getStateManager().goToState(FAST_OVERVIEW, activityVisible); - return !fromState.overviewUi; + public float getTranslationYForQuickScrub(Launcher activity) { + LauncherRecentsView recentsView = activity.getOverviewPanel(); + float transYFactor = FAST_OVERVIEW.getOverviewScaleAndTranslationYFactor(activity)[1]; + return recentsView.computeTranslationYForFactor(transYFactor); } @Override public void executeOnWindowAvailable(Launcher activity, Runnable action) { - if (activity.getWorkspace().runOnOverlayHidden(action)) { - // Notify the activity that qiuckscrub has started - onQuickstepGestureStarted(activity, true); - } - } - - @Override - public void executeOnNextDraw(Launcher activity, TaskView targetView, Runnable action) { - ViewOnDrawExecutor executor = new ViewOnDrawExecutor() { - @Override - public void onViewDetachedFromWindow(View v) { - if (!isCompleted()) { - runAllTasks(); - } - } - }; - executor.attachTo(activity, targetView, false /* waitForLoadAnimation */); - executor.execute(action); + activity.getWorkspace().runOnOverlayHidden(action); } @Override public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) { - LauncherRecentsView.getPageRect(dp, context, outRect); + LayoutUtils.calculateLauncherTaskSize(context, dp, outRect); if (dp.isVerticalBarLayout()) { Rect targetInsets = dp.getInsets(); int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right; @@ -161,15 +178,19 @@ public interface ActivityControlHelper { public void onSwipeUpComplete(Launcher activity) { // Re apply state in case we did something funky during the transition. activity.getStateManager().reapplyState(); + DiscoveryBounce.showForOverviewIfNeeded(activity); } @Override - public void prepareRecentsUI(Launcher activity, boolean activityVisible) { - LauncherState startState = activity.getStateManager().getState(); + public AnimationFactory prepareRecentsUI(Launcher activity, boolean activityVisible, + Consumer callback) { + final LauncherState startState = activity.getStateManager().getState(); + + LauncherState resetState = startState; if (startState.disableRestore) { - startState = activity.getStateManager().getRestState(); + resetState = activity.getStateManager().getRestState(); } - activity.getStateManager().setRestState(startState); + activity.getStateManager().setRestState(resetState); if (!activityVisible) { // Since the launcher is not visible, we can safely reset the scroll position. @@ -180,38 +201,53 @@ public interface ActivityControlHelper { // Optimization, hide the all apps view to prevent layout while initializing activity.getAppsView().getContentView().setVisibility(View.GONE); } + + return new AnimationFactory() { + @Override + public void createActivityController(long transitionLength) { + createActivityControllerInternal(activity, activityVisible, startState, + transitionLength, callback); + } + + @Override + public void onTransitionCancelled() { + activity.getStateManager().goToState(startState, false /* animate */); + } + }; } - @Override - public AnimatorPlaybackController createControllerForVisibleActivity(Launcher activity) { - DeviceProfile dp = activity.getDeviceProfile(); - long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx); - return activity.getStateManager().createAnimationToNewWorkspace(OVERVIEW, accuracy); - } - - @Override - public AnimatorPlaybackController createControllerForHiddenActivity( - Launcher activity, int transitionLength) { - AllAppsTransitionController controller = activity.getAllAppsController(); - AnimatorSet anim = new AnimatorSet(); - if (activity.getDeviceProfile().isVerticalBarLayout()) { - // TODO: - } else { - float scrollRange = Math.max(controller.getShiftRange(), 1); - float progressDelta = (transitionLength / scrollRange); - - float endProgress = OVERVIEW.getVerticalProgress(activity); - float startProgress = endProgress + progressDelta; - ObjectAnimator shiftAnim = ObjectAnimator.ofFloat( - controller, ALL_APPS_PROGRESS, startProgress, endProgress); - shiftAnim.setInterpolator(LINEAR); - anim.play(shiftAnim); + private void createActivityControllerInternal(Launcher activity, boolean wasVisible, + LauncherState startState, long transitionLength, + Consumer callback) { + if (wasVisible) { + DeviceProfile dp = activity.getDeviceProfile(); + long accuracy = 2 * Math.max(dp.widthPx, dp.heightPx); + activity.getStateManager().goToState(startState, false); + callback.accept(activity.getStateManager() + .createAnimationToNewWorkspace(OVERVIEW, accuracy)); + return; } - // TODO: Link this animation to state animation, so that it is cancelled - // automatically on state change + if (activity.getDeviceProfile().isVerticalBarLayout()) { + return; + } + + AllAppsTransitionController controller = activity.getAllAppsController(); + AnimatorSet anim = new AnimatorSet(); + + float scrollRange = Math.max(controller.getShiftRange(), 1); + float progressDelta = (transitionLength / scrollRange); + + float endProgress = OVERVIEW.getVerticalProgress(activity); + float startProgress = endProgress + progressDelta; + ObjectAnimator shiftAnim = ObjectAnimator.ofFloat( + controller, ALL_APPS_PROGRESS, startProgress, endProgress); + shiftAnim.setInterpolator(LINEAR); + anim.play(shiftAnim); + anim.setDuration(transitionLength * 2); - return AnimatorPlaybackController.wrap(anim, transitionLength * 2); + activity.getStateManager().setCurrentAnimation(anim); + callback.accept(AnimatorPlaybackController.wrap(anim, transitionLength * 2)); } @Override @@ -220,13 +256,6 @@ public interface ActivityControlHelper { return new LauncherInitListener(onInitListener); } - @Override - public void startRecentsFromSwipe(Intent intent, AssistDataReceiver assistDataReceiver, - final RecentsAnimationListener remoteAnimationListener) { - ActivityManagerWrapper.getInstance().startRecentsActivity( - intent, assistDataReceiver, remoteAnimationListener, null, null); - } - @Nullable @Override public Launcher getCreatedActivity() { @@ -249,32 +278,96 @@ public interface ActivityControlHelper { @Override public RecentsView getVisibleRecentsView() { Launcher launcher = getVisibleLaucher(); - return launcher != null && launcher.isInState(OVERVIEW) + return launcher != null && launcher.getStateManager().getState().overviewUi ? launcher.getOverviewPanel() : null; } @Override - public boolean switchToRecentsIfVisible() { + public boolean switchToRecentsIfVisible(boolean fromRecentsButton) { Launcher launcher = getVisibleLaucher(); if (launcher != null) { + if (fromRecentsButton) { + launcher.getUserEventDispatcher().logActionCommand( + LauncherLogProto.Action.Command.RECENTS_BUTTON, + getContainerType(), + LauncherLogProto.ContainerType.TASKSWITCHER); + } launcher.getStateManager().goToState(OVERVIEW); return true; } return false; } + + @Override + public boolean deferStartingActivity(int downHitTarget) { + return downHitTarget == HIT_TARGET_BACK || downHitTarget == HIT_TARGET_ROTATION; + } + + @Override + public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) { + return homeBounds; + } + + @Override + public boolean shouldMinimizeSplitScreen() { + return true; + } + + @Override + public boolean supportsLongSwipe(Launcher activity) { + return !activity.getDeviceProfile().isVerticalBarLayout(); + } + + @Override + public LongSwipeHelper getLongSwipeController(Launcher activity, + RemoteAnimationTargetSet targetSet) { + if (activity.getDeviceProfile().isVerticalBarLayout()) { + return null; + } + return new LongSwipeHelper(activity, targetSet); + } + + @Override + public AlphaProperty getAlphaProperty(Launcher activity) { + return activity.getDragLayer().getAlphaProperty(DragLayer.ALPHA_INDEX_SWIPE_UP); + } + + @Override + public int getContainerType() { + final Launcher launcher = getVisibleLaucher(); + return launcher != null ? launcher.getStateManager().getState().containerType + : LauncherLogProto.ContainerType.APP; + } } class FallbackActivityControllerHelper implements ActivityControlHelper { - @Override - public void onQuickstepGestureStarted(RecentsActivity activity, boolean activityVisible) { - // TODO: + private final ComponentName mHomeComponent; + private final Handler mUiHandler = new Handler(Looper.getMainLooper()); + + public FallbackActivityControllerHelper(ComponentName homeComponent) { + mHomeComponent = homeComponent; } @Override - public boolean onQuickInteractionStart(RecentsActivity activity, boolean activityVisible) { - // Activity does not need any UI change for quickscrub. - return false; + public void onQuickInteractionStart(RecentsActivity activity, RunningTaskInfo taskInfo, + boolean activityVisible) { + QuickScrubController controller = activity.getOverviewPanel() + .getQuickScrubController(); + + // TODO: match user is as well + boolean startingFromHome = !activityVisible && + (taskInfo == null || Objects.equals(taskInfo.topActivity, mHomeComponent)); + controller.onQuickScrubStart(startingFromHome, this); + if (activityVisible) { + mUiHandler.postDelayed(controller::onFinishedTransitionToQuickScrub, + OVERVIEW_TRANSITION_MS); + } + } + + @Override + public float getTranslationYForQuickScrub(RecentsActivity activity) { + return 0; } @Override @@ -282,13 +375,6 @@ public interface ActivityControlHelper { action.run(); } - @Override - public void executeOnNextDraw(RecentsActivity activity, TaskView targetView, - Runnable action) { - // TODO: - new Handler(Looper.getMainLooper()).post(action); - } - @Override public void onTransitionCancelled(RecentsActivity activity, boolean activityVisible) { // TODO: @@ -296,7 +382,7 @@ public interface ActivityControlHelper { @Override public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) { - FallbackRecentsView.getPageRect(dp, context, outRect); + LayoutUtils.calculateFallbackTaskSize(context, dp, outRect); if (dp.isVerticalBarLayout()) { Rect targetInsets = dp.getInsets(); int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right; @@ -312,23 +398,43 @@ public interface ActivityControlHelper { } @Override - public void prepareRecentsUI(RecentsActivity activity, boolean activityVisible) { - // TODO: - } + public AnimationFactory prepareRecentsUI(RecentsActivity activity, boolean activityVisible, + Consumer callback) { + if (activityVisible) { + return (transitionLength) -> { }; + } - @Override - public AnimatorPlaybackController createControllerForVisibleActivity( - RecentsActivity activity) { - DeviceProfile dp = activity.getDeviceProfile(); - return createControllerForHiddenActivity(activity, Math.max(dp.widthPx, dp.heightPx)); - } + RecentsViewContainer rv = activity.getOverviewPanelContainer(); + rv.setContentAlpha(0); - @Override - public AnimatorPlaybackController createControllerForHiddenActivity( - RecentsActivity activity, int transitionLength) { - // We do not animate anything. Create a empty controller - AnimatorSet anim = new AnimatorSet(); - return AnimatorPlaybackController.wrap(anim, transitionLength * 2); + return new AnimationFactory() { + + boolean isAnimatingHome = false; + + @Override + public void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) { + isAnimatingHome = targets != null && targets.isAnimatingHome(); + if (!isAnimatingHome) { + rv.setContentAlpha(1); + } + createActivityController(getSwipeUpDestinationAndLength( + activity.getDeviceProfile(), activity, new Rect())); + } + + @Override + public void createActivityController(long transitionLength) { + if (!isAnimatingHome) { + return; + } + + ObjectAnimator anim = ObjectAnimator + .ofFloat(rv, RecentsViewContainer.CONTENT_ALPHA, 0, 1); + anim.setDuration(transitionLength).setInterpolator(LINEAR); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.play(anim); + callback.accept(AnimatorPlaybackController.wrap(animatorSet, transitionLength)); + } + }; } @Override @@ -353,14 +459,6 @@ public interface ActivityControlHelper { return new RecentsActivityTracker(onInitListener); } - @Override - public void startRecentsFromSwipe(Intent intent, AssistDataReceiver assistDataReceiver, - final RecentsAnimationListener remoteAnimationListener) { - // We can use the normal recents animation for swipe up - ActivityManagerWrapper.getInstance().startRecentsActivity( - intent, assistDataReceiver, remoteAnimationListener, null, null); - } - @Nullable @Override public RecentsActivity getCreatedActivity() { @@ -378,9 +476,48 @@ public interface ActivityControlHelper { } @Override - public boolean switchToRecentsIfVisible() { + public boolean switchToRecentsIfVisible(boolean fromRecentsButton) { return false; } + + @Override + public boolean deferStartingActivity(int downHitTarget) { + // Always defer starting the activity when using fallback + return true; + } + + @Override + public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) { + // TODO: Remove this once b/77875376 is fixed + return target.sourceContainerBounds; + } + + @Override + public boolean shouldMinimizeSplitScreen() { + // TODO: Remove this once b/77875376 is fixed + return false; + } + + @Override + public boolean supportsLongSwipe(RecentsActivity activity) { + return false; + } + + @Override + public LongSwipeHelper getLongSwipeController(RecentsActivity activity, + RemoteAnimationTargetSet targetSet) { + return null; + } + + @Override + public AlphaProperty getAlphaProperty(RecentsActivity activity) { + return activity.getDragLayer().getAlphaProperty(0); + } + + @Override + public int getContainerType() { + return LauncherLogProto.ContainerType.SIDELOADED_LAUNCHER; + } } interface LayoutListener { @@ -401,4 +538,13 @@ public interface ActivityControlHelper { void registerAndStartActivity(Intent intent, RemoteAnimationProvider animProvider, Context context, Handler handler, long duration); } + + interface AnimationFactory { + + default void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) { } + + void createActivityController(long transitionLength); + + default void onTransitionCancelled() { } + } } diff --git a/quickstep/src/com/android/quickstep/LongSwipeHelper.java b/quickstep/src/com/android/quickstep/LongSwipeHelper.java new file mode 100644 index 0000000000..fbcde8bba2 --- /dev/null +++ b/quickstep/src/com/android/quickstep/LongSwipeHelper.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep; + +import static com.android.launcher3.LauncherAnimUtils.MIN_PROGRESS_TO_ALL_APPS; +import static com.android.launcher3.LauncherState.ALL_APPS; +import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.launcher3.anim.Interpolators.DEACCEL; +import static com.android.quickstep.WindowTransformSwipeHandler.MAX_SWIPE_DURATION; +import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber; +import static com.android.systemui.shared.recents.utilities.Utilities.getSurface; + +import android.animation.ValueAnimator; +import android.view.Surface; + +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAnimUtils; +import com.android.launcher3.R; +import com.android.launcher3.allapps.AllAppsTransitionController; +import com.android.launcher3.allapps.DiscoveryBounce; +import com.android.launcher3.anim.AnimatorPlaybackController; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; +import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; +import com.android.launcher3.util.FlingBlockCheck; +import com.android.quickstep.util.RemoteAnimationTargetSet; +import com.android.quickstep.views.RecentsView; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.TransactionCompat; + +/** + * Utility class to handle long swipe from an app. + * This assumes the presence of Launcher activity as long swipe is not supported on the + * fallback activity. + */ +public class LongSwipeHelper { + + private static final float SWIPE_DURATION_MULTIPLIER = + Math.min(1 / MIN_PROGRESS_TO_ALL_APPS, 1 / (1 - MIN_PROGRESS_TO_ALL_APPS)); + + private final Launcher mLauncher; + private final RemoteAnimationTargetSet mTargetSet; + + private float mMaxSwipeDistance = 1; + private AnimatorPlaybackController mAnimator; + private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck(); + + LongSwipeHelper(Launcher launcher, RemoteAnimationTargetSet targetSet) { + mLauncher = launcher; + mTargetSet = targetSet; + init(); + } + + private void init() { + setTargetAlpha(0, true); + mFlingBlockCheck.blockFling(); + + // Init animations + AllAppsTransitionController controller = mLauncher.getAllAppsController(); + // TODO: Scale it down so that we can reach all-apps in screen space + mMaxSwipeDistance = Math.max(1, controller.getProgress() * controller.getShiftRange()); + mAnimator = mLauncher.getStateManager() + .createAnimationToNewWorkspace(ALL_APPS, Math.round(2 * mMaxSwipeDistance)); + mAnimator.dispatchOnStart(); + } + + public void onMove(float displacement) { + mAnimator.setPlayFraction(displacement / mMaxSwipeDistance); + mFlingBlockCheck.onEvent(); + } + + public void destroy() { + // TODO: We can probably also hide the task view + setTargetAlpha(1, false); + + mLauncher.getStateManager().goToState(OVERVIEW, false); + } + + public void end(float velocity, boolean isFling, Runnable callback) { + long duration = MAX_SWIPE_DURATION; + + final float currentFraction = mAnimator.getProgressFraction(); + final boolean toAllApps; + float endProgress; + + boolean blockedFling = isFling && mFlingBlockCheck.isBlocked(); + if (blockedFling) { + isFling = false; + } + + if (!isFling) { + toAllApps = currentFraction > MIN_PROGRESS_TO_ALL_APPS; + endProgress = toAllApps ? 1 : 0; + + long expectedDuration = Math.abs(Math.round((endProgress - currentFraction) + * MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER)); + duration = Math.min(MAX_SWIPE_DURATION, expectedDuration); + } else { + toAllApps = velocity < 0; + endProgress = toAllApps ? 1 : 0; + + float minFlingVelocity = mLauncher.getResources() + .getDimension(R.dimen.quickstep_fling_min_velocity); + if (Math.abs(velocity) > minFlingVelocity && mMaxSwipeDistance > 0) { + float distanceToTravel = (endProgress - currentFraction) * mMaxSwipeDistance; + + // we want the page's snap velocity to approximately match the velocity at + // which the user flings, so we scale the duration by a value near to the + // derivative of the scroll interpolator at zero, ie. 2. + long baseDuration = Math.round(1000 * Math.abs(distanceToTravel / velocity)); + duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration); + } + } + + if (blockedFling && !toAllApps) { + duration *= LauncherAnimUtils.blockedFlingDurationFactor(0); + } + final boolean finalIsFling = isFling; + mAnimator.setEndAction(() -> onSwipeAnimationComplete(toAllApps, finalIsFling, callback)); + ValueAnimator animator = mAnimator.getAnimationPlayer(); + animator.setDuration(duration).setInterpolator(DEACCEL); + animator.setFloatValues(currentFraction, endProgress); + animator.start(); + } + + private void setTargetAlpha(float alpha, boolean defer) { + final Surface surface = getSurface(mLauncher.getDragLayer()); + final long frameNumber = defer && surface != null ? getNextFrameNumber(surface) : -1; + if (defer) { + if (frameNumber == -1) { + defer = false; + } else { + mLauncher.getDragLayer().invalidate(); + } + } + + TransactionCompat transaction = new TransactionCompat(); + for (RemoteAnimationTargetCompat app : mTargetSet.apps) { + if (!(app.isNotInRecents + || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME)) { + transaction.setAlpha(app.leash, alpha); + if (defer) { + transaction.deferTransactionUntil(app.leash, surface, frameNumber); + } + } + } + transaction.setEarlyWakeup(); + transaction.apply(); + } + + private void onSwipeAnimationComplete(boolean toAllApps, boolean isFling, Runnable callback) { + mLauncher.getStateManager().goToState(toAllApps ? ALL_APPS : OVERVIEW, false); + if (!toAllApps) { + DiscoveryBounce.showForOverviewIfNeeded(mLauncher); + mLauncher.getOverviewPanel().setSwipeDownShouldLaunchApp(true); + } + + mLauncher.getUserEventDispatcher().logStateChangeAction( + isFling ? Touch.FLING : Touch.SWIPE, Direction.UP, + ContainerType.NAVBAR, ContainerType.APP, + toAllApps ? ContainerType.ALLAPPS : ContainerType.TASKSWITCHER, + 0); + + callback.run(); + } +} diff --git a/quickstep/src/com/android/quickstep/MotionEventQueue.java b/quickstep/src/com/android/quickstep/MotionEventQueue.java index 538e23c3af..15f5aa5247 100644 --- a/quickstep/src/com/android/quickstep/MotionEventQueue.java +++ b/quickstep/src/com/android/quickstep/MotionEventQueue.java @@ -163,7 +163,7 @@ public class MotionEventQueue { mConsumer.updateTouchTracking(INTERACTION_QUICK_SCRUB); break; case ACTION_QUICK_STEP: - mConsumer.onQuickStep(event.getX(), event.getY(), event.getEventTime()); + mConsumer.onQuickStep(event); break; default: Log.e(TAG, "Invalid virtual event: " + event.getAction()); diff --git a/quickstep/src/com/android/quickstep/MultiStateCallback.java b/quickstep/src/com/android/quickstep/MultiStateCallback.java index 7a741764f0..bda3d06aac 100644 --- a/quickstep/src/com/android/quickstep/MultiStateCallback.java +++ b/quickstep/src/com/android/quickstep/MultiStateCallback.java @@ -59,4 +59,8 @@ public class MultiStateCallback { public int getState() { return mState; } + + public boolean hasStates(int stateMask) { + return (mState & stateMask) == stateMask; + } } diff --git a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java index 4d695de907..23738fb257 100644 --- a/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java +++ b/quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java @@ -21,9 +21,10 @@ import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.INVALID_POINTER_ID; -import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK; -import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW; -import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_STEP_DRAG_SLOP_PX; + +import static com.android.systemui.shared.system.ActivityManagerWrapper + .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import android.annotation.TargetApi; import android.app.ActivityManager.RunningTaskInfo; @@ -46,16 +47,17 @@ import android.view.WindowManager; import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.util.TraceHelper; +import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.AssistDataReceiver; import com.android.systemui.shared.system.BackgroundExecutor; +import com.android.systemui.shared.system.NavigationBarCompat; import com.android.systemui.shared.system.NavigationBarCompat.HitTarget; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RecentsAnimationListener; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.WindowManagerWrapper; -import java.util.Arrays; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -66,8 +68,6 @@ import java.util.concurrent.TimeUnit; public class OtherActivityTouchConsumer extends ContextWrapper implements TouchConsumer { private static final long LAUNCHER_DRAW_TIMEOUT_MS = 150; - private static final int[] DEFERRED_HIT_TARGETS = false - ? new int[] {HIT_TARGET_BACK, HIT_TARGET_OVERVIEW} : new int[] {HIT_TARGET_BACK}; private final RunningTaskInfo mRunningTask; private final RecentsModel mRecentsModel; @@ -75,12 +75,15 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC private final ActivityControlHelper mActivityControlHelper; private final MainThreadExecutor mMainThreadExecutor; private final Choreographer mBackgroundThreadChoreographer; + private final OverviewCallbacks mOverviewCallbacks; private final boolean mIsDeferredDownTarget; private final PointF mDownPos = new PointF(); private final PointF mLastPos = new PointF(); private int mActivePointerId = INVALID_POINTER_ID; private boolean mPassedInitialSlop; + // Used for non-deferred gestures to determine when to start dragging + private int mQuickStepDragSlop; private float mStartDisplacement; private WindowTransformSwipeHandler mInteractionHandler; private int mDisplayRotation; @@ -93,8 +96,10 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC public OtherActivityTouchConsumer(Context base, RunningTaskInfo runningTaskInfo, RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl, MainThreadExecutor mainThreadExecutor, Choreographer backgroundThreadChoreographer, - @HitTarget int downHitTarget, VelocityTracker velocityTracker) { + @HitTarget int downHitTarget, OverviewCallbacks overviewCallbacks, + VelocityTracker velocityTracker) { super(base); + mRunningTask = runningTaskInfo; mRecentsModel = recentsModel; mHomeIntent = homeIntent; @@ -102,7 +107,8 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mActivityControlHelper = activityControl; mMainThreadExecutor = mainThreadExecutor; mBackgroundThreadChoreographer = backgroundThreadChoreographer; - mIsDeferredDownTarget = Arrays.binarySearch(DEFERRED_HIT_TARGETS, downHitTarget) >= 0; + mIsDeferredDownTarget = activityControl.deferStartingActivity(downHitTarget); + mOverviewCallbacks = overviewCallbacks; } @Override @@ -122,6 +128,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mDownPos.set(ev.getX(), ev.getY()); mLastPos.set(mDownPos); mPassedInitialSlop = false; + mQuickStepDragSlop = NavigationBarCompat.getQuickStepDragSlopPx(); // Start the window animation on down to give more time for launcher to draw if the // user didn't start the gesture over the back button @@ -154,14 +161,14 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC } mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex)); float displacement = getDisplacement(ev); - if (!mPassedInitialSlop && Math.abs(displacement) > QUICK_STEP_DRAG_SLOP_PX) { - mPassedInitialSlop = true; - mStartDisplacement = displacement; - - // If we deferred starting the window animation on touch down, then - // start tracking now - if (mIsDeferredDownTarget) { - startTouchTrackingForWindowAnimation(ev.getEventTime()); + if (!mPassedInitialSlop) { + if (!mIsDeferredDownTarget) { + // Normal gesture, ensure we pass the drag slop before we start tracking + // the gesture + if (Math.abs(displacement) > mQuickStepDragSlop) { + mPassedInitialSlop = true; + mStartDisplacement = displacement; + } } } @@ -186,6 +193,11 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC if (mInteractionHandler == null) { return; } + + mOverviewCallbacks.closeAllWindows(); + ActivityManagerWrapper.getInstance().closeSystemWindows( + CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); + // Notify the handler that the gesture has actually started mInteractionHandler.onGestureStarted(); } @@ -218,7 +230,8 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC handler.initWhenReady(); TraceHelper.beginSection("RecentsController"); - Runnable startActivity = () -> mActivityControlHelper.startRecentsFromSwipe(mHomeIntent, + Runnable startActivity = () -> ActivityManagerWrapper.getInstance().startRecentsActivity( + mHomeIntent, new AssistDataReceiver() { @Override public void onHandleAssistData(Bundle bundle) { @@ -232,8 +245,9 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC Rect minimizedHomeBounds) { if (mInteractionHandler == handler) { TraceHelper.partitionSection("RecentsController", "Received"); - handler.onRecentsAnimationStart(controller, apps, homeContentInsets, - minimizedHomeBounds); + handler.onRecentsAnimationStart(controller, + new RemoteAnimationTargetSet(apps, MODE_CLOSING), + homeContentInsets, minimizedHomeBounds); } else { TraceHelper.endSection("RecentsController", "Finishing no handler"); controller.finish(false /* toHome */); @@ -247,7 +261,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC handler.onRecentsAnimationCanceled(); } } - }); + }, null, null); if (Looper.myLooper() != Looper.getMainLooper()) { startActivity.run(); @@ -305,6 +319,13 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC @Override public void updateTouchTracking(int interactionType) { + if (!mPassedInitialSlop && mIsDeferredDownTarget && mInteractionHandler == null) { + // If we deferred starting the window animation on touch down, then + // start tracking now + startTouchTrackingForWindowAnimation(SystemClock.uptimeMillis()); + mPassedInitialSlop = true; + } + notifyGestureStarted(); if (mInteractionHandler != null) { mInteractionHandler.updateInteractionType(interactionType); @@ -332,7 +353,14 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC } @Override - public void onQuickStep(float eventX, float eventY, long eventTime) { + public void onQuickStep(MotionEvent ev) { + if (mIsDeferredDownTarget) { + // Deferred gesture, start the animation and gesture tracking once we pass the actual + // touch slop + startTouchTrackingForWindowAnimation(ev.getEventTime()); + mPassedInitialSlop = true; + mStartDisplacement = getDisplacement(ev); + } notifyGestureStarted(); } diff --git a/quickstep/src/com/android/quickstep/OverviewCallbacks.java b/quickstep/src/com/android/quickstep/OverviewCallbacks.java new file mode 100644 index 0000000000..ac4a40b983 --- /dev/null +++ b/quickstep/src/com/android/quickstep/OverviewCallbacks.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep; + +import android.content.Context; + +import com.android.launcher3.R; +import com.android.launcher3.Utilities; +import com.android.launcher3.util.Preconditions; + +/** + * Callbacks related to overview/quicksteps. + */ +public class OverviewCallbacks { + + private static OverviewCallbacks sInstance; + + public static OverviewCallbacks get(Context context) { + Preconditions.assertUIThread(); + if (sInstance == null) { + sInstance = Utilities.getOverrideObject(OverviewCallbacks.class, + context.getApplicationContext(), R.string.overview_callbacks_class); + } + return sInstance; + } + + public void onInitOverviewTransition() { } + + public void onResetOverview() { } + + public void closeAllWindows() { } +} diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java index d76c49a09f..7b29323835 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java @@ -15,18 +15,32 @@ */ package com.android.quickstep; -import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; -import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; +import static android.content.Intent.ACTION_PACKAGE_ADDED; +import static android.content.Intent.ACTION_PACKAGE_CHANGED; +import static android.content.Intent.ACTION_PACKAGE_REMOVED; +import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; +import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR; +import static com.android.systemui.shared.system.ActivityManagerWrapper + .CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; +import static com.android.systemui.shared.system.PackageManagerWrapper + .ACTION_PREFERRED_ACTIVITY_CHANGED; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; + +import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.annotation.TargetApi; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ResolveInfo; import android.graphics.Rect; import android.os.Build; +import android.os.PatternMatcher; import android.os.SystemClock; import android.util.Log; import android.view.View; @@ -34,17 +48,26 @@ import android.view.ViewConfiguration; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.MainThreadExecutor; -import com.android.launcher3.anim.AnimatorPlaybackController; +import com.android.launcher3.anim.AnimationSuccessListener; +import com.android.launcher3.logging.UserEventDispatcher; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action; +import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.quickstep.ActivityControlHelper.ActivityInitListener; +import com.android.quickstep.ActivityControlHelper.AnimationFactory; import com.android.quickstep.ActivityControlHelper.FallbackActivityControllerHelper; import com.android.quickstep.ActivityControlHelper.LauncherActivityControllerHelper; import com.android.quickstep.util.ClipAnimationHelper; -import com.android.quickstep.util.RemoteAnimationProvider; -import com.android.quickstep.util.SysuiEventLogger; +import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.LatencyTrackerCompat; +import com.android.systemui.shared.system.PackageManagerWrapper; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.TransactionCompat; + +import java.util.ArrayList; /** * Helper class to handle various atomic commands for switching between Overview. @@ -52,18 +75,33 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat; @TargetApi(Build.VERSION_CODES.P) public class OverviewCommandHelper { - private static final long RECENTS_LAUNCH_DURATION = 200; + private static final long RECENTS_LAUNCH_DURATION = 250; private static final String TAG = "OverviewCommandHelper"; - private static final boolean DEBUG_START_FALLBACK_ACTIVITY = false; private final Context mContext; private final ActivityManagerWrapper mAM; private final RecentsModel mRecentsModel; private final MainThreadExecutor mMainThreadExecutor; + private final ComponentName mMyHomeComponent; - public final Intent homeIntent; - public final ComponentName launcher; + private final BroadcastReceiver mUserPreferenceChangeReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + initOverviewTargets(); + } + }; + private final BroadcastReceiver mOtherHomeAppUpdateReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + initOverviewTargets(); + } + }; + private String mUpdateRegisteredPackage; + + public Intent overviewIntent; + public ComponentName overviewComponent; + private ActivityControlHelper mActivityControlHelper; private long mLastToggleTime; @@ -73,22 +111,72 @@ public class OverviewCommandHelper { mMainThreadExecutor = new MainThreadExecutor(); mRecentsModel = RecentsModel.getInstance(mContext); - homeIntent = new Intent(Intent.ACTION_MAIN) + Intent myHomeIntent = new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_HOME) - .setPackage(context.getPackageName()) - .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - ResolveInfo info = context.getPackageManager().resolveActivity(homeIntent, 0); + .setPackage(mContext.getPackageName()); + ResolveInfo info = context.getPackageManager().resolveActivity(myHomeIntent, 0); + mMyHomeComponent = new ComponentName(context.getPackageName(), info.activityInfo.name); - if (DEBUG_START_FALLBACK_ACTIVITY) { - launcher = new ComponentName(context, RecentsActivity.class); - homeIntent.addCategory(Intent.CATEGORY_DEFAULT) - .removeCategory(Intent.CATEGORY_HOME); + mContext.registerReceiver(mUserPreferenceChangeReceiver, + new IntentFilter(ACTION_PREFERRED_ACTIVITY_CHANGED)); + initOverviewTargets(); + } + + private void initOverviewTargets() { + ComponentName defaultHome = PackageManagerWrapper.getInstance() + .getHomeActivities(new ArrayList<>()); + + final String overviewIntentCategory; + if (defaultHome == null || mMyHomeComponent.equals(defaultHome)) { + // User default home is same as out home app. Use Overview integrated in Launcher. + overviewComponent = mMyHomeComponent; + mActivityControlHelper = new LauncherActivityControllerHelper(); + overviewIntentCategory = Intent.CATEGORY_HOME; + + if (mUpdateRegisteredPackage != null) { + // Remove any update listener as we don't care about other packages. + mContext.unregisterReceiver(mOtherHomeAppUpdateReceiver); + mUpdateRegisteredPackage = null; + } } else { - launcher = new ComponentName(context.getPackageName(), info.activityInfo.name); + // The default home app is a different launcher. Use the fallback Overview instead. + overviewComponent = new ComponentName(mContext, RecentsActivity.class); + mActivityControlHelper = new FallbackActivityControllerHelper(defaultHome); + overviewIntentCategory = Intent.CATEGORY_DEFAULT; + + // User's default home app can change as a result of package updates of this app (such + // as uninstalling the app or removing the "Launcher" feature in an update). + // Listen for package updates of this app (and remove any previously attached + // package listener). + if (!defaultHome.getPackageName().equals(mUpdateRegisteredPackage)) { + if (mUpdateRegisteredPackage != null) { + mContext.unregisterReceiver(mOtherHomeAppUpdateReceiver); + } + + mUpdateRegisteredPackage = defaultHome.getPackageName(); + IntentFilter updateReceiver = new IntentFilter(ACTION_PACKAGE_ADDED); + updateReceiver.addAction(ACTION_PACKAGE_CHANGED); + updateReceiver.addAction(ACTION_PACKAGE_REMOVED); + updateReceiver.addDataScheme("package"); + updateReceiver.addDataSchemeSpecificPart(mUpdateRegisteredPackage, + PatternMatcher.PATTERN_LITERAL); + mContext.registerReceiver(mOtherHomeAppUpdateReceiver, updateReceiver); + } } - // Clear the packageName as system can fail to dedupe it b/64108432 - homeIntent.setComponent(launcher).setPackage(null); + overviewIntent = new Intent(Intent.ACTION_MAIN) + .addCategory(overviewIntentCategory) + .setComponent(overviewComponent) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } + + public void onDestroy() { + mContext.unregisterReceiver(mUserPreferenceChangeReceiver); + + if (mUpdateRegisteredPackage != null) { + mContext.unregisterReceiver(mOtherHomeAppUpdateReceiver); + mUpdateRegisteredPackage = null; + } } public void onOverviewToggle() { @@ -97,7 +185,7 @@ public class OverviewCommandHelper { return; } - mAM.closeSystemWindows("recentapps"); + mAM.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); mMainThreadExecutor.execute(new RecentsActivityCommand<>()); } @@ -105,25 +193,26 @@ public class OverviewCommandHelper { mMainThreadExecutor.execute(new ShowRecentsCommand()); } + public void onTip(int actionType, int viewType) { + mMainThreadExecutor.execute(new Runnable() { + @Override + public void run() { + UserEventDispatcher.newInstance(mContext, + new InvariantDeviceProfile(mContext).getDeviceProfile(mContext)) + .logActionTip(actionType, viewType); + } + }); + } + public ActivityControlHelper getActivityControlHelper() { - if (DEBUG_START_FALLBACK_ACTIVITY) { - return new FallbackActivityControllerHelper(); - } else { - return new LauncherActivityControllerHelper(); - } + return mActivityControlHelper; } private class ShowRecentsCommand extends RecentsActivityCommand { @Override protected boolean handleCommand(long elapsedTime) { - RecentsView recents = mHelper.getVisibleRecentsView(); - if (recents != null) { - recents.snapToTaskAfterNext(); - return true; - } else { - return false; - } + return mHelper.getVisibleRecentsView() != null; } } @@ -135,6 +224,9 @@ public class OverviewCommandHelper { private ActivityInitListener mListener; private T mActivity; + private RecentsView mRecentsView; + private final long mToggleClickedTime = SystemClock.uptimeMillis(); + private boolean mUserEventLogged; public RecentsActivityCommand() { mHelper = getActivityControlHelper(); @@ -152,12 +244,9 @@ public class OverviewCommandHelper { if (!handleCommand(elapsedTime)) { // Start overview - if (mHelper.switchToRecentsIfVisible()) { - SysuiEventLogger.writeDummyRecentsTransition(0); - // Do nothing - } else { + if (!mHelper.switchToRecentsIfVisible(true)) { mListener = mHelper.createActivityInitListener(this::onActivityReady); - mListener.registerAndStartActivity(homeIntent, this::createWindowAnimation, + mListener.registerAndStartActivity(overviewIntent, this::createWindowAnimation, mContext, mMainThreadExecutor.getHandler(), RECENTS_LAUNCH_DURATION); } } @@ -183,41 +272,60 @@ public class OverviewCommandHelper { private boolean onActivityReady(T activity, Boolean wasVisible) { activity.getOverviewPanel().setCurrentTask(mRunningTaskId); AbstractFloatingView.closeAllOpenViews(activity, wasVisible); - mHelper.prepareRecentsUI(activity, wasVisible); + AnimationFactory factory = mHelper.prepareRecentsUI(activity, wasVisible, + (controller) -> { + controller.dispatchOnStart(); + ValueAnimator anim = controller.getAnimationPlayer() + .setDuration(RECENTS_LAUNCH_DURATION); + anim.setInterpolator(FAST_OUT_SLOW_IN); + anim.start(); + }); + factory.onRemoteAnimationReceived(null); if (wasVisible) { - AnimatorPlaybackController controller = - mHelper.createControllerForVisibleActivity(activity); - controller.dispatchOnStart(); - ValueAnimator anim = - controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION); - anim.setInterpolator(FAST_OUT_SLOW_IN); - anim.start(); + factory.createActivityController(RECENTS_LAUNCH_DURATION); } mActivity = activity; + mRecentsView = mActivity.getOverviewPanel(); + mRecentsView.setRunningTaskIconScaledDown(true /* isScaledDown */, false /* animate */); + if (!mUserEventLogged) { + activity.getUserEventDispatcher().logActionCommand(Action.Command.RECENTS_BUTTON, + mHelper.getContainerType(), ContainerType.TASKSWITCHER); + mUserEventLogged = true; + } return false; } private AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targetCompats) { + if (LatencyTrackerCompat.isEnabled(mContext)) { + LatencyTrackerCompat.logToggleRecents( + (int) (SystemClock.uptimeMillis() - mToggleClickedTime)); + } + if (mListener != null) { mListener.unregister(); } - RemoteAnimationProvider.showOpeningTarget(targetCompats); AnimatorSet anim = new AnimatorSet(); + anim.addListener(new AnimationSuccessListener() { + @Override + public void onAnimationSuccess(Animator animator) { + if (mRecentsView != null) { + mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, + true /* animate */); + } + } + }); if (mActivity == null) { Log.e(TAG, "Animation created, before activity"); anim.play(ValueAnimator.ofInt(0, 1).setDuration(100)); return anim; } - RemoteAnimationTargetCompat closingTarget = null; + RemoteAnimationTargetSet targetSet = + new RemoteAnimationTargetSet(targetCompats, MODE_CLOSING); + // Use the top closing app to determine the insets for the animation - for (RemoteAnimationTargetCompat target : targetCompats) { - if (target.mode == MODE_CLOSING) { - closingTarget = target; - break; - } - } - if (closingTarget == null) { + RemoteAnimationTargetCompat runningTaskTarget = targetSet.findTask(mRunningTaskId); + if (runningTaskTarget == null) { Log.e(TAG, "No closing app"); anim.play(ValueAnimator.ofInt(0, 1).setDuration(100)); return anim; @@ -232,19 +340,33 @@ public class OverviewCommandHelper { rootView.getLocationOnScreen(loc); Rect homeBounds = new Rect(loc[0], loc[1], loc[0] + rootView.getWidth(), loc[1] + rootView.getHeight()); - clipHelper.updateSource(homeBounds, closingTarget); + clipHelper.updateSource(homeBounds, runningTaskTarget); Rect targetRect = new Rect(); mHelper.getSwipeUpDestinationAndLength( mActivity.getDeviceProfile(), mActivity, targetRect); clipHelper.updateTargetRect(targetRect); - + clipHelper.prepareAnimation(false /* isOpening */); ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1); - valueAnimator.setDuration(RECENTS_LAUNCH_DURATION).setInterpolator(FAST_OUT_SLOW_IN); - valueAnimator.addUpdateListener((v) -> { - clipHelper.applyTransform(targetCompats, (float) v.getAnimatedValue()); - }); + valueAnimator.setDuration(RECENTS_LAUNCH_DURATION); + valueAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); + valueAnimator.addUpdateListener((v) -> + clipHelper.applyTransform(targetSet, (float) v.getAnimatedValue())); + + if (targetSet.isAnimatingHome()) { + // If we are animating home, fade in the opening targets + RemoteAnimationTargetSet openingSet = + new RemoteAnimationTargetSet(targetCompats, MODE_OPENING); + + TransactionCompat transaction = new TransactionCompat(); + valueAnimator.addUpdateListener((v) -> { + for (RemoteAnimationTargetCompat app : openingSet.apps) { + transaction.setAlpha(app.leash, (float) v.getAnimatedValue()); + } + transaction.apply(); + }); + } anim.play(valueAnimator); return anim; } diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java index 22b175779d..d60574676e 100644 --- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java +++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java @@ -15,23 +15,26 @@ */ package com.android.quickstep; -import static com.android.launcher3.Utilities.getPrefs; import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB; import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP; -import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON; import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON; +import static com.android.systemui.shared.system.SettingsCompat.SWIPE_UP_SETTING_NAME; +import android.content.ContentResolver; import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.content.res.Resources; +import android.database.ContentObserver; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.os.RemoteException; +import android.provider.Settings; import android.support.annotation.WorkerThread; import android.util.Log; import com.android.launcher3.MainThreadExecutor; +import com.android.launcher3.Utilities; +import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.util.UiThreadHelper; import com.android.systemui.shared.recents.ISystemUiProxy; @@ -42,15 +45,20 @@ import java.util.concurrent.ExecutionException; * * - FLAG_DISABLE_QUICK_SCRUB * - FLAG_DISABLE_SWIPE_UP - * - FLAG_HIDE_BACK_BUTTON * - FLAG_SHOW_OVERVIEW_BUTTON * * @see com.android.systemui.shared.system.NavigationBarCompat.InteractionType and associated flags. */ -public class OverviewInteractionState implements OnSharedPreferenceChangeListener { +public class OverviewInteractionState { private static final String TAG = "OverviewFlags"; + private static final String HAS_ENABLED_QUICKSTEP_ONCE = "launcher.has_enabled_quickstep_once"; + private static final String SWIPE_UP_SETTING_AVAILABLE_RES_NAME = + "config_swipe_up_gesture_setting_available"; + private static final String SWIPE_UP_ENABLED_DEFAULT_RES_NAME = + "config_swipe_up_gesture_default"; + // We do not need any synchronization for this variable as its only written on UI thread. private static OverviewInteractionState INSTANCE; @@ -70,42 +78,48 @@ public class OverviewInteractionState implements OnSharedPreferenceChangeListene return INSTANCE; } - public static final String KEY_SWIPE_UP_ENABLED = "pref_enable_quickstep"; - private static final int MSG_SET_PROXY = 200; - private static final int MSG_SET_BACK_BUTTON_VISIBLE = 201; + private static final int MSG_SET_BACK_BUTTON_ALPHA = 201; private static final int MSG_SET_SWIPE_UP_ENABLED = 202; + private final SwipeUpGestureEnabledSettingObserver mSwipeUpSettingObserver; + + private final Context mContext; private final Handler mUiHandler; private final Handler mBgHandler; // These are updated on the background thread private ISystemUiProxy mISystemUiProxy; - private boolean mBackButtonVisible = true; private boolean mSwipeUpEnabled = true; + private Runnable mOnSwipeUpSettingChangedListener; + private OverviewInteractionState(Context context) { + mContext = context; + + // Data posted to the uihandler will be sent to the bghandler. Data is sent to uihandler + // because of its high send frequency and data may be very different than the previous value + // For example, send back alpha on uihandler to avoid flickering when setting its visibility mUiHandler = new Handler(this::handleUiMessage); mBgHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleBgMessage); - SharedPreferences prefs = getPrefs(context); - prefs.registerOnSharedPreferenceChangeListener(this); - onSharedPreferenceChanged(prefs, KEY_SWIPE_UP_ENABLED); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences prefs, String s) { - if (KEY_SWIPE_UP_ENABLED.equals(s)) { - mUiHandler.removeMessages(MSG_SET_SWIPE_UP_ENABLED); - boolean swipeUpEnabled = prefs.getBoolean(s, true); - mUiHandler.obtainMessage(MSG_SET_SWIPE_UP_ENABLED, - swipeUpEnabled ? 1 : 0, 0).sendToTarget(); + if (getSystemBooleanRes(SWIPE_UP_SETTING_AVAILABLE_RES_NAME)) { + mSwipeUpSettingObserver = new SwipeUpGestureEnabledSettingObserver(mUiHandler, + context.getContentResolver()); + mSwipeUpSettingObserver.register(); + } else { + mSwipeUpSettingObserver = null; + mSwipeUpEnabled = getSystemBooleanRes(SWIPE_UP_ENABLED_DEFAULT_RES_NAME); } } - public void setBackButtonVisible(boolean visible) { - mUiHandler.removeMessages(MSG_SET_BACK_BUTTON_VISIBLE); - mUiHandler.obtainMessage(MSG_SET_BACK_BUTTON_VISIBLE, visible ? 1 : 0, 0) + public boolean isSwipeUpGestureEnabled() { + return mSwipeUpEnabled; + } + + public void setBackButtonAlpha(float alpha, boolean animate) { + mUiHandler.removeMessages(MSG_SET_BACK_BUTTON_ALPHA); + mUiHandler.obtainMessage(MSG_SET_BACK_BUTTON_ALPHA, animate ? 1 : 0, 0, alpha) .sendToTarget(); } @@ -114,7 +128,7 @@ public class OverviewInteractionState implements OnSharedPreferenceChangeListene } private boolean handleUiMessage(Message msg) { - mBgHandler.obtainMessage(msg.what, msg.arg1, msg.arg2).sendToTarget(); + mBgHandler.obtainMessage(msg.what, msg.arg1, msg.arg2, msg.obj).sendToTarget(); return true; } @@ -123,27 +137,34 @@ public class OverviewInteractionState implements OnSharedPreferenceChangeListene case MSG_SET_PROXY: mISystemUiProxy = (ISystemUiProxy) msg.obj; break; - case MSG_SET_BACK_BUTTON_VISIBLE: - mBackButtonVisible = msg.arg1 != 0; - break; + case MSG_SET_BACK_BUTTON_ALPHA: + applyBackButtonAlpha((float) msg.obj, msg.arg1 == 1); + return true; case MSG_SET_SWIPE_UP_ENABLED: mSwipeUpEnabled = msg.arg1 != 0; + resetHomeBounceSeenOnQuickstepEnabledFirstTime(); + + if (mOnSwipeUpSettingChangedListener != null) { + mOnSwipeUpSettingChangedListener.run(); + } break; } applyFlags(); return true; } + public void setOnSwipeUpSettingChangedListener(Runnable listener) { + mOnSwipeUpSettingChangedListener = listener; + } + @WorkerThread private void applyFlags() { if (mISystemUiProxy == null) { return; } - int flags; - if (mSwipeUpEnabled) { - flags = mBackButtonVisible ? 0 : FLAG_HIDE_BACK_BUTTON; - } else { + int flags = 0; + if (!mSwipeUpEnabled) { flags = FLAG_DISABLE_SWIPE_UP | FLAG_DISABLE_QUICK_SCRUB | FLAG_SHOW_OVERVIEW_BUTTON; } try { @@ -152,4 +173,69 @@ public class OverviewInteractionState implements OnSharedPreferenceChangeListene Log.w(TAG, "Unable to update overview interaction flags", e); } } + + @WorkerThread + private void applyBackButtonAlpha(float alpha, boolean animate) { + if (mISystemUiProxy == null) { + return; + } + try { + mISystemUiProxy.setBackButtonAlpha(alpha, animate); + } catch (RemoteException e) { + Log.w(TAG, "Unable to update overview back button alpha", e); + } + } + + private class SwipeUpGestureEnabledSettingObserver extends ContentObserver { + private Handler mHandler; + private ContentResolver mResolver; + private final int defaultValue; + + SwipeUpGestureEnabledSettingObserver(Handler handler, ContentResolver resolver) { + super(handler); + mHandler = handler; + mResolver = resolver; + defaultValue = getSystemBooleanRes(SWIPE_UP_ENABLED_DEFAULT_RES_NAME) ? 1 : 0; + } + + public void register() { + mResolver.registerContentObserver(Settings.Secure.getUriFor(SWIPE_UP_SETTING_NAME), + false, this); + mSwipeUpEnabled = getValue(); + resetHomeBounceSeenOnQuickstepEnabledFirstTime(); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + mHandler.removeMessages(MSG_SET_SWIPE_UP_ENABLED); + mHandler.obtainMessage(MSG_SET_SWIPE_UP_ENABLED, getValue() ? 1 : 0, 0).sendToTarget(); + } + + private boolean getValue() { + return Settings.Secure.getInt(mResolver, SWIPE_UP_SETTING_NAME, defaultValue) == 1; + } + } + + private boolean getSystemBooleanRes(String resName) { + Resources res = Resources.getSystem(); + int resId = res.getIdentifier(resName, "bool", "android"); + + if (resId != 0) { + return res.getBoolean(resId); + } else { + Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?"); + return false; + } + } + + private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() { + if (mSwipeUpEnabled && !Utilities.getPrefs(mContext).getBoolean( + HAS_ENABLED_QUICKSTEP_ONCE, true)) { + Utilities.getPrefs(mContext).edit() + .putBoolean(HAS_ENABLED_QUICKSTEP_ONCE, true) + .putBoolean(DiscoveryBounce.HOME_BOUNCE_SEEN, false) + .apply(); + } + } } diff --git a/quickstep/src/com/android/quickstep/QuickScrubController.java b/quickstep/src/com/android/quickstep/QuickScrubController.java index fd089b5927..abb479dea7 100644 --- a/quickstep/src/com/android/quickstep/QuickScrubController.java +++ b/quickstep/src/com/android/quickstep/QuickScrubController.java @@ -16,15 +16,18 @@ package com.android.quickstep; +import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; + +import android.util.Log; import android.view.HapticFeedbackConstants; +import android.view.animation.Interpolator; import com.android.launcher3.Alarm; import com.android.launcher3.BaseActivity; import com.android.launcher3.OnAlarmListener; import com.android.launcher3.Utilities; +import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; -import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; @@ -36,15 +39,20 @@ import com.android.quickstep.views.TaskView; */ public class QuickScrubController implements OnAlarmListener { - public static final int QUICK_SCRUB_START_DURATION = 210; + public static final int QUICK_SCRUB_FROM_APP_START_DURATION = 240; + public static final int QUICK_SCRUB_FROM_HOME_START_DURATION = 150; + // We want the translation y to finish faster than the rest of the animation. + public static final float QUICK_SCRUB_TRANSLATION_Y_FACTOR = 5f / 6; + public static final Interpolator QUICK_SCRUB_START_INTERPOLATOR = FAST_OUT_SLOW_IN; /** * Snap to a new page when crossing these thresholds. The first and last auto-advance. */ private static final float[] QUICK_SCRUB_THRESHOLDS = new float[] { - 0.05f, 0.35f, 0.65f, 0.95f + 0.04f, 0.27f, 0.50f, 0.73f, 0.96f }; + private static final String TAG = "QuickScrubController"; private static final boolean ENABLE_AUTO_ADVANCE = true; private static final long AUTO_ADVANCE_DELAY = 500; private static final int QUICKSCRUB_SNAP_DURATION_PER_PAGE = 325; @@ -55,9 +63,12 @@ public class QuickScrubController implements OnAlarmListener { private final BaseActivity mActivity; private boolean mInQuickScrub; + private boolean mWaitingForTaskLaunch; private int mQuickScrubSection; private boolean mStartedFromHome; private boolean mFinishedTransitionToQuickScrub; + private Runnable mOnFinishedTransitionToQuickScrubRunnable; + private ActivityControlHelper mActivityControlHelper; public QuickScrubController(BaseActivity activity, RecentsView recentsView) { mActivity = activity; @@ -68,11 +79,13 @@ public class QuickScrubController implements OnAlarmListener { } } - public void onQuickScrubStart(boolean startingFromHome) { + public void onQuickScrubStart(boolean startingFromHome, ActivityControlHelper controlHelper) { + prepareQuickScrub(TAG); mInQuickScrub = true; mStartedFromHome = startingFromHome; mQuickScrubSection = 0; mFinishedTransitionToQuickScrub = false; + mActivityControlHelper = controlHelper; snapToNextTaskIfAvailable(); mActivity.getUserEventDispatcher().resetActionDurationMillis(); @@ -85,26 +98,61 @@ public class QuickScrubController implements OnAlarmListener { } int page = mRecentsView.getNextPage(); Runnable launchTaskRunnable = () -> { - TaskView taskView = ((TaskView) mRecentsView.getPageAt(page)); + TaskView taskView = mRecentsView.getPageAt(page); if (taskView != null) { - taskView.launchTask(true); + mWaitingForTaskLaunch = true; + taskView.launchTask(true, (result) -> { + if (!result) { + taskView.notifyTaskLaunchFailed(TAG); + breakOutOfQuickScrub(); + } else { + mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(Touch.DRAGDROP, + LauncherLogProto.Action.Direction.NONE, page, + TaskUtils.getComponentKeyForTask(taskView.getTask().key)); + } + mWaitingForTaskLaunch = false; + }, taskView.getHandler()); } else { - // Break out of quick scrub so user can interact with launcher. - mActivity.onBackPressed(); + breakOutOfQuickScrub(); } + mActivityControlHelper = null; }; int snapDuration = Math.abs(page - mRecentsView.getPageNearestToCenterOfScreen()) * QUICKSCRUB_END_SNAP_DURATION_PER_PAGE; - if (mRecentsView.snapToPage(page, snapDuration)) { + if (mRecentsView.getChildCount() > 0 && mRecentsView.snapToPage(page, snapDuration)) { // Settle on the page then launch it mRecentsView.setNextPageSwitchRunnable(launchTaskRunnable); } else { // No page move needed, just launch it - launchTaskRunnable.run(); + if (mFinishedTransitionToQuickScrub) { + launchTaskRunnable.run(); + } else { + mOnFinishedTransitionToQuickScrubRunnable = launchTaskRunnable; + } + } + } + + /** + * Initializes the UI for quick scrub, returns true if success. + */ + public boolean prepareQuickScrub(String tag) { + if (mWaitingForTaskLaunch || mInQuickScrub) { + Log.d(tag, "Waiting for last scrub to finish, will skip this interaction"); + return false; + } + mOnFinishedTransitionToQuickScrubRunnable = null; + mRecentsView.setNextPageSwitchRunnable(null); + return true; + } + + /** + * Attempts to go to normal overview or back to home, so UI doesn't prevent user interaction. + */ + private void breakOutOfQuickScrub() { + if (mRecentsView.getChildCount() == 0 || mActivityControlHelper == null + || !mActivityControlHelper.switchToRecentsIfVisible(false)) { + mActivity.onBackPressed(); } - mActivity.getUserEventDispatcher().logActionOnControl(Touch.DRAGDROP, - ControlType.QUICK_SCRUB_BUTTON, null, mStartedFromHome ? - ContainerType.WORKSPACE : ContainerType.APP); } public void onQuickScrubProgress(float progress) { @@ -135,20 +183,39 @@ public class QuickScrubController implements OnAlarmListener { public void onFinishedTransitionToQuickScrub() { mFinishedTransitionToQuickScrub = true; + Runnable action = mOnFinishedTransitionToQuickScrubRunnable; + // Clear the runnable before executing it, to prevent potential recursion. + mOnFinishedTransitionToQuickScrubRunnable = null; + if (action != null) { + action.run(); + } } public void snapToNextTaskIfAvailable() { - if (!mStartedFromHome && mInQuickScrub && mRecentsView.getChildCount() > 0) { - mRecentsView.snapToPage(mRecentsView.getNextPage() + 1, QUICK_SCRUB_START_DURATION); + if (mInQuickScrub && mRecentsView.getChildCount() > 0) { + int duration = mStartedFromHome ? QUICK_SCRUB_FROM_HOME_START_DURATION + : QUICK_SCRUB_FROM_APP_START_DURATION; + int pageToGoTo = mStartedFromHome ? 0 : mRecentsView.getNextPage() + 1; + goToPageWithHaptic(pageToGoTo, duration, true /* forceHaptic */, + QUICK_SCRUB_START_INTERPOLATOR); } } private void goToPageWithHaptic(int pageToGoTo) { + goToPageWithHaptic(pageToGoTo, -1 /* overrideDuration */, false /* forceHaptic */, null); + } + + private void goToPageWithHaptic(int pageToGoTo, int overrideDuration, boolean forceHaptic, + Interpolator interpolator) { pageToGoTo = Utilities.boundToRange(pageToGoTo, 0, mRecentsView.getPageCount() - 1); - if (pageToGoTo != mRecentsView.getNextPage()) { - int duration = Math.abs(pageToGoTo - mRecentsView.getNextPage()) + boolean snappingToPage = pageToGoTo != mRecentsView.getNextPage(); + if (snappingToPage) { + int duration = overrideDuration > -1 ? overrideDuration + : Math.abs(pageToGoTo - mRecentsView.getNextPage()) * QUICKSCRUB_SNAP_DURATION_PER_PAGE; - mRecentsView.snapToPage(pageToGoTo, duration); + mRecentsView.snapToPage(pageToGoTo, duration, interpolator); + } + if (snappingToPage || forceHaptic) { mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } @@ -157,6 +224,12 @@ public class QuickScrubController implements OnAlarmListener { @Override public void onAlarm(Alarm alarm) { int currPage = mRecentsView.getNextPage(); + boolean recentsVisible = mActivityControlHelper != null + && mActivityControlHelper.getVisibleRecentsView() != null; + if (!recentsVisible) { + Log.w(TAG, "Failed to auto advance; recents not visible"); + return; + } if (mQuickScrubSection == QUICK_SCRUB_THRESHOLDS.length && currPage < mRecentsView.getPageCount() - 1) { goToPageWithHaptic(currPage + 1); diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java index cf60fdff65..b472d611ae 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivity.java +++ b/quickstep/src/com/android/quickstep/RecentsActivity.java @@ -15,15 +15,35 @@ */ package com.android.quickstep; +import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; +import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; + +import static com.android.launcher3.LauncherAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION; +import static com.android.launcher3.LauncherAppTransitionManagerImpl.STATUS_BAR_TRANSITION_DURATION; +import static com.android.quickstep.TaskUtils.getRecentsWindowAnimator; +import static com.android.quickstep.TaskUtils.taskIsATargetWithMode; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; import android.app.ActivityOptions; +import android.content.Intent; +import android.content.res.Configuration; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.view.View; +import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.ItemInfo; +import com.android.launcher3.LauncherAnimationRunner; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; +import com.android.launcher3.anim.Interpolators; import com.android.launcher3.badge.BadgeInfo; import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.util.SystemUiController; @@ -31,29 +51,40 @@ import com.android.launcher3.util.Themes; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.fallback.FallbackRecentsView; import com.android.quickstep.fallback.RecentsRootView; +import com.android.quickstep.util.ClipAnimationHelper; +import com.android.quickstep.views.RecentsViewContainer; +import com.android.quickstep.views.TaskView; +import com.android.systemui.shared.system.ActivityOptionsCompat; +import com.android.systemui.shared.system.RemoteAnimationAdapterCompat; +import com.android.systemui.shared.system.RemoteAnimationRunnerCompat; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; + +import java.io.FileDescriptor; +import java.io.PrintWriter; /** * A simple activity to show the recently launched tasks */ public class RecentsActivity extends BaseDraggingActivity { + private Handler mUiHandler = new Handler(Looper.getMainLooper()); private RecentsRootView mRecentsRootView; private FallbackRecentsView mFallbackRecentsView; + private RecentsViewContainer mOverviewPanelContainer; + + private Configuration mOldConfig; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // In case we are reusing IDP, create a copy so that we dont conflict with Launcher - // activity. - LauncherAppState appState = LauncherAppState.getInstanceNoCreate(); - setDeviceProfile(appState != null - ? appState.getInvariantDeviceProfile().getDeviceProfile(this).copy(this) - : new InvariantDeviceProfile(this).getDeviceProfile(this)); + mOldConfig = new Configuration(getResources().getConfiguration()); + initDeviceProfile(); setContentView(R.layout.fallback_recents_activity); mRecentsRootView = findViewById(R.id.drag_layer); mFallbackRecentsView = findViewById(R.id.overview_panel); + mOverviewPanelContainer = findViewById(R.id.overview_panel_container); mRecentsRootView.setup(); @@ -62,6 +93,64 @@ public class RecentsActivity extends BaseDraggingActivity { RecentsActivityTracker.onRecentsActivityCreate(this); } + @Override + public void onConfigurationChanged(Configuration newConfig) { + int diff = newConfig.diff(mOldConfig); + if ((diff & (CONFIG_ORIENTATION | CONFIG_SCREEN_SIZE)) != 0) { + onHandleConfigChanged(); + } + mOldConfig.setTo(newConfig); + super.onConfigurationChanged(newConfig); + } + + @Override + public void onMultiWindowModeChanged(boolean isInMultiWindowMode, Configuration newConfig) { + onHandleConfigChanged(); + super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig); + } + + public void onRootViewSizeChanged() { + if (isInMultiWindowModeCompat()) { + onHandleConfigChanged(); + } + } + + private void onHandleConfigChanged() { + mUserEventDispatcher = null; + initDeviceProfile(); + + AbstractFloatingView.closeOpenViews(this, true, + AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE); + dispatchDeviceProfileChanged(); + + mRecentsRootView.setup(); + reapplyUi(); + } + + @Override + protected void reapplyUi() { + mRecentsRootView.dispatchInsets(); + } + + private void initDeviceProfile() { + // In case we are reusing IDP, create a copy so that we dont conflict with Launcher + // activity. + LauncherAppState appState = LauncherAppState.getInstanceNoCreate(); + if (isInMultiWindowModeCompat()) { + InvariantDeviceProfile idp = appState == null + ? new InvariantDeviceProfile(this) : appState.getInvariantDeviceProfile(); + DeviceProfile dp = idp.getDeviceProfile(this); + mDeviceProfile = mRecentsRootView == null ? dp.copy(this) + : dp.getMultiWindowProfile(this, mRecentsRootView.getLastKnownSize()); + } else { + // If we are reusing the Invariant device profile, make a copy. + mDeviceProfile = appState == null + ? new InvariantDeviceProfile(this).getDeviceProfile(this) + : appState.getInvariantDeviceProfile().getDeviceProfile(this).copy(this); + } + onDeviceProfileInitiated(); + } + @Override public BaseDragLayer getDragLayer() { return mRecentsRootView; @@ -77,14 +166,62 @@ public class RecentsActivity extends BaseDraggingActivity { return (T) mFallbackRecentsView; } + public RecentsViewContainer getOverviewPanelContainer() { + return mOverviewPanelContainer; + } + @Override public BadgeInfo getBadgeInfoForItem(ItemInfo info) { return null; } @Override - public ActivityOptions getActivityLaunchOptions(View v, boolean useDefaultLaunchOptions) { - return null; + public ActivityOptions getActivityLaunchOptions(final View v, boolean useDefaultLaunchOptions) { + if (useDefaultLaunchOptions || !(v instanceof TaskView)) { + return null; + } + + final TaskView taskView = (TaskView) v; + RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mUiHandler, + true /* startAtFrontOfQueue */) { + + @Override + public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, + AnimationResult result) { + result.setAnimation(composeRecentsLaunchAnimator(taskView, targetCompats)); + } + }; + return ActivityOptionsCompat.makeRemoteAnimation(new RemoteAnimationAdapterCompat( + runner, RECENTS_LAUNCH_DURATION, + RECENTS_LAUNCH_DURATION - STATUS_BAR_TRANSITION_DURATION)); + } + + /** + * Composes the animations for a launch from the recents list if possible. + */ + private AnimatorSet composeRecentsLaunchAnimator(TaskView taskView, + RemoteAnimationTargetCompat[] targets) { + AnimatorSet target = new AnimatorSet(); + boolean activityClosing = taskIsATargetWithMode(targets, getTaskId(), MODE_CLOSING); + ClipAnimationHelper helper = new ClipAnimationHelper(); + target.play(getRecentsWindowAnimator(taskView, !activityClosing, targets, helper) + .setDuration(RECENTS_LAUNCH_DURATION)); + + // Found a visible recents task that matches the opening app, lets launch the app from there + if (activityClosing) { + Animator adjacentAnimation = mFallbackRecentsView + .createAdjacentPageAnimForTaskLaunch(taskView, helper); + adjacentAnimation.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); + adjacentAnimation.setDuration(RECENTS_LAUNCH_DURATION); + adjacentAnimation.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mFallbackRecentsView.resetTaskVisuals(); + } + }); + target.play(adjacentAnimation); + } + return target; } @Override @@ -92,8 +229,20 @@ public class RecentsActivity extends BaseDraggingActivity { @Override protected void onStart() { + // Set the alpha to 1 before calling super, as it may get set back to 0 due to + // onActivityStart callback. + mFallbackRecentsView.setContentAlpha(1); super.onStart(); UiFactory.onStart(this); + mFallbackRecentsView.resetTaskVisuals(); + } + + @Override + protected void onStop() { + super.onStop(); + + // Workaround for b/78520668, explicitly trim memory once UI is hidden + onTrimMemory(TRIM_MEMORY_UI_HIDDEN); } @Override @@ -102,9 +251,34 @@ public class RecentsActivity extends BaseDraggingActivity { UiFactory.onTrimMemory(this, level); } + @Override + protected void onNewIntent(Intent intent) { + super.onNewIntent(intent); + RecentsActivityTracker.onRecentsActivityNewIntent(this); + } + @Override protected void onDestroy() { super.onDestroy(); RecentsActivityTracker.onRecentsActivityDestroy(this); } + + @Override + public void onBackPressed() { + // TODO: Launch the task we came from + startHome(); + } + + public void startHome() { + startActivity(new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_HOME) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)); + } + + @Override + public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) { + super.dump(prefix, fd, writer, args); + writer.println(prefix + "Misc:"); + dumpMisc(writer); + } } diff --git a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java index 77f0e7a53f..fb6090e2a5 100644 --- a/quickstep/src/com/android/quickstep/RecentsActivityTracker.java +++ b/quickstep/src/com/android/quickstep/RecentsActivityTracker.java @@ -22,6 +22,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; +import com.android.launcher3.MainThreadExecutor; import com.android.quickstep.ActivityControlHelper.ActivityInitListener; import com.android.quickstep.util.RemoteAnimationProvider; @@ -34,9 +35,8 @@ import java.util.function.BiPredicate; @TargetApi(Build.VERSION_CODES.P) public class RecentsActivityTracker implements ActivityInitListener { - private static final Object LOCK = new Object(); - private static WeakReference sTracker = new WeakReference<>(null); private static WeakReference sCurrentActivity = new WeakReference<>(null); + private static final Scheduler sScheduler = new Scheduler(); private final BiPredicate mOnInitListener; @@ -46,42 +46,20 @@ public class RecentsActivityTracker implements ActivityInitListener { @Override public void register() { - synchronized (LOCK) { - sTracker = new WeakReference<>(this); - } + sScheduler.schedule(this); } @Override public void unregister() { - synchronized (LOCK) { - if (sTracker.get() == this) { - sTracker.clear(); - } - } + sScheduler.clearReference(this); } - public static void onRecentsActivityCreate(RecentsActivity activity) { - synchronized (LOCK) { - RecentsActivityTracker tracker = sTracker.get(); - if (tracker != null && tracker.mOnInitListener.test(activity, false)) { - sTracker.clear(); - } - sCurrentActivity = new WeakReference<>(activity); - } - } - - public static void onRecentsActivityDestroy(RecentsActivity activity) { - synchronized (LOCK) { - if (sCurrentActivity.get() == activity) { - sCurrentActivity.clear(); - } - } + private boolean init(RecentsActivity activity, boolean visible) { + return mOnInitListener.test(activity, visible); } public static RecentsActivity getCurrentActivity() { - synchronized (LOCK) { - return sCurrentActivity.get(); - } + return sCurrentActivity.get(); } @Override @@ -92,4 +70,62 @@ public class RecentsActivityTracker implements ActivityInitListener { Bundle options = animProvider.toActivityOptions(handler, duration).toBundle(); context.startActivity(intent, options); } + + public static void onRecentsActivityCreate(RecentsActivity activity) { + sCurrentActivity = new WeakReference<>(activity); + sScheduler.initIfPending(activity, false); + } + + + public static void onRecentsActivityNewIntent(RecentsActivity activity) { + sScheduler.initIfPending(activity, activity.isStarted()); + } + + public static void onRecentsActivityDestroy(RecentsActivity activity) { + if (sCurrentActivity.get() == activity) { + sCurrentActivity.clear(); + } + } + + + private static class Scheduler implements Runnable { + + private WeakReference mPendingTracker = new WeakReference<>(null); + private MainThreadExecutor mMainThreadExecutor; + + public synchronized void schedule(RecentsActivityTracker tracker) { + mPendingTracker = new WeakReference<>(tracker); + if (mMainThreadExecutor == null) { + mMainThreadExecutor = new MainThreadExecutor(); + } + mMainThreadExecutor.execute(this); + } + + @Override + public void run() { + RecentsActivity activity = sCurrentActivity.get(); + if (activity != null) { + initIfPending(activity, activity.isStarted()); + } + } + + public synchronized boolean initIfPending(RecentsActivity activity, boolean alreadyOnHome) { + RecentsActivityTracker tracker = mPendingTracker.get(); + if (tracker != null) { + if (!tracker.init(activity, alreadyOnHome)) { + mPendingTracker.clear(); + } + return true; + } + return false; + } + + public synchronized boolean clearReference(RecentsActivityTracker tracker) { + if (mPendingTracker.get() == tracker) { + mPendingTracker.clear(); + return true; + } + return false; + } + } } diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationInterpolator.java b/quickstep/src/com/android/quickstep/RecentsAnimationInterpolator.java deleted file mode 100644 index fdeb0c1705..0000000000 --- a/quickstep/src/com/android/quickstep/RecentsAnimationInterpolator.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.quickstep; - -import android.graphics.Rect; - -import com.android.launcher3.Utilities; - -/** - * Helper class to interpolate the animation between a task view representation and an actual - * window. - */ -public class RecentsAnimationInterpolator { - - public static class TaskWindowBounds { - public float taskScale = 1f; - public float taskX = 0f; - public float taskY = 0f; - - public float winScale = 1f; - public float winX = 0f; - public float winY = 0f; - public Rect winCrop = new Rect(); - - @Override - public String toString() { - return "taskScale=" + taskScale + " taskX=" + taskX + " taskY=" + taskY - + " winScale=" + winScale + " winX=" + winX + " winY=" + winY - + " winCrop=" + winCrop; - } - } - - private TaskWindowBounds mTmpTaskWindowBounds = new TaskWindowBounds(); - private Rect mTmpInsets = new Rect(); - - private Rect mWindow; - private Rect mInsetWindow; - private Rect mInsets; - private Rect mTask; - private Rect mTaskInsets; - private Rect mThumbnail; - - private float mInitialTaskScale; - private float mInitialTaskTranslationX; - private float mFinalTaskScale; - private Rect mScaledTask; - private Rect mTargetTask; - private Rect mSrcWindow; - - public RecentsAnimationInterpolator(Rect window, Rect insets, Rect task, Rect taskInsets, - float taskScale, float taskTranslationX) { - mWindow = window; - mInsets = insets; - mTask = task; - mTaskInsets = taskInsets; - mInsetWindow = new Rect(window); - Utilities.insetRect(mInsetWindow, insets); - - mThumbnail = new Rect(task); - Utilities.insetRect(mThumbnail, taskInsets); - mInitialTaskScale = taskScale; - mInitialTaskTranslationX = taskTranslationX; - mFinalTaskScale = (float) mInsetWindow.width() / mThumbnail.width(); - mScaledTask = new Rect(task); - Utilities.scaleRectAboutCenter(mScaledTask, mFinalTaskScale); - Rect finalScaledTaskInsets = new Rect(taskInsets); - Utilities.scaleRect(finalScaledTaskInsets, mFinalTaskScale); - mTargetTask = new Rect(mInsetWindow); - mTargetTask.offsetTo(window.left + insets.left - finalScaledTaskInsets.left, - window.top + insets.top - finalScaledTaskInsets.top); - - float initialWinScale = 1f / mFinalTaskScale; - Rect scaledWindow = new Rect(mInsetWindow); - Utilities.scaleRectAboutCenter(scaledWindow, initialWinScale); - Rect scaledInsets = new Rect(insets); - Utilities.scaleRect(scaledInsets, initialWinScale); - mSrcWindow = new Rect(scaledWindow); - mSrcWindow.offsetTo(mThumbnail.left - scaledInsets.left, - mThumbnail.top - scaledInsets.top); - } - - public TaskWindowBounds interpolate(float t) { - mTmpTaskWindowBounds.taskScale = Utilities.mapRange(t, - mInitialTaskScale, mFinalTaskScale); - mTmpTaskWindowBounds.taskX = Utilities.mapRange(t, - mInitialTaskTranslationX, mTargetTask.left - mScaledTask.left); - mTmpTaskWindowBounds.taskY = Utilities.mapRange(t, - 0, mTargetTask.top - mScaledTask.top); - - float taskScale = Utilities.mapRange(t, 1, mFinalTaskScale); - mTmpTaskWindowBounds.winScale = taskScale / mFinalTaskScale; - mTmpTaskWindowBounds.winX = Utilities.mapRange(t, - mSrcWindow.left, 0); - mTmpTaskWindowBounds.winY = Utilities.mapRange(t, - mSrcWindow.top, 0); - - mTmpInsets.set(mInsets); - Utilities.scaleRect(mTmpInsets, (1f - t)); - mTmpTaskWindowBounds.winCrop.set(mWindow); - Utilities.insetRect(mTmpTaskWindowBounds.winCrop, mTmpInsets); - - return mTmpTaskWindowBounds; - } -} diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java index 12f8d52b82..30b10b0eab 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationWrapper.java @@ -15,28 +15,33 @@ */ package com.android.quickstep; +import com.android.launcher3.util.LooperExecutor; import com.android.launcher3.util.TraceHelper; -import com.android.systemui.shared.system.BackgroundExecutor; +import com.android.launcher3.util.UiThreadHelper; +import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; -import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import java.util.concurrent.ExecutorService; /** * Wrapper around RecentsAnimationController to help with some synchronization */ public class RecentsAnimationWrapper { - public RecentsAnimationControllerCompat controller; - public RemoteAnimationTargetCompat[] targets; + public RemoteAnimationTargetSet targetSet; + private RecentsAnimationControllerCompat mController; private boolean mInputConsumerEnabled = false; private boolean mBehindSystemBars = true; private boolean mSplitScreenMinimized = false; + private final ExecutorService mExecutorService = + new LooperExecutor(UiThreadHelper.getBackgroundLooper()); + public synchronized void setController( - RecentsAnimationControllerCompat controller, RemoteAnimationTargetCompat[] targets) { + RecentsAnimationControllerCompat controller, RemoteAnimationTargetSet targetSet) { TraceHelper.partitionSection("RecentsController", "Set controller " + controller); - this.controller = controller; - this.targets = targets; + this.mController = controller; + this.targetSet = targetSet; if (mInputConsumerEnabled) { enableInputConsumer(); @@ -48,16 +53,16 @@ public class RecentsAnimationWrapper { * on the background thread. */ public void finish(boolean toHome, Runnable onFinishComplete) { - BackgroundExecutor.get().submit(() -> { - synchronized (this) { - TraceHelper.endSection("RecentsController", - "Finish " + controller + ", toHome=" + toHome); - if (controller != null) { - controller.setInputConsumerEnabled(false); - controller.finish(toHome); - if (onFinishComplete != null) { - onFinishComplete.run(); - } + mExecutorService.submit(() -> { + RecentsAnimationControllerCompat controller = mController; + mController = null; + TraceHelper.endSection("RecentsController", + "Finish " + controller + ", toHome=" + toHome); + if (controller != null) { + controller.setInputConsumerEnabled(false); + controller.finish(toHome); + if (onFinishComplete != null) { + onFinishComplete.run(); } } }); @@ -66,13 +71,12 @@ public class RecentsAnimationWrapper { public void enableInputConsumer() { mInputConsumerEnabled = true; if (mInputConsumerEnabled) { - BackgroundExecutor.get().submit(() -> { - synchronized (this) { - TraceHelper.partitionSection("RecentsController", - "Enabling consumer on " + controller); - if (controller != null) { - controller.setInputConsumerEnabled(true); - } + mExecutorService.submit(() -> { + RecentsAnimationControllerCompat controller = mController; + TraceHelper.partitionSection("RecentsController", + "Enabling consumer on " + controller); + if (controller != null) { + controller.setInputConsumerEnabled(true); } }); } @@ -83,13 +87,12 @@ public class RecentsAnimationWrapper { return; } mBehindSystemBars = behindSystemBars; - BackgroundExecutor.get().submit(() -> { - synchronized (this) { - TraceHelper.partitionSection("RecentsController", - "Setting behind system bars on " + controller); - if (controller != null) { - controller.setAnimationTargetsBehindSystemBars(behindSystemBars); - } + mExecutorService.submit(() -> { + RecentsAnimationControllerCompat controller = mController; + TraceHelper.partitionSection("RecentsController", + "Setting behind system bars on " + controller); + if (controller != null) { + controller.setAnimationTargetsBehindSystemBars(behindSystemBars); } }); } @@ -105,14 +108,28 @@ public class RecentsAnimationWrapper { return; } mSplitScreenMinimized = minimized; - BackgroundExecutor.get().submit(() -> { - synchronized (this) { - TraceHelper.partitionSection("RecentsController", - "Setting minimize dock on " + controller); - if (controller != null) { - controller.setSplitScreenMinimized(minimized); - } + mExecutorService.submit(() -> { + RecentsAnimationControllerCompat controller = mController; + TraceHelper.partitionSection("RecentsController", + "Setting minimize dock on " + controller); + if (controller != null) { + controller.setSplitScreenMinimized(minimized); } }); } + + public void hideCurrentInputMethod() { + mExecutorService.submit(() -> { + RecentsAnimationControllerCompat controller = mController; + TraceHelper.partitionSection("RecentsController", + "Hiding currentinput method on " + controller); + if (controller != null) { + controller.hideCurrentInputMethod(); + } + }); + } + + public RecentsAnimationControllerCompat getController() { + return mController; + } } diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java index 4652f2d656..9c2c8b3130 100644 --- a/quickstep/src/com/android/quickstep/RecentsModel.java +++ b/quickstep/src/com/android/quickstep/RecentsModel.java @@ -15,6 +15,8 @@ */ package com.android.quickstep; +import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId; + import android.annotation.TargetApi; import android.app.ActivityManager; import android.content.ComponentCallbacks2; @@ -26,8 +28,10 @@ import android.graphics.drawable.Drawable; import android.os.Build; import android.os.Bundle; import android.os.Looper; +import android.os.RemoteException; import android.os.UserHandle; import android.support.annotation.WorkerThread; +import android.util.Log; import android.util.LruCache; import android.util.SparseArray; import android.view.accessibility.AccessibilityManager; @@ -85,7 +89,8 @@ public class RecentsModel extends TaskStackChangeListener { private int mTaskChangeId; private ISystemUiProxy mSystemUiProxy; private boolean mClearAssistCacheOnStackChange = true; - private final boolean mPreloadTasksInBackground; + private final boolean mIsLowRamDevice; + private boolean mPreloadTasksInBackground; private final AccessibilityManager mAccessibilityManager; private RecentsModel(Context context) { @@ -93,7 +98,7 @@ public class RecentsModel extends TaskStackChangeListener { ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - mPreloadTasksInBackground = !activityManager.isLowRamDevice(); + mIsLowRamDevice = activityManager.isLowRamDevice(); mMainThreadExecutor = new MainThreadExecutor(); Resources res = context.getResources(); @@ -158,6 +163,10 @@ public class RecentsModel extends TaskStackChangeListener { return requestId; } + public void setPreloadTasksInBackground(boolean preloadTasksInBackground) { + mPreloadTasksInBackground = preloadTasksInBackground && !mIsLowRamDevice; + } + @Override public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { mTaskChangeId++; @@ -183,7 +192,7 @@ public class RecentsModel extends TaskStackChangeListener { @Override public void onTaskStackChangedBackground() { int userId = UserHandle.myUserId(); - if (!mPreloadTasksInBackground || !checkCurrentUserId(userId, false /* debug */)) { + if (!mPreloadTasksInBackground || !checkCurrentOrManagedUserId(userId, mContext)) { // TODO: Only register this for the current user return; } @@ -234,6 +243,19 @@ public class RecentsModel extends TaskStackChangeListener { mRecentsTaskLoader.onTrimMemory(level); } + public void onOverviewShown(boolean fromHome, String tag) { + if (mSystemUiProxy == null) { + return; + } + try { + mSystemUiProxy.onOverviewShown(fromHome); + } catch (RemoteException e) { + Log.w(tag, + "Failed to notify SysUI of overview shown from " + (fromHome ? "home" : "app") + + ": ", e); + } + } + @WorkerThread public void preloadAssistData(int taskId, Bundle data) { mMainThreadExecutor.execute(() -> { diff --git a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java index 2ebf2525f5..228af8e907 100644 --- a/quickstep/src/com/android/quickstep/TaskSystemShortcut.java +++ b/quickstep/src/com/android/quickstep/TaskSystemShortcut.java @@ -27,7 +27,6 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.view.View; -import android.view.ViewTreeObserver.OnPreDrawListener; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseDraggingActivity; @@ -101,13 +100,9 @@ public class TaskSystemShortcut extends SystemShortcut } } - public static class SplitScreen extends TaskSystemShortcut implements OnPreDrawListener, - DeviceProfile.OnDeviceProfileChangeListener, View.OnLayoutChangeListener { + public static class SplitScreen extends TaskSystemShortcut { private Handler mHandler; - private RecentsView mRecentsView; - private TaskView mTaskView; - private BaseDraggingActivity mActivity; public SplitScreen() { super(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen); @@ -125,16 +120,45 @@ public class TaskSystemShortcut extends SystemShortcut if (!task.isDockable) { return null; } - mActivity = activity; - mRecentsView = activity.getOverviewPanel(); - mTaskView = taskView; + final RecentsView recentsView = activity.getOverviewPanel(); + final TaskThumbnailView thumbnailView = taskView.getThumbnail(); return (v -> { + final View.OnLayoutChangeListener onLayoutChangeListener = + new View.OnLayoutChangeListener() { + @Override + public void onLayoutChange(View v, int l, int t, int r, int b, + int oldL, int oldT, int oldR, int oldB) { + taskView.getRootView().removeOnLayoutChangeListener(this); + recentsView.removeIgnoreResetTask(taskView); + + // Start animating in the side pages once launcher has been resized + recentsView.dismissTask(taskView, false, false); + } + }; + + final DeviceProfile.OnDeviceProfileChangeListener onDeviceProfileChangeListener = + new DeviceProfile.OnDeviceProfileChangeListener() { + @Override + public void onDeviceProfileChanged(DeviceProfile dp) { + activity.removeOnDeviceProfileChangeListener(this); + if (dp.isMultiWindowMode) { + taskView.getRootView().addOnLayoutChangeListener( + onLayoutChangeListener); + } + } + }; + AbstractFloatingView.closeOpenViews(activity, true, AbstractFloatingView.TYPE_ALL & ~AbstractFloatingView.TYPE_REBIND_SAFE); + final int navBarPosition = WindowManagerWrapper.getInstance().getNavBarPosition(); + if (navBarPosition == WindowManagerWrapper.NAV_BAR_POS_INVALID) { + return; + } + boolean dockTopOrLeft = navBarPosition != WindowManagerWrapper.NAV_BAR_POS_LEFT; if (ActivityManagerWrapper.getInstance().startActivityFromRecents(taskId, - ActivityOptionsCompat.makeSplitScreenOptions(true))) { + ActivityOptionsCompat.makeSplitScreenOptions(dockTopOrLeft))) { ISystemUiProxy sysUiProxy = RecentsModel.getInstance(activity).getSystemUiProxy(); try { sysUiProxy.onSplitScreenInvoked(); @@ -145,15 +169,14 @@ public class TaskSystemShortcut extends SystemShortcut // Add a device profile change listener to kick off animating the side tasks // once we enter multiwindow mode and relayout - activity.addOnDeviceProfileChangeListener(this); + activity.addOnDeviceProfileChangeListener(onDeviceProfileChangeListener); final Runnable animStartedListener = () -> { // Hide the task view and wait for the window to be resized // TODO: Consider animating in launcher and do an in-place start activity // afterwards - mRecentsView.addIgnoreResetTask(mTaskView); - mTaskView.setAlpha(0f); - mTaskView.getViewTreeObserver().addOnPreDrawListener(SplitScreen.this); + recentsView.addIgnoreResetTask(taskView); + taskView.setAlpha(0f); }; final int[] position = new int[2]; @@ -179,35 +202,12 @@ public class TaskSystemShortcut extends SystemShortcut } }); } - - @Override - public boolean onPreDraw() { - mTaskView.getViewTreeObserver().removeOnPreDrawListener(this); - WindowManagerWrapper.getInstance().endProlongedAnimations(); - return true; - } - - @Override - public void onDeviceProfileChanged(DeviceProfile dp) { - mActivity.removeOnDeviceProfileChangeListener(this); - if (dp.isMultiWindowMode) { - mTaskView.getRootView().addOnLayoutChangeListener(this); - } - } - - @Override - public void onLayoutChange(View v, int l, int t, int r, int b, - int oldL, int oldT, int oldR, int oldB) { - mTaskView.getRootView().removeOnLayoutChangeListener(this); - mRecentsView.removeIgnoreResetTask(mTaskView); - - // Start animating in the side pages once launcher has been resized - mRecentsView.dismissTask(mTaskView, false, false); - } } public static class Pin extends TaskSystemShortcut { + private static final String TAG = Pin.class.getSimpleName(); + private Handler mHandler; public Pin() { @@ -237,6 +237,8 @@ public class TaskSystemShortcut extends SystemShortcut } catch (RemoteException e) { Log.w(TAG, "Failed to start screen pinning: ", e); } + } else { + taskView.notifyTaskLaunchFailed(TAG); } }; taskView.launchTask(true, resultCallback, mHandler); diff --git a/quickstep/src/com/android/quickstep/TaskUtils.java b/quickstep/src/com/android/quickstep/TaskUtils.java index 5bf1d07db4..2b0c98f939 100644 --- a/quickstep/src/com/android/quickstep/TaskUtils.java +++ b/quickstep/src/com/android/quickstep/TaskUtils.java @@ -16,25 +16,49 @@ package com.android.quickstep; +import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR; +import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber; +import static com.android.systemui.shared.recents.utilities.Utilities.getSurface; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; + +import android.animation.ValueAnimator; +import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.graphics.RectF; import android.os.UserHandle; import android.util.Log; +import android.view.Surface; +import android.view.View; +import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.ItemInfo; +import com.android.launcher3.Utilities; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.util.ComponentKey; +import com.android.quickstep.util.ClipAnimationHelper; +import com.android.quickstep.util.MultiValueUpdateListener; +import com.android.quickstep.util.RemoteAnimationTargetSet; +import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.Task; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; + +import java.util.List; /** * Contains helpful methods for retrieving data from {@link Task}s. - * TODO: remove this once we switch to getting the icon and label from IconCache. */ public class TaskUtils { private static final String TAG = "TaskUtils"; + /** + * TODO: remove this once we switch to getting the icon and label from IconCache. + */ public static CharSequence getTitle(Context context, Task task) { LauncherAppsCompat launcherAppsCompat = LauncherAppsCompat.getInstance(context); UserManagerCompat userManagerCompat = UserManagerCompat.getInstance(context); @@ -53,4 +77,150 @@ public class TaskUtils { public static ComponentKey getComponentKeyForTask(Task.TaskKey taskKey) { return new ComponentKey(taskKey.getComponent(), UserHandle.of(taskKey.userId)); } + + + /** + * Try to find a TaskView that corresponds with the component of the launched view. + * + * If this method returns a non-null TaskView, it will be used in composeRecentsLaunchAnimation. + * Otherwise, we will assume we are using a normal app transition, but it's possible that the + * opening remote target (which we don't get until onAnimationStart) will resolve to a TaskView. + */ + public static TaskView findTaskViewToLaunch( + BaseDraggingActivity activity, View v, RemoteAnimationTargetCompat[] targets) { + if (v instanceof TaskView) { + return (TaskView) v; + } + RecentsView recentsView = activity.getOverviewPanel(); + + // It's possible that the launched view can still be resolved to a visible task view, check + // the task id of the opening task and see if we can find a match. + if (v.getTag() instanceof ItemInfo) { + ItemInfo itemInfo = (ItemInfo) v.getTag(); + ComponentName componentName = itemInfo.getTargetComponent(); + int userId = itemInfo.user.getIdentifier(); + if (componentName != null) { + for (int i = 0; i < recentsView.getChildCount(); i++) { + TaskView taskView = recentsView.getPageAt(i); + if (recentsView.isTaskViewVisible(taskView)) { + Task.TaskKey key = taskView.getTask().key; + if (componentName.equals(key.getComponent()) && userId == key.userId) { + return taskView; + } + } + } + } + } + + if (targets == null) { + return null; + } + // Resolve the opening task id + int openingTaskId = -1; + for (RemoteAnimationTargetCompat target : targets) { + if (target.mode == MODE_OPENING) { + openingTaskId = target.taskId; + break; + } + } + + // If there is no opening task id, fall back to the normal app icon launch animation + if (openingTaskId == -1) { + return null; + } + + // If the opening task id is not currently visible in overview, then fall back to normal app + // icon launch animation + TaskView taskView = recentsView.getTaskView(openingTaskId); + if (taskView == null || !recentsView.isTaskViewVisible(taskView)) { + return null; + } + return taskView; + } + + /** + * @return Animator that controls the window of the opening targets for the recents launch + * animation. + */ + public static ValueAnimator getRecentsWindowAnimator(TaskView v, boolean skipViewChanges, + RemoteAnimationTargetCompat[] targets, final ClipAnimationHelper inOutHelper) { + final ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); + appAnimator.setInterpolator(TOUCH_RESPONSE_INTERPOLATOR); + appAnimator.addUpdateListener(new MultiValueUpdateListener() { + + // Defer fading out the view until after the app window gets faded in + final FloatProp mViewAlpha = new FloatProp(1f, 0f, 75, 75, LINEAR); + final FloatProp mTaskAlpha = new FloatProp(0f, 1f, 0, 75, LINEAR); + + final RemoteAnimationTargetSet mTargetSet; + + final RectF mThumbnailRect; + private Surface mSurface; + private long mFrameNumber; + + { + mTargetSet = new RemoteAnimationTargetSet(targets, MODE_OPENING); + inOutHelper.setTaskTransformCallback((t, app) -> { + t.setAlpha(app.leash, mTaskAlpha.value); + + if (!skipViewChanges) { + t.deferTransactionUntil(app.leash, mSurface, mFrameNumber); + } + }); + + inOutHelper.prepareAnimation(true /* isOpening */); + inOutHelper.fromTaskThumbnailView(v.getThumbnail(), (RecentsView) v.getParent(), + mTargetSet.apps.length == 0 ? null : mTargetSet.apps[0]); + + mThumbnailRect = new RectF(inOutHelper.getTargetRect()); + mThumbnailRect.offset(-v.getTranslationX(), -v.getTranslationY()); + Utilities.scaleRectFAboutCenter(mThumbnailRect, 1 / v.getScaleX()); + } + + @Override + public void onUpdate(float percent) { + mSurface = getSurface(v); + mFrameNumber = mSurface != null ? getNextFrameNumber(mSurface) : -1; + if (mFrameNumber == -1) { + // Booo, not cool! Our surface got destroyed, so no reason to animate anything. + Log.w(TAG, "Failed to animate, surface got destroyed."); + return; + } + + RectF taskBounds = inOutHelper.applyTransform(mTargetSet, 1 - percent); + if (!skipViewChanges) { + float scale = taskBounds.width() / mThumbnailRect.width(); + v.setScaleX(scale); + v.setScaleY(scale); + v.setTranslationX(taskBounds.centerX() - mThumbnailRect.centerX()); + v.setTranslationY(taskBounds.centerY() - mThumbnailRect.centerY()); + v.setAlpha(mViewAlpha.value); + } + } + }); + return appAnimator; + } + + public static boolean taskIsATargetWithMode(RemoteAnimationTargetCompat[] targets, + int taskId, int mode) { + for (RemoteAnimationTargetCompat target : targets) { + if (target.mode == mode && target.taskId == taskId) { + return true; + } + } + return false; + } + + public static boolean checkCurrentOrManagedUserId(int currentUserId, Context context) { + if (currentUserId == UserHandle.myUserId()) { + return true; + } + List allUsers = UserManagerCompat.getInstance(context).getUserProfiles(); + for (int i = allUsers.size() - 1; i >= 0; i--) { + if (currentUserId == allUsers.get(i).getIdentifier()) { + return true; + } + } + return false; + } } diff --git a/quickstep/src/com/android/quickstep/TouchConsumer.java b/quickstep/src/com/android/quickstep/TouchConsumer.java index 1290ec3375..aa844d80df 100644 --- a/quickstep/src/com/android/quickstep/TouchConsumer.java +++ b/quickstep/src/com/android/quickstep/TouchConsumer.java @@ -46,7 +46,7 @@ public interface TouchConsumer extends Consumer { default void onQuickScrubProgress(float progress) { } - default void onQuickStep(float eventX, float eventY, long eventTime) { } + default void onQuickStep(MotionEvent ev) { } /** * Called on the binder thread to allow the consumer to process the motion event before it is diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index 84d8983e03..aecb66c77d 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -21,7 +21,7 @@ import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_POINTER_DOWN; import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_UP; - +import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE; import android.annotation.TargetApi; @@ -39,13 +39,12 @@ import android.util.SparseArray; import android.view.Choreographer; import android.view.MotionEvent; import android.view.VelocityTracker; -import android.view.View; import android.view.ViewConfiguration; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.MainThreadExecutor; -import com.android.launcher3.R; import com.android.launcher3.util.TraceHelper; +import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; @@ -99,8 +98,6 @@ public class TouchInteractionService extends Service { public void onBind(ISystemUiProxy iSystemUiProxy) { mISystemUiProxy = iSystemUiProxy; mRecentsModel.setSystemUiProxy(mISystemUiProxy); - RemoteRunnable.executeSafely(() -> mISystemUiProxy.setRecentsOnboardingText( - getResources().getString(R.string.recents_swipe_up_onboarding))); mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); } @@ -150,6 +147,11 @@ public class TouchInteractionService extends Service { TraceHelper.endSection("SysUiBinder", "onQuickStep"); } + + @Override + public void onTip(int actionType, int viewType) { + mOverviewCommandHelper.onTip(actionType, viewType); + } }; private final TouchConsumer mNoOpTouchConsumer = (ev) -> {}; @@ -167,6 +169,7 @@ public class TouchInteractionService extends Service { private ISystemUiProxy mISystemUiProxy; private OverviewCommandHelper mOverviewCommandHelper; private OverviewInteractionState mOverviewInteractionState; + private OverviewCallbacks mOverviewCallbacks; private Choreographer mMainThreadChoreographer; private Choreographer mBackgroundThreadChoreographer; @@ -176,11 +179,13 @@ public class TouchInteractionService extends Service { super.onCreate(); mAM = ActivityManagerWrapper.getInstance(); mRecentsModel = RecentsModel.getInstance(this); + mRecentsModel.setPreloadTasksInBackground(true); mMainThreadExecutor = new MainThreadExecutor(); mOverviewCommandHelper = new OverviewCommandHelper(this); mMainThreadChoreographer = Choreographer.getInstance(); mEventQueue = new MotionEventQueue(mMainThreadChoreographer, mNoOpTouchConsumer); mOverviewInteractionState = OverviewInteractionState.getInstance(this); + mOverviewCallbacks = OverviewCallbacks.get(this); sConnected = true; @@ -191,6 +196,7 @@ public class TouchInteractionService extends Service { @Override public void onDestroy() { + mOverviewCommandHelper.onDestroy(); sConnected = false; super.onDestroy(); } @@ -222,16 +228,17 @@ public class TouchInteractionService extends Service { if (runningTaskInfo == null && !forceToLauncher) { return mNoOpTouchConsumer; } else if (forceToLauncher || - runningTaskInfo.topActivity.equals(mOverviewCommandHelper.launcher)) { + runningTaskInfo.topActivity.equals(mOverviewCommandHelper.overviewComponent)) { return getOverviewConsumer(); } else { if (tracker == null) { tracker = VelocityTracker.obtain(); } return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel, - mOverviewCommandHelper.homeIntent, + mOverviewCommandHelper.overviewIntent, mOverviewCommandHelper.getActivityControlHelper(), mMainThreadExecutor, - mBackgroundThreadChoreographer, downHitTarget, tracker); + mBackgroundThreadChoreographer, downHitTarget, mOverviewCallbacks, + tracker); } } @@ -249,7 +256,7 @@ public class TouchInteractionService extends Service { private final ActivityControlHelper mActivityHelper; private final T mActivity; - private final View mTarget; + private final BaseDragLayer mTarget; private final int[] mLocationOnScreen = new int[2]; private final PointF mDownPos = new PointF(); private final int mTouchSlop; @@ -257,7 +264,6 @@ public class TouchInteractionService extends Service { private boolean mTrackingStarted = false; private boolean mInvalidated = false; - private boolean mHadWindowFocusOnDown; private float mLastProgress = 0; private boolean mStartPending = false; @@ -282,8 +288,7 @@ public class TouchInteractionService extends Service { if (action == ACTION_DOWN) { mTrackingStarted = false; mDownPos.set(ev.getX(), ev.getY()); - mHadWindowFocusOnDown = mTarget.hasWindowFocus(); - } else if (!mTrackingStarted && mHadWindowFocusOnDown) { + } else if (!mTrackingStarted) { switch (action) { case ACTION_POINTER_UP: case ACTION_POINTER_DOWN: @@ -294,7 +299,6 @@ public class TouchInteractionService extends Service { case ACTION_MOVE: { float displacement = ev.getY() - mDownPos.y; if (Math.abs(displacement) >= mTouchSlop) { - mTrackingStarted = true; mTarget.getLocationOnScreen(mLocationOnScreen); // Send a down event only when mTouchSlop is crossed. @@ -302,6 +306,7 @@ public class TouchInteractionService extends Service { down.setAction(ACTION_DOWN); sendEvent(down); down.recycle(); + mTrackingStarted = true; } } } @@ -320,22 +325,45 @@ public class TouchInteractionService extends Service { int flags = ev.getEdgeFlags(); ev.setEdgeFlags(flags | EDGE_NAV_BAR); ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]); - mTarget.dispatchTouchEvent(ev); + if (!mTrackingStarted) { + mTarget.onInterceptTouchEvent(ev); + } + mTarget.onTouchEvent(ev); ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]); ev.setEdgeFlags(flags); } + @Override + public void onQuickStep(MotionEvent ev) { + if (mInvalidated) { + return; + } + OverviewCallbacks.get(mActivity).closeAllWindows(); + ActivityManagerWrapper.getInstance() + .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); + } + @Override public void updateTouchTracking(int interactionType) { if (mInvalidated) { return; } if (interactionType == INTERACTION_QUICK_SCRUB) { - mStartPending = true; + if (!mQuickScrubController.prepareQuickScrub(TAG)) { + mInvalidated = true; + return; + } + OverviewCallbacks.get(mActivity).closeAllWindows(); + ActivityManagerWrapper.getInstance() + .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); + mStartPending = true; Runnable action = () -> { - mQuickScrubController.onQuickScrubStart( - mActivityHelper.onQuickInteractionStart(mActivity, true)); + if (!mQuickScrubController.prepareQuickScrub(TAG)) { + mInvalidated = true; + return; + } + mActivityHelper.onQuickInteractionStart(mActivity, null, true); mQuickScrubController.onQuickScrubProgress(mLastProgress); mStartPending = false; @@ -343,7 +371,6 @@ public class TouchInteractionService extends Service { mQuickScrubController.onQuickScrubEnd(); mEndPending = false; } - }; mActivityHelper.executeOnWindowAvailable(mActivity, action); @@ -365,7 +392,7 @@ public class TouchInteractionService extends Service { @Override public void onQuickScrubProgress(float progress) { mLastProgress = progress; - if (mInvalidated || mEndPending) { + if (mInvalidated || mStartPending) { return; } mQuickScrubController.onQuickScrubProgress(progress); diff --git a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java index d4c35e0b1e..84b2176488 100644 --- a/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -15,54 +15,57 @@ */ package com.android.quickstep; -import static com.android.launcher3.anim.Interpolators.ACCEL_2; +import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER; +import static com.android.launcher3.Utilities.postAsyncCallback; +import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.LINEAR; -import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_DURATION; +import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_FROM_APP_START_DURATION; import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL; import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB; -import static com.android.systemui.shared.recents.utilities.Utilities - .postAtFrontOfQueueAsynchronously; -import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.annotation.TargetApi; import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; -import android.content.res.Resources; +import android.graphics.Canvas; import android.graphics.Point; import android.graphics.Rect; import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; +import android.support.annotation.AnyThread; import android.support.annotation.UiThread; import android.support.annotation.WorkerThread; import android.util.Log; import android.view.View; import android.view.ViewTreeObserver.OnDrawListener; +import android.view.WindowManager; import android.view.animation.Interpolator; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; -import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.R; -import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; -import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; +import com.android.launcher3.util.MultiValueAlpha; +import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.TraceHelper; import com.android.quickstep.ActivityControlHelper.ActivityInitListener; +import com.android.quickstep.ActivityControlHelper.AnimationFactory; import com.android.quickstep.ActivityControlHelper.LayoutListener; import com.android.quickstep.TouchConsumer.InteractionType; import com.android.quickstep.util.ClipAnimationHelper; -import com.android.quickstep.util.SysuiEventLogger; +import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.systemui.shared.recents.model.ThumbnailData; @@ -70,7 +73,7 @@ import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import com.android.systemui.shared.system.TransactionCompat; +import com.android.systemui.shared.system.WindowCallbacksCompat; import com.android.systemui.shared.system.WindowManagerWrapper; import java.util.StringJoiner; @@ -96,16 +99,30 @@ public class WindowTransformSwipeHandler { private static final int STATE_HANDLER_INVALIDATED = 1 << 7; private static final int STATE_GESTURE_STARTED = 1 << 8; private static final int STATE_GESTURE_CANCELLED = 1 << 9; + private static final int STATE_GESTURE_COMPLETED = 1 << 10; // States for quick switch/scrub - private static final int STATE_SWITCH_TO_SCREENSHOT_COMPLETE = 1 << 10; - private static final int STATE_QUICK_SCRUB_START = 1 << 11; - private static final int STATE_QUICK_SCRUB_END = 1 << 12; + private static final int STATE_CURRENT_TASK_FINISHED = 1 << 11; + private static final int STATE_QUICK_SCRUB_START = 1 << 12; + private static final int STATE_QUICK_SCRUB_END = 1 << 13; + + private static final int STATE_CAPTURE_SCREENSHOT = 1 << 14; + private static final int STATE_SCREENSHOT_CAPTURED = 1 << 15; + + private static final int STATE_RESUME_LAST_TASK = 1 << 16; private static final int LAUNCHER_UI_STATES = STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED; + private static final int LONG_SWIPE_ENTER_STATE = + STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED + | STATE_APP_CONTROLLER_RECEIVED; + + private static final int LONG_SWIPE_START_STATE = + STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED + | STATE_APP_CONTROLLER_RECEIVED | STATE_SCREENSHOT_CAPTURED; + // For debugging, keep in sync with above states private static final String[] STATES = new String[] { "STATE_LAUNCHER_PRESENT", @@ -118,16 +135,21 @@ public class WindowTransformSwipeHandler { "STATE_HANDLER_INVALIDATED", "STATE_GESTURE_STARTED", "STATE_GESTURE_CANCELLED", - "STATE_SWITCH_TO_SCREENSHOT_COMPLETE", - "STATE_QUICK_SWITCH", + "STATE_GESTURE_COMPLETED", + "STATE_CURRENT_TASK_FINISHED", "STATE_QUICK_SCRUB_START", - "STATE_QUICK_SCRUB_END" + "STATE_QUICK_SCRUB_END", + "STATE_CAPTURE_SCREENSHOT", + "STATE_SCREENSHOT_CAPTURED", + "STATE_RESUME_LAST_TASK", }; - private static final long MAX_SWIPE_DURATION = 200; - private static final long MIN_SWIPE_DURATION = 80; + public static final long MAX_SWIPE_DURATION = 350; + public static final long MIN_SWIPE_DURATION = 80; private static final float MIN_PROGRESS_FOR_OVERVIEW = 0.5f; + private static final float SWIPE_DURATION_MULTIPLIER = + Math.min(1 / MIN_PROGRESS_FOR_OVERVIEW, 1 / (1 - MIN_PROGRESS_FOR_OVERVIEW)); private final ClipAnimationHelper mClipAnimationHelper = new ClipAnimationHelper(); @@ -142,13 +164,16 @@ public class WindowTransformSwipeHandler { // visible. private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift); - private final MainThreadExecutor mMainExecutor = new MainThreadExecutor(); + private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper()); private final Context mContext; - private final int mRunningTaskId; private final ActivityControlHelper mActivityControlHelper; private final ActivityInitListener mActivityInitListener; + private final int mRunningTaskId; + private final RunningTaskInfo mRunningTaskInfo; + private ThumbnailData mTaskSnapshot; + private MultiStateCallback mStateCallback; private AnimatorPlaybackController mLauncherTransitionController; @@ -156,14 +181,16 @@ public class WindowTransformSwipeHandler { private LayoutListener mLayoutListener; private RecentsView mRecentsView; private QuickScrubController mQuickScrubController; + private AnimationFactory mAnimationFactory = (t) -> { }; private Runnable mLauncherDrawnCallback; private boolean mWasLauncherAlreadyVisible; - private float mCurrentDisplacement; private boolean mGestureStarted; private int mLogAction = Touch.SWIPE; + private float mCurrentQuickScrubProgress; + private boolean mQuickScrubBlocked; private @InteractionType int mInteractionType = INTERACTION_NORMAL; @@ -174,19 +201,25 @@ public class WindowTransformSwipeHandler { private final long mTouchTimeMs; private long mLauncherFrameDrawnTime; + private boolean mBgLongSwipeMode = false; + private boolean mUiLongSwipeMode = false; + private float mLongSwipeDisplacement = 0; + private LongSwipeHelper mLongSwipeController; + WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs, ActivityControlHelper controller) { mContext = context; + mRunningTaskInfo = runningTaskInfo; mRunningTaskId = runningTaskInfo.id; mTouchTimeMs = touchTimeMs; mActivityControlHelper = controller; mActivityInitListener = mActivityControlHelper .createActivityInitListener(this::onActivityInit); + initStateCallbacks(); // Register the input consumer on the UI thread, to ensure that it runs after any pending // unregister calls - mMainExecutor.execute(mInputConsumer::registerInputConsumer); - initStateCallbacks(); + executeOnUiThread(mInputConsumer::registerInputConsumer); } private void initStateCallbacks() { @@ -203,45 +236,66 @@ public class WindowTransformSwipeHandler { mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN, this::launcherFrameDrawn); mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED, - this::notifyGestureStarted); + this::notifyGestureStartedAsync); mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_STARTED | STATE_GESTURE_CANCELLED, this::resetStateForAnimationCancel); - mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED - | STATE_SCALED_CONTROLLER_APP, + mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_APP_CONTROLLER_RECEIVED, + this::sendRemoteAnimationsToAnimationFactory); + + mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SCALED_CONTROLLER_APP, + this::resumeLastTaskForQuickstep); + mStateCallback.addCallback(STATE_RESUME_LAST_TASK | STATE_APP_CONTROLLER_RECEIVED, this::resumeLastTask); + mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED | STATE_ACTIVITY_MULTIPLIER_COMPLETE - | STATE_SCALED_CONTROLLER_RECENTS, + | STATE_CAPTURE_SCREENSHOT, this::switchToScreenshot); + + mStateCallback.addCallback(STATE_SCREENSHOT_CAPTURED | STATE_GESTURE_COMPLETED + | STATE_SCALED_CONTROLLER_RECENTS, + this::finishCurrentTransitionToHome); + mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED | STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_SCALED_CONTROLLER_RECENTS - | STATE_SWITCH_TO_SCREENSHOT_COMPLETE, + | STATE_CURRENT_TASK_FINISHED + | STATE_GESTURE_COMPLETED, this::setupLauncherUiAfterSwipeUpAnimation); - mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SCALED_CONTROLLER_APP, - this::reset); - mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler); mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED, this::invalidateHandlerWithLauncher); + mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED + | STATE_SCALED_CONTROLLER_APP, + this::notifyTransitionCancelled); - mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_QUICK_SCRUB_START, + mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_QUICK_SCRUB_START, this::onQuickScrubStart); - mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_QUICK_SCRUB_START + mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_QUICK_SCRUB_START | STATE_SCALED_CONTROLLER_RECENTS, this::onFinishedTransitionToQuickScrub); - mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_SWITCH_TO_SCREENSHOT_COMPLETE + mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_CURRENT_TASK_FINISHED | STATE_QUICK_SCRUB_END, this::switchToFinalAppAfterQuickScrub); + + mStateCallback.addCallback(LONG_SWIPE_ENTER_STATE, this::checkLongSwipeCanEnter); + mStateCallback.addCallback(LONG_SWIPE_START_STATE, this::checkLongSwipeCanStart); + } + + private void executeOnUiThread(Runnable action) { + if (Looper.myLooper() == mMainThreadHandler.getLooper()) { + action.run(); + } else { + postAsyncCallback(mMainThreadHandler, action); + } } private void setStateOnUiThread(int stateFlag) { - Handler handler = mMainExecutor.getHandler(); - if (Looper.myLooper() == handler.getLooper()) { + if (Looper.myLooper() == mMainThreadHandler.getLooper()) { mStateCallback.setState(stateFlag); } else { - postAtFrontOfQueueAsynchronously(handler, () -> mStateCallback.setState(stateFlag)); + postAsyncCallback(mMainThreadHandler, () -> mStateCallback.setState(stateFlag)); } } @@ -285,7 +339,11 @@ public class WindowTransformSwipeHandler { mActivity = activity; // Override the visibility of the activity until the gesture actually starts and we swipe // up, or until we transition home and the home animation is composed - mActivity.setForceInvisible(true); + if (alreadyOnHome) { + mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER); + } else { + mActivity.addForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER); + } mRecentsView = activity.getOverviewPanel(); mQuickScrubController = mRecentsView.getQuickScrubController(); @@ -304,33 +362,27 @@ public class WindowTransformSwipeHandler { if (mActivity != activity) { return; } - if ((mStateCallback.getState() & STATE_HANDLER_INVALIDATED) != 0) { + if (mStateCallback.hasStates(STATE_HANDLER_INVALIDATED)) { return; } - mStateCallback.setState(STATE_LAUNCHER_STARTED); - mActivityControlHelper.prepareRecentsUI(mActivity, mWasLauncherAlreadyVisible); + mAnimationFactory = mActivityControlHelper.prepareRecentsUI(mActivity, + mWasLauncherAlreadyVisible, this::onAnimatorPlaybackControllerCreated); AbstractFloatingView.closeAllOpenViews(activity, mWasLauncherAlreadyVisible); if (mWasLauncherAlreadyVisible) { - mLauncherTransitionController = mActivityControlHelper - .createControllerForVisibleActivity(activity); - mLauncherTransitionController.dispatchOnStart(); - mLauncherTransitionController.setPlayFraction(mCurrentShift.value); - mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_DRAWN); } else { TraceHelper.beginSection("WTS-init"); - // TODO: Implement a better animation for fading in - View rootView = activity.getRootView(); - rootView.setAlpha(0); - rootView.getViewTreeObserver().addOnDrawListener(new OnDrawListener() { + View dragLayer = activity.getDragLayer(); + mActivityControlHelper.getAlphaProperty(activity).setValue(0); + dragLayer.getViewTreeObserver().addOnDrawListener(new OnDrawListener() { @Override public void onDraw() { TraceHelper.endSection("WTS-init", "Launcher frame is drawn"); - rootView.post(() -> - rootView.getViewTreeObserver().removeOnDrawListener(this)); + dragLayer.post(() -> + dragLayer.getViewTreeObserver().removeOnDrawListener(this)); if (activity != mActivity) { return; } @@ -341,8 +393,10 @@ public class WindowTransformSwipeHandler { } mRecentsView.showTask(mRunningTaskId); - mRecentsView.setFirstTaskIconScaledDown(true /* isScaledDown */, false /* animate */); + mRecentsView.setRunningTaskHidden(true); + mRecentsView.setRunningTaskIconScaledDown(true /* isScaledDown */, false /* animate */); mLayoutListener.open(); + mStateCallback.setState(STATE_LAUNCHER_STARTED); } public void setLauncherOnDrawCallback(Runnable callback) { @@ -350,15 +404,22 @@ public class WindowTransformSwipeHandler { } private void launcherFrameDrawn() { - View rootView = mActivity.getRootView(); - if (rootView.getAlpha() < 1) { + AlphaProperty property = mActivityControlHelper.getAlphaProperty(mActivity); + if (property.getValue() < 1) { if (mGestureStarted) { final MultiStateCallback callback = mStateCallback; - rootView.animate().alpha(1) - .setDuration(getFadeInDuration()) - .withEndAction(() -> callback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE)); + ObjectAnimator animator = ObjectAnimator.ofFloat( + property, MultiValueAlpha.VALUE, 1); + animator.setDuration(getFadeInDuration()).addListener( + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + callback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE); + } + }); + animator.start(); } else { - rootView.setAlpha(1); + property.setValue(1); mStateCallback.setState(STATE_ACTIVITY_MULTIPLIER_COMPLETE); } } @@ -368,15 +429,16 @@ public class WindowTransformSwipeHandler { mLauncherFrameDrawnTime = SystemClock.uptimeMillis(); } + private void sendRemoteAnimationsToAnimationFactory() { + mAnimationFactory.onRemoteAnimationReceived(mRecentsAnimationWrapper.targetSet); + } + private void initializeLauncherAnimationController() { mLayoutListener.setHandler(this); - onLauncherLayoutChanged(); - - final long transitionDelay = mLauncherFrameDrawnTime - mTouchTimeMs; - SysuiEventLogger.writeDummyRecentsTransition(transitionDelay); + buildAnimationController(); if (LatencyTrackerCompat.isEnabled(mContext)) { - LatencyTrackerCompat.logToggleRecents((int) transitionDelay); + LatencyTrackerCompat.logToggleRecents((int) (mLauncherFrameDrawnTime - mTouchTimeMs)); } } @@ -391,110 +453,108 @@ public class WindowTransformSwipeHandler { } mInteractionType = interactionType; - setStateOnUiThread(STATE_QUICK_SCRUB_START); + setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED); // Start the window animation without waiting for launcher. - animateToProgress(1f, QUICK_SCRUB_START_DURATION); + animateToProgress(1f, QUICK_SCRUB_FROM_APP_START_DURATION, LINEAR); } @WorkerThread public void updateDisplacement(float displacement) { - mCurrentDisplacement = displacement; + // We are moving in the negative x/y direction + displacement = -displacement; + if (displacement > mTransitionDragLength) { + mCurrentShift.updateValue(1); - float translation = Utilities.boundToRange(-mCurrentDisplacement, 0, mTransitionDragLength); - float shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength; - mCurrentShift.updateValue(shift); + if (!mBgLongSwipeMode) { + mBgLongSwipeMode = true; + executeOnUiThread(this::onLongSwipeEnabledUi); + } + mLongSwipeDisplacement = displacement - mTransitionDragLength; + executeOnUiThread(this::onLongSwipeDisplacementUpdated); + } else { + if (mBgLongSwipeMode) { + mBgLongSwipeMode = false; + executeOnUiThread(this::onLongSwipeDisabledUi); + } + float translation = Math.max(displacement, 0); + float shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength; + mCurrentShift.updateValue(shift); + } } /** * Called by {@link #mLayoutListener} when launcher layout changes */ - public void onLauncherLayoutChanged() { + public void buildAnimationController() { initTransitionEndpoints(mActivity.getDeviceProfile()); + mAnimationFactory.createActivityController(mTransitionDragLength); + } - if (!mWasLauncherAlreadyVisible) { - mLauncherTransitionController = mActivityControlHelper - .createControllerForHiddenActivity(mActivity, mTransitionDragLength); - mLauncherTransitionController.setPlayFraction(mCurrentShift.value); - } + private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) { + mLauncherTransitionController = anim; + mLauncherTransitionController.dispatchOnStart(); + mLauncherTransitionController.setPlayFraction(mCurrentShift.value); } @WorkerThread private void updateFinalShift() { float shift = mCurrentShift.value; - synchronized (mRecentsAnimationWrapper) { - if (mRecentsAnimationWrapper.controller != null) { - Interpolator interpolator = mInteractionType == INTERACTION_QUICK_SCRUB - ? ACCEL_2 : LINEAR; - float interpolated = interpolator.getInterpolation(shift); - mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targets, interpolated); + RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController(); + if (controller != null) { + mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet, shift); + + // TODO: This logic is spartanic! + boolean passedThreshold = shift > 0.12f; + mRecentsAnimationWrapper.setAnimationTargetsBehindSystemBars(!passedThreshold); + if (mActivityControlHelper.shouldMinimizeSplitScreen()) { + mRecentsAnimationWrapper.setSplitScreenMinimizedForTransaction(passedThreshold); } } - if (mLauncherTransitionController != null) { - Runnable runOnUi = () -> { - if (mLauncherTransitionController == null) { - return; - } - mLauncherTransitionController.setPlayFraction(shift); + executeOnUiThread(this::updateFinalShiftUi); + } - // Make sure the window follows the first task if it moves, e.g. during quick scrub. - View firstTask = mRecentsView.getPageAt(0); - // The first task may be null if we are swiping up from a task that does not - // appear in the list (ie. the assistant) - if (firstTask != null) { - int scrollForFirstTask = mRecentsView.getScrollForPage(0); - int offsetFromFirstTask = (scrollForFirstTask - mRecentsView.getScrollX()); - mClipAnimationHelper.offsetTarget(firstTask.getScaleX(), - offsetFromFirstTask + firstTask.getTranslationX(), - mRecentsView.getTranslationY()); - } - if (mRecentsAnimationWrapper.controller != null) { - // TODO: This logic is spartanic! - boolean passedThreshold = shift > 0.12f; - mRecentsAnimationWrapper.setAnimationTargetsBehindSystemBars(!passedThreshold); - mRecentsAnimationWrapper.setSplitScreenMinimizedForTransaction(passedThreshold); - } - }; - if (Looper.getMainLooper() == Looper.myLooper()) { - runOnUi.run(); - } else { - // The fling operation completed even before the launcher was drawn - mMainExecutor.execute(runOnUi); - } + private void updateFinalShiftUi() { + if (mLauncherTransitionController == null) { + return; } + mLauncherTransitionController.setPlayFraction(mCurrentShift.value); } public void onRecentsAnimationStart(RecentsAnimationControllerCompat controller, - RemoteAnimationTargetCompat[] apps, Rect homeContentInsets, Rect minimizedHomeBounds) { - if (apps != null) { - // Use the top closing app to determine the insets for the animation - for (RemoteAnimationTargetCompat target : apps) { - if (target.mode == MODE_CLOSING) { - DeviceProfile dp = LauncherAppState.getIDP(mContext).getDeviceProfile(mContext); - final Rect homeStackBounds; + RemoteAnimationTargetSet targets, Rect homeContentInsets, Rect minimizedHomeBounds) { + LauncherAppState appState = LauncherAppState.getInstanceNoCreate(); + InvariantDeviceProfile idp = appState == null ? + new InvariantDeviceProfile(mContext) : appState.getInvariantDeviceProfile(); + DeviceProfile dp = idp.getDeviceProfile(mContext); + final Rect overviewStackBounds; + RemoteAnimationTargetCompat runningTaskTarget = targets.findTask(mRunningTaskId); - if (minimizedHomeBounds != null) { - homeStackBounds = minimizedHomeBounds; - dp = dp.getMultiWindowProfile(mContext, - new Point(minimizedHomeBounds.width(), minimizedHomeBounds.height())); - dp.updateInsets(homeContentInsets); - } else { - homeStackBounds = new Rect(0, 0, dp.widthPx, dp.heightPx); - // TODO: Workaround for an existing issue where the home content insets are - // not valid immediately after rotation, just use the stable insets for now - Rect insets = new Rect(); - WindowManagerWrapper.getInstance().getStableInsets(insets); - dp.updateInsets(insets); - } - - mClipAnimationHelper.updateSource(homeStackBounds, target); - initTransitionEndpoints(dp); - } - } + if (minimizedHomeBounds != null && runningTaskTarget != null) { + overviewStackBounds = mActivityControlHelper + .getOverviewWindowBounds(minimizedHomeBounds, runningTaskTarget); + dp = dp.getMultiWindowProfile(mContext, + new Point(minimizedHomeBounds.width(), minimizedHomeBounds.height())); + dp.updateInsets(homeContentInsets); + } else { + overviewStackBounds = new Rect(0, 0, dp.widthPx, dp.heightPx); + // If we are not in multi-window mode, home insets should be same as system insets. + Rect insets = new Rect(); + WindowManagerWrapper.getInstance().getStableInsets(insets); + dp = dp.copy(mContext); + dp.updateInsets(insets); } - mRecentsAnimationWrapper.setController(controller, apps); + dp.updateIsSeascape(mContext.getSystemService(WindowManager.class)); + + if (runningTaskTarget != null) { + mClipAnimationHelper.updateSource(overviewStackBounds, runningTaskTarget); + } + mClipAnimationHelper.prepareAnimation(false /* isOpening */); + initTransitionEndpoints(dp); + + mRecentsAnimationWrapper.setController(controller, targets); setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED); } @@ -505,9 +565,10 @@ public class WindowTransformSwipeHandler { } public void onGestureStarted() { - notifyGestureStarted(); + notifyGestureStartedAsync(); setStateOnUiThread(STATE_GESTURE_STARTED); mGestureStarted = true; + mRecentsAnimationWrapper.hideCurrentInputMethod(); mRecentsAnimationWrapper.enableInputConsumer(); } @@ -515,43 +576,56 @@ public class WindowTransformSwipeHandler { * Notifies the launcher that the swipe gesture has started. This can be called multiple times * on both background and UI threads */ - private void notifyGestureStarted() { + @AnyThread + private void notifyGestureStartedAsync() { final T curActivity = mActivity; if (curActivity != null) { // Once the gesture starts, we can no longer transition home through the button, so // reset the force override of the activity visibility - mActivity.setForceInvisible(false); - mActivityControlHelper.onQuickstepGestureStarted( - curActivity, mWasLauncherAlreadyVisible); + mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER); } } @WorkerThread public void onGestureEnded(float endVelocity) { - Resources res = mContext.getResources(); - float flingThreshold = res.getDimension(R.dimen.quickstep_fling_threshold_velocity); - boolean isFling = Math.abs(endVelocity) > flingThreshold; + float flingThreshold = mContext.getResources() + .getDimension(R.dimen.quickstep_fling_threshold_velocity); + boolean isFling = mGestureStarted && Math.abs(endVelocity) > flingThreshold; + setStateOnUiThread(STATE_GESTURE_COMPLETED); + mLogAction = isFling ? Touch.FLING : Touch.SWIPE; + + if (mBgLongSwipeMode) { + executeOnUiThread(() -> onLongSwipeGestureFinishUi(endVelocity, isFling)); + } else { + handleNormalGestureEnd(endVelocity, isFling); + } + } + + private void handleNormalGestureEnd(float endVelocity, boolean isFling) { long duration = MAX_SWIPE_DURATION; final float endShift; if (!isFling) { - endShift = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? 1 : 0; - mLogAction = Touch.SWIPE; + endShift = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW && mGestureStarted ? 1 : 0; + long expectedDuration = Math.abs(Math.round((endShift - mCurrentShift.value) + * MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER)); + duration = Math.min(MAX_SWIPE_DURATION, expectedDuration); } else { endShift = endVelocity < 0 ? 1 : 0; - float minFlingVelocity = res.getDimension(R.dimen.quickstep_fling_min_velocity); + float minFlingVelocity = mContext.getResources() + .getDimension(R.dimen.quickstep_fling_min_velocity); if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) { float distanceToTravel = (endShift - mCurrentShift.value) * mTransitionDragLength; // we want the page's snap velocity to approximately match the velocity at // which the user flings, so we scale the duration by a value near to the - // derivative of the scroll interpolator at zero, ie. 5. - duration = 5 * Math.round(1000 * Math.abs(distanceToTravel / endVelocity)); + // derivative of the scroll interpolator at zero, ie. 2. + long baseDuration = Math.round(1000 * Math.abs(distanceToTravel / endVelocity)); + duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration); } - mLogAction = Touch.FLING; } - animateToProgress(endShift, duration); + animateToProgress(endShift, duration, DEACCEL); } private void doLogGesture(boolean toLauncher) { @@ -571,24 +645,31 @@ public class WindowTransformSwipeHandler { } /** Animates to the given progress, where 0 is the current app and 1 is overview. */ - private void animateToProgress(float progress, long duration) { + private void animateToProgress(float progress, long duration, Interpolator interpolator) { mIsGoingToHome = Float.compare(progress, 1) == 0; ObjectAnimator anim = mCurrentShift.animateToValue(progress).setDuration(duration); - anim.setInterpolator(Interpolators.SCROLL); + anim.setInterpolator(interpolator); anim.addListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { - setStateOnUiThread(mIsGoingToHome ? - STATE_SCALED_CONTROLLER_RECENTS : STATE_SCALED_CONTROLLER_APP); + setStateOnUiThread(mIsGoingToHome + ? (STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT) + : STATE_SCALED_CONTROLLER_APP); } }); anim.start(); } + @UiThread + private void resumeLastTaskForQuickstep() { + setStateOnUiThread(STATE_RESUME_LAST_TASK); + doLogGesture(false /* toLauncher */); + reset(); + } + @UiThread private void resumeLastTask() { mRecentsAnimationWrapper.finish(false /* toHome */, null); - doLogGesture(false /* toLauncher */); } public void reset() { @@ -608,13 +689,20 @@ public class WindowTransformSwipeHandler { mActivityInitListener.unregister(); mInputConsumer.unregisterInputConsumer(); + mTaskSnapshot = null; } private void invalidateHandlerWithLauncher() { mLauncherTransitionController = null; mLayoutListener.finish(); + mActivityControlHelper.getAlphaProperty(mActivity).setValue(1); - mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, false /* animate */); + mRecentsView.setRunningTaskHidden(false); + mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, false /* animate */); + } + + private void notifyTransitionCancelled() { + mAnimationFactory.onTransitionCancelled(); } private void resetStateForAnimationCancel() { @@ -630,40 +718,38 @@ public class WindowTransformSwipeHandler { private void switchToScreenshot() { boolean finishTransitionPosted = false; - final Runnable finishTransitionRunnable = () -> { - synchronized (mRecentsAnimationWrapper) { - mRecentsAnimationWrapper.finish(true /* toHome */, - () -> setStateOnUiThread(STATE_SWITCH_TO_SCREENSHOT_COMPLETE)); + RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController(); + if (controller != null) { + // Update the screenshot of the task + if (mTaskSnapshot == null) { + mTaskSnapshot = controller.screenshotTask(mRunningTaskId); } - }; + TaskView taskView = mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot); + mRecentsView.setRunningTaskHidden(false); + if (taskView != null) { + // Defer finishing the animation until the next launcher frame with the + // new thumbnail + finishTransitionPosted = new WindowCallbacksCompat(taskView) { - synchronized (mRecentsAnimationWrapper) { - if (mRecentsAnimationWrapper.controller != null) { - TransactionCompat transaction = new TransactionCompat(); - for (RemoteAnimationTargetCompat app : mRecentsAnimationWrapper.targets) { - if (app.mode == MODE_CLOSING) { - // Update the screenshot of the task - ThumbnailData thumbnail = - mRecentsAnimationWrapper.controller.screenshotTask(app.taskId); - TaskView taskView = mRecentsView.updateThumbnail(app.taskId, thumbnail); - if (taskView != null) { - taskView.setAlpha(1); - // Defer finishing the animation until the next launcher frame with the - // new thumbnail - mActivityControlHelper.executeOnNextDraw(mActivity, taskView, - finishTransitionRunnable); - finishTransitionPosted = true; - } + @Override + public void onPostDraw(Canvas canvas) { + setStateOnUiThread(STATE_SCREENSHOT_CAPTURED); + detach(); } - } - transaction.apply(); + }.attach(); } } if (!finishTransitionPosted) { - // If we haven't posted the transition end runnable, run it now - finishTransitionRunnable.run(); + // If we haven't posted a draw callback, set the state immediately. + setStateOnUiThread(STATE_SCREENSHOT_CAPTURED); + } + } + + private void finishCurrentTransitionToHome() { + synchronized (mRecentsAnimationWrapper) { + mRecentsAnimationWrapper.finish(true /* toHome */, + () -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED)); } - doLogGesture(true /* toLauncher */); } private void setupLauncherUiAfterSwipeUpAnimation() { @@ -674,27 +760,64 @@ public class WindowTransformSwipeHandler { mActivityControlHelper.onSwipeUpComplete(mActivity); // Animate the first icon. - mRecentsView.setFirstTaskIconScaledDown(false /* isScaledDown */, true /* animate */); - + mRecentsView.setRunningTaskIconScaledDown(false /* isScaledDown */, true /* animate */); mRecentsView.setSwipeDownShouldLaunchApp(true); + RecentsModel.getInstance(mContext).onOverviewShown(false, TAG); + + doLogGesture(true /* toLauncher */); reset(); } private void onQuickScrubStart() { - mActivityControlHelper.onQuickInteractionStart(mActivity, mWasLauncherAlreadyVisible); - mQuickScrubController.onQuickScrubStart(false); + if (!mQuickScrubController.prepareQuickScrub(TAG)) { + mQuickScrubBlocked = true; + setStateOnUiThread(STATE_RESUME_LAST_TASK | STATE_HANDLER_INVALIDATED); + return; + } + if (mLauncherTransitionController != null) { + mLauncherTransitionController.getAnimationPlayer().end(); + mLauncherTransitionController = null; + } + + mActivityControlHelper.onQuickInteractionStart(mActivity, mRunningTaskInfo, false); + + // Inform the last progress in case we skipped before. + mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress); + + // Make sure the window follows the first task if it moves, e.g. during quick scrub. + TaskView firstTask = mRecentsView.getPageAt(0); + // The first task may be null if we are swiping up from a task that does not + // appear in the list (i.e. the assistant) + if (firstTask != null) { + int scrollForFirstTask = mRecentsView.getScrollForPage(0); + int scrollForSecondTask = mRecentsView.getChildCount() > 1 + ? mRecentsView.getScrollForPage(1) : scrollForFirstTask; + int offsetFromFirstTask = scrollForFirstTask - scrollForSecondTask; + final float interpolation; + if (mRecentsView.getWidth() == 0) { + interpolation = scrollForSecondTask == scrollForFirstTask ? 0 : 1; + } else { + interpolation = (float) offsetFromFirstTask / (mRecentsView.getWidth() / 2); + } + mClipAnimationHelper.offsetTarget( + firstTask.getCurveScaleForInterpolation(interpolation), offsetFromFirstTask, + mActivityControlHelper.getTranslationYForQuickScrub(mActivity), + QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR); + } } private void onFinishedTransitionToQuickScrub() { + if (mQuickScrubBlocked) { + return; + } mQuickScrubController.onFinishedTransitionToQuickScrub(); } public void onQuickScrubProgress(float progress) { - if (Looper.myLooper() != Looper.getMainLooper() || mQuickScrubController == null) { - // TODO: We can still get progress events while launcher is not ready on the worker - // thread. Keep track of last received progress and apply that progress when launcher - // is ready + mCurrentQuickScrubProgress = progress; + if (Looper.myLooper() != Looper.getMainLooper() || mQuickScrubController == null + || mQuickScrubBlocked) { return; } mQuickScrubController.onQuickScrubProgress(progress); @@ -705,6 +828,9 @@ public class WindowTransformSwipeHandler { } private void switchToFinalAppAfterQuickScrub() { + if (mQuickScrubBlocked) { + return; + } mQuickScrubController.onQuickScrubEnd(); // Normally this is handled in reset(), but since we are still scrubbing after the @@ -736,4 +862,72 @@ public class WindowTransformSwipeHandler { public void setGestureEndCallback(Runnable gestureEndCallback) { mGestureEndCallback = gestureEndCallback; } + + // Handling long swipe + private void onLongSwipeEnabledUi() { + mUiLongSwipeMode = true; + checkLongSwipeCanEnter(); + checkLongSwipeCanStart(); + } + + private void onLongSwipeDisabledUi() { + mUiLongSwipeMode = false; + + if (mLongSwipeController != null) { + mLongSwipeController.destroy(); + + // Rebuild animations + buildAnimationController(); + } + } + + private void onLongSwipeDisplacementUpdated() { + if (!mUiLongSwipeMode || mLongSwipeController == null) { + return; + } + + mLongSwipeController.onMove(mLongSwipeDisplacement); + } + + private void checkLongSwipeCanEnter() { + if (!mUiLongSwipeMode || !mStateCallback.hasStates(LONG_SWIPE_ENTER_STATE) + || !mActivityControlHelper.supportsLongSwipe(mActivity)) { + return; + } + + // We are entering long swipe mode, make sure the screen shot is captured. + mStateCallback.setState(STATE_CAPTURE_SCREENSHOT); + + } + + private void checkLongSwipeCanStart() { + if (!mUiLongSwipeMode || !mStateCallback.hasStates(LONG_SWIPE_START_STATE) + || !mActivityControlHelper.supportsLongSwipe(mActivity)) { + return; + } + + RemoteAnimationTargetSet targetSet = mRecentsAnimationWrapper.targetSet; + if (targetSet == null) { + // This can happen when cancelAnimation comes on the background thread, while we are + // processing the long swipe on the UI thread. + return; + } + + mLongSwipeController = mActivityControlHelper.getLongSwipeController( + mActivity, mRecentsAnimationWrapper.targetSet); + onLongSwipeDisplacementUpdated(); + } + + private void onLongSwipeGestureFinishUi(float velocity, boolean isFling) { + if (!mUiLongSwipeMode || mLongSwipeController == null) { + mUiLongSwipeMode = false; + handleNormalGestureEnd(velocity, isFling); + return; + } + mUiLongSwipeMode = false; + finishCurrentTransitionToHome(); + mLongSwipeController.end(velocity, isFling, + () -> setStateOnUiThread(STATE_HANDLER_INVALIDATED)); + + } } diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java index 4ed165699e..9e2de33954 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -18,7 +18,6 @@ package com.android.quickstep.fallback; import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; -import android.support.annotation.AnyThread; import android.util.AttributeSet; import android.view.View; @@ -36,12 +35,12 @@ public class FallbackRecentsView extends RecentsView { public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setOverviewStateEnabled(true); - updateEmptyMessage(); + getQuickScrubController().onFinishedTransitionToQuickScrub(); } @Override protected void onAllTasksRemoved() { - mActivity.finish(); + mActivity.startHome(); } @Override @@ -64,11 +63,12 @@ public class FallbackRecentsView extends RecentsView { @Override protected void getTaskSize(DeviceProfile dp, Rect outRect) { - LayoutUtils.calculateTaskSize(getContext(), dp, 0, outRect); + LayoutUtils.calculateFallbackTaskSize(getContext(), dp, outRect); } - @AnyThread - public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) { - LayoutUtils.calculateTaskSize(context, grid, 0, outRect); + @Override + public boolean shouldUseMultiWindowTaskSizeStrategy() { + // Just use the activity task size for multi-window as well. + return false; } } diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java b/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java index 7aaa88c38d..ca8c2520c4 100644 --- a/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java +++ b/quickstep/src/com/android/quickstep/fallback/RecentsRootView.java @@ -17,6 +17,7 @@ package com.android.quickstep.fallback; import android.annotation.TargetApi; import android.content.Context; +import android.graphics.Point; import android.graphics.Rect; import android.util.AttributeSet; @@ -31,18 +32,37 @@ public class RecentsRootView extends BaseDragLayer { private final RecentsActivity mActivity; + private final Point mLastKnownSize = new Point(10, 10); + public RecentsRootView(Context context, AttributeSet attrs) { - super(context, attrs); + super(context, attrs, 1 /* alphaChannelCount */); mActivity = (RecentsActivity) BaseActivity.fromContext(context); setSystemUiVisibility(SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | SYSTEM_UI_FLAG_LAYOUT_STABLE); } + public Point getLastKnownSize() { + return mLastKnownSize; + } + public void setup() { mControllers = new TouchController[] { new RecentsTaskController(mActivity) }; } + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Check size changes before the actual measure, to avoid multiple measure calls. + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + if (mLastKnownSize.x != width || mLastKnownSize.y != height) { + mLastKnownSize.set(width, height); + mActivity.onRootViewSizeChanged(); + } + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + @TargetApi(23) @Override protected boolean fitSystemWindows(Rect insets) { @@ -62,4 +82,9 @@ public class RecentsRootView extends BaseDragLayer { setBackground(insets.top == 0 ? null : Themes.getAttrDrawable(getContext(), R.attr.workspaceStatusBarScrim)); } + + public void dispatchInsets() { + mActivity.getDeviceProfile().updateInsets(mInsets); + super.setInsets(mInsets); + } } \ No newline at end of file diff --git a/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java new file mode 100644 index 0000000000..04153cc99e --- /dev/null +++ b/quickstep/src/com/android/quickstep/logging/UserEventDispatcherExtension.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.logging; + +import android.util.Log; + +import static com.android.launcher3.logging.LoggerUtils.newAction; +import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; +import static com.android.launcher3.logging.LoggerUtils.newLauncherEvent; +import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CANCEL_TARGET; +import static com.android.systemui.shared.system.LauncherEventUtil.VISIBLE; +import static com.android.systemui.shared.system.LauncherEventUtil.DISMISS; +import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_QUICK_SCRUB_ONBOARDING_TIP; +import static com.android.systemui.shared.system.LauncherEventUtil.RECENTS_SWIPE_UP_ONBOARDING_TIP; + +import com.android.launcher3.logging.UserEventDispatcher; +import com.android.launcher3.model.nano.LauncherDumpProto; +import com.android.launcher3.userevent.nano.LauncherLogExtensions; +import com.android.launcher3.userevent.nano.LauncherLogProto; +import com.android.systemui.shared.system.LauncherEventUtil; +import com.android.systemui.shared.system.MetricsLoggerCompat; + +/** + * This class handles AOSP MetricsLogger function calls and logging around + * quickstep interactions. + */ +public class UserEventDispatcherExtension extends UserEventDispatcher { + + private static final String TAG = "UserEventDispatcher"; + + public void logStateChangeAction(int action, int dir, int srcChildTargetType, + int srcParentContainerType, int dstContainerType, + int pageIndex) { + new MetricsLoggerCompat().visibility(MetricsLoggerCompat.OVERVIEW_ACTIVITY, + dstContainerType == LauncherLogProto.ContainerType.TASKSWITCHER); + super.logStateChangeAction(action, dir, srcChildTargetType, srcParentContainerType, + dstContainerType, pageIndex); + } + + public void logActionTip(int actionType, int viewType) { + LauncherLogProto.Action action = new LauncherLogProto.Action(); + LauncherLogProto.Target target = new LauncherLogProto.Target(); + switch(actionType) { + case VISIBLE: + action.type = LauncherLogProto.Action.Type.TIP; + target.type = LauncherLogProto.Target.Type.CONTAINER; + target.containerType = LauncherLogProto.ContainerType.TIP; + break; + case DISMISS: + action.type = LauncherLogProto.Action.Type.TOUCH; + action.touch = LauncherLogProto.Action.Touch.TAP; + target.type = LauncherLogProto.Target.Type.CONTROL; + target.controlType = CANCEL_TARGET; + break; + default: + Log.e(TAG, "Unexpected action type = " + actionType); + } + + switch(viewType) { + case RECENTS_QUICK_SCRUB_ONBOARDING_TIP: + target.tipType = LauncherLogProto.TipType.QUICK_SCRUB_TEXT; + break; + case RECENTS_SWIPE_UP_ONBOARDING_TIP: + target.tipType = LauncherLogProto.TipType.SWIPE_UP_TEXT; + break; + default: + Log.e(TAG, "Unexpected viewType = " + viewType); + } + LauncherLogProto.LauncherEvent event = newLauncherEvent(action, target); + dispatchUserEvent(event, null); + } +} diff --git a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java index 493e9e2386..8c7f104a64 100644 --- a/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java +++ b/quickstep/src/com/android/quickstep/util/ClipAnimationHelper.java @@ -15,21 +15,44 @@ */ package com.android.quickstep.util; +import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; +import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; +import android.annotation.TargetApi; +import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Matrix.ScaleToFit; +import android.graphics.PointF; import android.graphics.Rect; import android.graphics.RectF; +import android.os.Build; +import android.os.RemoteException; +import android.support.annotation.Nullable; +import android.view.animation.Interpolator; +import com.android.launcher3.BaseDraggingActivity; +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.R; import com.android.launcher3.Utilities; +import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.views.BaseDragLayer; +import com.android.quickstep.RecentsModel; +import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.TaskThumbnailView; +import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.recents.utilities.RectFEvaluator; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.TransactionCompat; +import com.android.systemui.shared.system.WindowManagerWrapper; + +import java.util.function.BiConsumer; /** * Utility class to handle window clip animation */ +@TargetApi(Build.VERSION_CODES.P) public class ClipAnimationHelper { // The bounds of the source app in device coordinates @@ -40,8 +63,8 @@ public class ClipAnimationHelper { private final RectF mSourceRect = new RectF(); // The bounds of the task view in launcher window coordinates private final RectF mTargetRect = new RectF(); - // Doesn't change after initialized, used as an anchor when changing mTargetRect - private final RectF mInitialTargetRect = new RectF(); + // Set when the final window destination is changed, such as offsetting for quick scrub + private final PointF mTargetOffset = new PointF(); // The insets to be used for clipping the app window, which can be larger than mSourceInsets // if the aspect ratio of the target is smaller than the aspect ratio of the source rect. In // app window coordinates. @@ -54,15 +77,33 @@ public class ClipAnimationHelper { private final Rect mClipRect = new Rect(); private final RectFEvaluator mRectFEvaluator = new RectFEvaluator(); private final Matrix mTmpMatrix = new Matrix(); + private final RectF mTmpRectF = new RectF(); + private float mTargetScale = 1f; + private Interpolator mInterpolator = LINEAR; + // We translate y slightly faster than the rest of the animation for quick scrub. + private Interpolator mOffsetYInterpolator = LINEAR; - public void updateSource(Rect homeStackBounds, RemoteAnimationTargetCompat target) { - mHomeStackBounds.set(homeStackBounds); - mSourceInsets.set(target.getContentInsets()); + // Whether to boost the opening animation target layers, or the closing + private int mBoostModeTargetLayers = -1; + // Wether or not applyTransform has been called yet since prepareAnimation() + private boolean mIsFirstFrame = true; + + private BiConsumer mTaskTransformCallback = + (t, a) -> { }; + + private void updateSourceStack(RemoteAnimationTargetCompat target) { + mSourceInsets.set(target.contentInsets); mSourceStackBounds.set(target.sourceContainerBounds); // TODO: Should sourceContainerBounds already have this offset? mSourceStackBounds.offsetTo(target.position.x, target.position.y); + + } + + public void updateSource(Rect homeStackBounds, RemoteAnimationTargetCompat target) { + mHomeStackBounds.set(homeStackBounds); + updateSourceStack(target); } public void updateTargetRect(Rect targetRect) { @@ -73,8 +114,6 @@ public class ClipAnimationHelper { mTargetRect.offset(mHomeStackBounds.left - mSourceStackBounds.left, mHomeStackBounds.top - mSourceStackBounds.top); - mInitialTargetRect.set(mTargetRect); - // Calculate the clip based on the target rect (since the content insets and the // launcher insets may differ, so the aspect ratio of the target rect can differ // from the source rect. The difference between the target rect (scaled to the @@ -91,12 +130,22 @@ public class ClipAnimationHelper { mSourceRect.set(scaledTargetRect); } - public void applyTransform(RemoteAnimationTargetCompat[] targets, float progress) { + public void prepareAnimation(boolean isOpening) { + mIsFirstFrame = true; + mBoostModeTargetLayers = isOpening ? MODE_OPENING : MODE_CLOSING; + } + + public RectF applyTransform(RemoteAnimationTargetSet targetSet, float progress) { RectF currentRect; - synchronized (mTargetRect) { - currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect); + mTmpRectF.set(mTargetRect); + Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale); + float offsetYProgress = mOffsetYInterpolator.getInterpolation(progress); + progress = mInterpolator.getInterpolation(progress); + currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF); + + synchronized (mTargetOffset) { // Stay lined up with the center of the target, since it moves for quick scrub. - currentRect.offset(mTargetRect.centerX() - currentRect.centerX(), 0); + currentRect.offset(mTargetOffset.x * progress, mTargetOffset.y * offsetYProgress); } mClipRect.left = (int) (mSourceWindowClipInsets.left * progress); @@ -106,30 +155,140 @@ public class ClipAnimationHelper { mClipRect.bottom = (int) (mSourceStackBounds.height() - (mSourceWindowClipInsets.bottom * progress)); - mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL); - TransactionCompat transaction = new TransactionCompat(); - for (RemoteAnimationTargetCompat app : targets) { - if (app.mode == MODE_CLOSING) { + if (mIsFirstFrame) { + RemoteAnimationProvider.prepareTargetsForFirstFrame(targetSet.unfilteredApps, + transaction, mBoostModeTargetLayers); + mIsFirstFrame = false; + } + for (RemoteAnimationTargetCompat app : targetSet.apps) { + if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) { + mTmpMatrix.setRectToRect(mSourceRect, currentRect, ScaleToFit.FILL); mTmpMatrix.postTranslate(app.position.x, app.position.y); transaction.setMatrix(app.leash, mTmpMatrix) .setWindowCrop(app.leash, mClipRect); - if (app.isNotInRecents) { - transaction.setAlpha(app.leash, 1 - progress); - } - - transaction.show(app.leash); } + + if (app.isNotInRecents + || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) { + transaction.setAlpha(app.leash, 1 - progress); + } + + mTaskTransformCallback.accept(transaction, app); } transaction.setEarlyWakeup(); transaction.apply(); + return currentRect; } - public void offsetTarget(float scale, float offsetX, float offsetY) { - synchronized (mTargetRect) { - mTargetRect.set(mInitialTargetRect); - Utilities.scaleRectFAboutCenter(mTargetRect, scale); - mTargetRect.offset(offsetX, offsetY); + public void setTaskTransformCallback + (BiConsumer callback) { + mTaskTransformCallback = callback; + } + + public void offsetTarget(float scale, float offsetX, float offsetY, Interpolator interpolator) { + synchronized (mTargetOffset) { + mTargetOffset.set(offsetX, offsetY); } + mTargetScale = scale; + mInterpolator = interpolator; + mOffsetYInterpolator = Interpolators.clampToProgress(mInterpolator, 0, + QUICK_SCRUB_TRANSLATION_Y_FACTOR); + } + + public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv) { + fromTaskThumbnailView(ttv, rv, null); + } + + public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv, + @Nullable RemoteAnimationTargetCompat target) { + BaseDraggingActivity activity = BaseDraggingActivity.fromContext(ttv.getContext()); + BaseDragLayer dl = activity.getDragLayer(); + + int[] pos = new int[2]; + dl.getLocationOnScreen(pos); + mHomeStackBounds.set(0, 0, dl.getWidth(), dl.getHeight()); + mHomeStackBounds.offset(pos[0], pos[1]); + + if (target != null) { + updateSourceStack(target); + } else if (rv.shouldUseMultiWindowTaskSizeStrategy()) { + updateStackBoundsToMultiWindowTaskSize(activity); + } else { + mSourceStackBounds.set(mHomeStackBounds); + mSourceInsets.set(activity.getDeviceProfile().getInsets()); + } + + Rect targetRect = new Rect(); + dl.getDescendantRectRelativeToSelf(ttv, targetRect); + updateTargetRect(targetRect); + + // Transform the clip relative to the target rect. + float scale = mTargetRect.width() / mSourceRect.width(); + mSourceWindowClipInsets.left = mSourceWindowClipInsets.left * scale; + mSourceWindowClipInsets.top = mSourceWindowClipInsets.top * scale; + mSourceWindowClipInsets.right = mSourceWindowClipInsets.right * scale; + mSourceWindowClipInsets.bottom = mSourceWindowClipInsets.bottom * scale; + } + + private void updateStackBoundsToMultiWindowTaskSize(BaseDraggingActivity activity) { + ISystemUiProxy sysUiProxy = RecentsModel.getInstance(activity).getSystemUiProxy(); + if (sysUiProxy != null) { + try { + mSourceStackBounds.set(sysUiProxy.getNonMinimizedSplitScreenSecondaryBounds()); + return; + } catch (RemoteException e) { + // Use half screen size + } + } + + // Assume that the task size is half screen size (minus the insets and the divider size) + DeviceProfile fullDp = activity.getDeviceProfile().getFullScreenProfile(); + // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to + // account for system insets + int taskWidth = fullDp.availableWidthPx; + int taskHeight = fullDp.availableHeightPx; + int halfDividerSize = activity.getResources() + .getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2; + + Rect insets = new Rect(); + WindowManagerWrapper.getInstance().getStableInsets(insets); + if (fullDp.isLandscape) { + taskWidth = taskWidth / 2 - halfDividerSize; + } else { + taskHeight = taskHeight / 2 - halfDividerSize; + } + + // Align the task to bottom left/right edge (closer to nav bar). + int left = activity.getDeviceProfile().isSeascape() ? insets.left + : (insets.left + fullDp.availableWidthPx - taskWidth); + mSourceStackBounds.set(0, 0, taskWidth, taskHeight); + mSourceStackBounds.offset(left, insets.top + fullDp.availableHeightPx - taskHeight); + } + + public void drawForProgress(TaskThumbnailView ttv, Canvas canvas, float progress) { + RectF currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect); + canvas.translate(mSourceStackBounds.left - mHomeStackBounds.left, + mSourceStackBounds.top - mHomeStackBounds.top); + mTmpMatrix.setRectToRect(mTargetRect, currentRect, ScaleToFit.FILL); + + canvas.concat(mTmpMatrix); + canvas.translate(mTargetRect.left, mTargetRect.top); + + float insetProgress = (1 - progress); + ttv.drawOnCanvas(canvas, + -mSourceWindowClipInsets.left * insetProgress, + -mSourceWindowClipInsets.top * insetProgress, + ttv.getMeasuredWidth() + mSourceWindowClipInsets.right * insetProgress, + ttv.getMeasuredHeight() + mSourceWindowClipInsets.bottom * insetProgress, + ttv.getCornerRadius() * progress); + } + + public RectF getTargetRect() { + return mTargetRect; + } + + public RectF getSourceRect() { + return mSourceRect; } } diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java index f29f9e4e92..ec9c7eaed9 100644 --- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java +++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java @@ -15,39 +15,68 @@ */ package com.android.quickstep.util; +import static java.lang.annotation.RetentionPolicy.SOURCE; + import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; -import android.graphics.RectF; +import android.support.annotation.AnyThread; +import android.support.annotation.IntDef; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; +import java.lang.annotation.Retention; + public class LayoutUtils { + private static final int MULTI_WINDOW_STRATEGY_HALF_SCREEN = 1; + private static final int MULTI_WINDOW_STRATEGY_DEVICE_PROFILE = 2; + + @Retention(SOURCE) + @IntDef({MULTI_WINDOW_STRATEGY_HALF_SCREEN, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE}) + private @interface MultiWindowStrategy {} + public static void calculateLauncherTaskSize(Context context, DeviceProfile dp, Rect outRect) { - float extraSpace = dp.isVerticalBarLayout() ? 0 : dp.hotseatBarSizePx; - calculateTaskSize(context, dp, extraSpace, outRect); + float extraSpace; + if (dp.isVerticalBarLayout()) { + extraSpace = 0; + } else { + extraSpace = dp.hotseatBarSizePx + dp.verticalDragHandleSizePx; + } + calculateTaskSize(context, dp, extraSpace, MULTI_WINDOW_STRATEGY_HALF_SCREEN, outRect); } + public static void calculateFallbackTaskSize(Context context, DeviceProfile dp, Rect outRect) { + calculateTaskSize(context, dp, 0, MULTI_WINDOW_STRATEGY_DEVICE_PROFILE, outRect); + } + + @AnyThread public static void calculateTaskSize(Context context, DeviceProfile dp, - float extraVerticalSpace, Rect outRect) { + float extraVerticalSpace, @MultiWindowStrategy int multiWindowStrategy, Rect outRect) { float taskWidth, taskHeight, paddingHorz; Resources res = context.getResources(); Rect insets = dp.getInsets(); if (dp.isMultiWindowMode) { - DeviceProfile fullDp = dp.getFullScreenProfile(); - // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to - // account for system insets - taskWidth = fullDp.availableWidthPx; - taskHeight = fullDp.availableHeightPx; - float halfDividerSize = res.getDimension(R.dimen.multi_window_task_divider_size) / 2; + if (multiWindowStrategy == MULTI_WINDOW_STRATEGY_HALF_SCREEN) { + DeviceProfile fullDp = dp.getFullScreenProfile(); + // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to + // account for system insets + taskWidth = fullDp.availableWidthPx; + taskHeight = fullDp.availableHeightPx; + float halfDividerSize = res.getDimension(R.dimen.multi_window_task_divider_size) + / 2; - if (fullDp.isLandscape) { - taskWidth = taskWidth / 2 - halfDividerSize; + if (fullDp.isLandscape) { + taskWidth = taskWidth / 2 - halfDividerSize; + } else { + taskHeight = taskHeight / 2 - halfDividerSize; + } } else { - taskHeight = taskHeight / 2 - halfDividerSize; + // multiWindowStrategy == MULTI_WINDOW_STRATEGY_DEVICE_PROFILE + taskWidth = dp.widthPx; + taskHeight = dp.heightPx; } paddingHorz = res.getDimension(R.dimen.multi_window_task_card_horz_space); } else { @@ -75,7 +104,7 @@ public class LayoutUtils { float outHeight = scale * taskHeight; // Center in the visible space - float x = insets.left + (taskWidth - outWidth) / 2; + float x = insets.left + (launcherVisibleWidth - outWidth) / 2; float y = insets.top + Math.max(topIconMargin, (launcherVisibleHeight - extraVerticalSpace - outHeight) / 2); outRect.set(Math.round(x), Math.round(y), diff --git a/quickstep/src/com/android/quickstep/util/MultiValueUpdateListener.java b/quickstep/src/com/android/quickstep/util/MultiValueUpdateListener.java new file mode 100644 index 0000000000..e798d5cbcc --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/MultiValueUpdateListener.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.util; + +import android.animation.ValueAnimator; +import android.view.animation.Interpolator; + +import java.util.ArrayList; + +/** + * Utility class to update multiple values with different interpolators and durations during + * the same animation. + */ +public abstract class MultiValueUpdateListener implements ValueAnimator.AnimatorUpdateListener { + + private final ArrayList mAllProperties = new ArrayList<>(); + + @Override + public final void onAnimationUpdate(ValueAnimator animator) { + final float percent = animator.getAnimatedFraction(); + final float currentPlayTime = percent * animator.getDuration(); + + for (int i = mAllProperties.size() - 1; i >= 0; i--) { + FloatProp prop = mAllProperties.get(i); + float time = Math.max(0, currentPlayTime - prop.mDelay); + float newPercent = Math.min(1f, time / prop.mDuration); + newPercent = prop.mInterpolator.getInterpolation(newPercent); + prop.value = prop.mEnd * newPercent + prop.mStart * (1 - newPercent); + } + onUpdate(percent); + } + + public abstract void onUpdate(float percent); + + public final class FloatProp { + + public float value; + + private final float mStart; + private final float mEnd; + private final float mDelay; + private final float mDuration; + private final Interpolator mInterpolator; + + public FloatProp(float start, float end, float delay, float duration, Interpolator i) { + value = mStart = start; + mEnd = end; + mDelay = delay; + mDuration = duration; + mInterpolator = i; + + mAllProperties.add(this); + } + } +} diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java index 2ffcae38ef..bbf223d1ef 100644 --- a/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java +++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationProvider.java @@ -31,25 +31,34 @@ public interface RemoteAnimationProvider { AnimatorSet createWindowAnimation(RemoteAnimationTargetCompat[] targets); default ActivityOptions toActivityOptions(Handler handler, long duration) { - LauncherAnimationRunner runner = new LauncherAnimationRunner(handler) { + LauncherAnimationRunner runner = new LauncherAnimationRunner(handler, + false /* startAtFrontOfQueue */) { + @Override - public AnimatorSet getAnimator(RemoteAnimationTargetCompat[] targetCompats) { - return createWindowAnimation(targetCompats); + public void onCreateAnimation(RemoteAnimationTargetCompat[] targetCompats, + AnimationResult result) { + result.setAnimation(createWindowAnimation(targetCompats)); } }; return ActivityOptionsCompat.makeRemoteAnimation( new RemoteAnimationAdapterCompat(runner, duration, 0)); } - static void showOpeningTarget(RemoteAnimationTargetCompat[] targetCompats) { - TransactionCompat t = new TransactionCompat(); - for (RemoteAnimationTargetCompat target : targetCompats) { - int layer = target.mode == RemoteAnimationTargetCompat.MODE_CLOSING + /** + * Prepares the given {@param targets} for a remote animation, and should be called with the + * transaction from the first frame of animation. + * + * @param boostModeTargets The mode indicating which targets to boost in z-order above other + * targets. + */ + static void prepareTargetsForFirstFrame(RemoteAnimationTargetCompat[] targets, + TransactionCompat t, int boostModeTargets) { + for (RemoteAnimationTargetCompat target : targets) { + int layer = target.mode == boostModeTargets ? Integer.MAX_VALUE : target.prefixOrderIndex; t.setLayer(target.leash, layer); t.show(target.leash); } - t.apply(); } } diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java new file mode 100644 index 0000000000..04b8be58bf --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargetSet.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.util; + +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; + +import java.util.ArrayList; + +/** + * Holds a collection of RemoteAnimationTargets, filtered by different properties. + */ +public class RemoteAnimationTargetSet { + + public final RemoteAnimationTargetCompat[] unfilteredApps; + public final RemoteAnimationTargetCompat[] apps; + + public RemoteAnimationTargetSet(RemoteAnimationTargetCompat[] apps, int targetMode) { + ArrayList filteredApps = new ArrayList<>(); + if (apps != null) { + for (RemoteAnimationTargetCompat target : apps) { + if (target.mode == targetMode) { + filteredApps.add(target); + } + } + } + + this.unfilteredApps = apps; + this.apps = filteredApps.toArray(new RemoteAnimationTargetCompat[filteredApps.size()]); + } + + public RemoteAnimationTargetCompat findTask(int taskId) { + for (RemoteAnimationTargetCompat target : apps) { + if (target.taskId == taskId) { + return target; + } + } + return null; + } + + public boolean isAnimatingHome() { + for (RemoteAnimationTargetCompat target : apps) { + if (target.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) { + return true; + } + } + return false; + } +} diff --git a/quickstep/src/com/android/quickstep/util/SysuiEventLogger.java b/quickstep/src/com/android/quickstep/util/SysuiEventLogger.java deleted file mode 100644 index d474ded905..0000000000 --- a/quickstep/src/com/android/quickstep/util/SysuiEventLogger.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.quickstep.util; - -import android.metrics.LogMaker; -import android.util.EventLog; - -/** - * Utility class for writing logs on behalf of systemUI - */ -public class SysuiEventLogger { - - /** 524292 sysui_multi_action (content|4) */ - public static final int SYSUI_MULTI_ACTION = 524292; - - private static void write(LogMaker content) { - if (content.getType() == 0/*MetricsEvent.TYPE_UNKNOWN*/) { - content.setType(4/*MetricsEvent.TYPE_ACTION*/); - } - EventLog.writeEvent(SYSUI_MULTI_ACTION, content.serialize()); - } - - public static void writeDummyRecentsTransition(long transitionDelay) { - // Mimic ActivityMetricsLogger.logAppTransitionMultiEvents() logging for - // "Recents" activity for app transition tests for the app-to-recents case. - final LogMaker builder = new LogMaker(761/*APP_TRANSITION*/); - builder.setPackageName("com.android.systemui"); - builder.addTaggedData(871/*FIELD_CLASS_NAME*/, - "com.android.systemui.recents.RecentsActivity"); - builder.addTaggedData(319/*APP_TRANSITION_DELAY_MS*/, - transitionDelay); - write(builder); - } -} diff --git a/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java b/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java new file mode 100644 index 0000000000..48b07a7144 --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/TaskViewDrawable.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.util; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ValueAnimator; +import android.graphics.Canvas; +import android.graphics.ColorFilter; +import android.graphics.PixelFormat; +import android.graphics.drawable.Drawable; +import android.util.FloatProperty; +import android.view.View; + +import com.android.launcher3.Utilities; +import com.android.quickstep.views.RecentsView; +import com.android.quickstep.views.TaskThumbnailView; +import com.android.quickstep.views.TaskView; + +public class TaskViewDrawable extends Drawable { + + public static final FloatProperty PROGRESS = + new FloatProperty("progress") { + @Override + public void setValue(TaskViewDrawable taskViewDrawable, float v) { + taskViewDrawable.setProgress(v); + } + + @Override + public Float get(TaskViewDrawable taskViewDrawable) { + return taskViewDrawable.mProgress; + } + }; + + /** + * The progress at which we play the atomic icon scale animation. + */ + private static final float ICON_SCALE_THRESHOLD = 0.95f; + + private final RecentsView mParent; + private final View mIconView; + private final int[] mIconPos; + + private final TaskThumbnailView mThumbnailView; + + private final ClipAnimationHelper mClipAnimationHelper; + + private float mProgress = 1; + private boolean mPassedIconScaleThreshold; + private ValueAnimator mIconScaleAnimator; + private float mIconScale; + + public TaskViewDrawable(TaskView tv, RecentsView parent) { + mParent = parent; + mIconView = tv.getIconView(); + mIconPos = new int[2]; + mIconScale = mIconView.getScaleX(); + Utilities.getDescendantCoordRelativeToAncestor(mIconView, parent, mIconPos, true); + + mThumbnailView = tv.getThumbnail(); + mClipAnimationHelper = new ClipAnimationHelper(); + mClipAnimationHelper.fromTaskThumbnailView(mThumbnailView, parent); + } + + public void setProgress(float progress) { + mProgress = progress; + mParent.invalidate(); + boolean passedIconScaleThreshold = progress <= ICON_SCALE_THRESHOLD; + if (mPassedIconScaleThreshold != passedIconScaleThreshold) { + mPassedIconScaleThreshold = passedIconScaleThreshold; + animateIconScale(mPassedIconScaleThreshold ? 0 : 1); + } + } + + private void animateIconScale(float toScale) { + if (mIconScaleAnimator != null) { + mIconScaleAnimator.cancel(); + } + mIconScaleAnimator = ValueAnimator.ofFloat(mIconScale, toScale); + mIconScaleAnimator.addUpdateListener(valueAnimator -> { + mIconScale = (float) valueAnimator.getAnimatedValue(); + if (mProgress > ICON_SCALE_THRESHOLD) { + // Speed up the icon scale to ensure it is 1 when progress is 1. + float iconProgress = (mProgress - ICON_SCALE_THRESHOLD) / (1 - ICON_SCALE_THRESHOLD); + if (iconProgress > mIconScale) { + mIconScale = iconProgress; + } + } + invalidateSelf(); + }); + mIconScaleAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mIconScaleAnimator = null; + } + }); + mIconScaleAnimator.setDuration(TaskView.SCALE_ICON_DURATION); + mIconScaleAnimator.start(); + } + + @Override + public void draw(Canvas canvas) { + canvas.save(); + canvas.translate(mParent.getScrollX(), mParent.getScrollY()); + mClipAnimationHelper.drawForProgress(mThumbnailView, canvas, mProgress); + canvas.restore(); + + canvas.save(); + canvas.translate(mIconPos[0], mIconPos[1]); + canvas.scale(mIconScale, mIconScale, mIconView.getWidth() / 2, mIconView.getHeight() / 2); + mIconView.draw(canvas); + canvas.restore(); + } + + public ClipAnimationHelper getClipAnimationHelper() { + return mClipAnimationHelper; + } + + @Override + public void setAlpha(int i) { } + + @Override + public void setColorFilter(ColorFilter colorFilter) { } + + @Override + public int getOpacity() { + return PixelFormat.TRANSLUCENT; + } +} diff --git a/quickstep/src/com/android/quickstep/views/ClearAllButton.java b/quickstep/src/com/android/quickstep/views/ClearAllButton.java new file mode 100644 index 0000000000..d5c43a0f56 --- /dev/null +++ b/quickstep/src/com/android/quickstep/views/ClearAllButton.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.quickstep.views; + +import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.util.AttributeSet; +import android.widget.Button; + +public class ClearAllButton extends Button { + RecentsView mRecentsView; + + public ClearAllButton(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public void setRecentsView(RecentsView recentsView) { + mRecentsView = recentsView; + } + + @Override + public boolean performAccessibilityAction(int action, Bundle arguments) { + final boolean res = super.performAccessibilityAction(action, arguments); + if (action == ACTION_ACCESSIBILITY_FOCUS) { + mRecentsView.revealClearAllButton(); + } + return res; + } +} diff --git a/quickstep/src/com/android/quickstep/views/IconView.java b/quickstep/src/com/android/quickstep/views/IconView.java new file mode 100644 index 0000000000..c359966df4 --- /dev/null +++ b/quickstep/src/com/android/quickstep/views/IconView.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.views; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; + +/** + * A view which draws a drawable stretched to fit its size. Unlike ImageView, it avoids relayout + * when the drawable changes. + */ +public class IconView extends View { + + private Drawable mDrawable; + + public IconView(Context context) { + super(context); + } + + public IconView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public IconView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public void setDrawable(Drawable d) { + if (mDrawable != null) { + mDrawable.setCallback(null); + } + mDrawable = d; + if (mDrawable != null) { + mDrawable.setCallback(this); + mDrawable.setBounds(0, 0, getWidth(), getHeight()); + } + invalidate(); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + if (mDrawable != null) { + mDrawable.setBounds(0, 0, w, h); + } + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return super.verifyDrawable(who) || who == mDrawable; + } + + @Override + protected void drawableStateChanged() { + super.drawableStateChanged(); + + final Drawable drawable = mDrawable; + if (drawable != null && drawable.isStateful() + && drawable.setState(getDrawableState())) { + invalidateDrawable(drawable); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (mDrawable != null) { + mDrawable.draw(canvas); + } + } + + @Override + public boolean hasOverlappingRendering() { + return false; + } +} diff --git a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java index ac34d90b1d..c149de54f0 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java +++ b/quickstep/src/com/android/quickstep/views/LauncherLayoutListener.java @@ -54,7 +54,7 @@ public class LauncherLayoutListener extends AbstractFloatingView @Override public void setInsets(Rect insets) { if (mHandler != null) { - mHandler.onLauncherLayoutChanged(); + mHandler.buildAnimationController(); } } diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 4b4af3fa7e..950f7fb997 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -27,7 +27,6 @@ import android.content.Context; import android.graphics.Canvas; import android.graphics.Rect; import android.os.Build; -import android.support.annotation.AnyThread; import android.util.AttributeSet; import android.util.FloatProperty; import android.view.View; @@ -36,6 +35,8 @@ import android.view.ViewDebug; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; +import com.android.quickstep.OverviewInteractionState; +import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.LayoutUtils; /** @@ -87,7 +88,11 @@ public class LauncherRecentsView extends RecentsView { public void setTranslationYFactor(float translationFactor) { mTranslationYFactor = translationFactor; - setTranslationY(mTranslationYFactor * (getPaddingBottom() - getPaddingTop())); + setTranslationY(computeTranslationYForFactor(mTranslationYFactor)); + } + + public float computeTranslationYForFactor(float translationYFactor) { + return translationYFactor * (getPaddingBottom() - getPaddingTop()); } @Override @@ -112,8 +117,15 @@ public class LauncherRecentsView extends RecentsView { * Animates adjacent tasks and translate hotseat off screen as well. */ @Override - public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv) { - AnimatorSet anim = super.createAdjacentPageAnimForTaskLaunch(tv); + public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv, + ClipAnimationHelper helper) { + AnimatorSet anim = super.createAdjacentPageAnimForTaskLaunch(tv, helper); + + if (!OverviewInteractionState.getInstance(mActivity).isSwipeUpGestureEnabled()) { + // Hotseat doesn't move when opening recents with the button, + // so don't animate it here either. + return anim; + } float allAppsProgressOffscreen = ALL_APPS_PROGRESS_OFF_SCREEN; LauncherState state = mActivity.getStateManager().getState(); @@ -132,8 +144,19 @@ public class LauncherRecentsView extends RecentsView { LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect); } - @AnyThread - public static void getPageRect(DeviceProfile grid, Context context, Rect outRect) { - LayoutUtils.calculateLauncherTaskSize(context, grid, outRect); + @Override + protected void onTaskLaunched(boolean success) { + if (success) { + mActivity.getStateManager().goToState(NORMAL, false /* animate */); + } else { + LauncherState state = mActivity.getStateManager().getState(); + mActivity.getAllAppsController().setProgress(state.getVerticalProgress(mActivity)); + } + super.onTaskLaunched(success); + } + + @Override + public boolean shouldUseMultiWindowTaskSizeStrategy() { + return mActivity.isInMultiWindowModeCompat(); } } diff --git a/quickstep/src/com/android/quickstep/views/QuickstepDragIndicator.java b/quickstep/src/com/android/quickstep/views/QuickstepDragIndicator.java deleted file mode 100644 index 5e9cd6e4fe..0000000000 --- a/quickstep/src/com/android/quickstep/views/QuickstepDragIndicator.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.quickstep.views; - -import static com.android.launcher3.LauncherState.ALL_APPS; -import static com.android.launcher3.LauncherState.OVERVIEW; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.View; -import android.view.accessibility.AccessibilityNodeInfo; - -import com.android.launcher3.R; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action; -import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; -import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; -import com.android.launcher3.views.LauncherDragIndicator; - -public class QuickstepDragIndicator extends LauncherDragIndicator { - - public QuickstepDragIndicator(Context context) { - super(context); - } - - public QuickstepDragIndicator(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public QuickstepDragIndicator(Context context, AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - - private boolean isInOverview() { - return mLauncher.isInState(OVERVIEW); - } - - @Override - public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - super.onInitializeAccessibilityNodeInfo(info); - info.setContentDescription(getContext().getString(R.string.all_apps_button_label)); - } - - @Override - protected void initCustomActions(AccessibilityNodeInfo info) { - if (!isInOverview()) { - super.initCustomActions(info); - } - } - - @Override - public void onClick(View view) { - mLauncher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP, - ControlType.ALL_APPS_BUTTON, - isInOverview() ? ContainerType.TASKSWITCHER : ContainerType.WORKSPACE); - mLauncher.getStateManager().goToState(ALL_APPS); - } -} diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 7e81ba9020..a6da89f205 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -16,11 +16,15 @@ package com.android.quickstep.views; +import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL_2; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW; +import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId; +import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; @@ -30,13 +34,13 @@ import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.graphics.Canvas; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Build; +import android.os.Handler; +import android.os.UserHandle; import android.text.Layout; import android.text.StaticLayout; import android.text.TextPaint; @@ -49,7 +53,6 @@ import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewDebug; -import android.view.accessibility.AccessibilityEvent; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; @@ -64,43 +67,35 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.util.PendingAnimation; import com.android.launcher3.util.Themes; +import com.android.quickstep.OverviewCallbacks; import com.android.quickstep.QuickScrubController; -import com.android.quickstep.RecentsAnimationInterpolator; -import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds; import com.android.quickstep.RecentsModel; import com.android.quickstep.TaskUtils; +import com.android.quickstep.util.ClipAnimationHelper; +import com.android.quickstep.util.TaskViewDrawable; import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan; import com.android.systemui.shared.recents.model.RecentsTaskLoader; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.TaskStack; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; +import com.android.systemui.shared.system.BackgroundExecutor; +import com.android.systemui.shared.system.PackageManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import java.util.ArrayList; +import java.util.function.Consumer; /** * A list of recent tasks. */ @TargetApi(Build.VERSION_CODES.P) -public abstract class RecentsView - extends PagedView implements OnSharedPreferenceChangeListener, Insettable { +public abstract class RecentsView extends PagedView implements Insettable { + + private static final String TAG = RecentsView.class.getSimpleName(); private final Rect mTempRect = new Rect(); - public static final FloatProperty CONTENT_ALPHA = - new FloatProperty("contentAlpha") { - @Override - public void setValue(RecentsView recentsView, float v) { - recentsView.setContentAlpha(v); - } - - @Override - public Float get(RecentsView recentsView) { - return recentsView.mContentAlpha; - } - }; - public static final FloatProperty ADJACENT_SCALE = new FloatProperty("adjacentScale") { @Override @@ -113,8 +108,12 @@ public abstract class RecentsView return recentsView.mAdjacentScale; } }; - private static final String PREF_FLIP_RECENTS = "pref_flip_recents"; + public static final boolean FLIP_RECENTS = true; private static final int DISMISS_TASK_DURATION = 300; + // The threshold at which we update the SystemUI flags when animating from the task into the app + private static final float UPDATE_SYSUI_FLAGS_THRESHOLD = 0.6f; + + private static final float[] sTempFloatArray = new float[3]; protected final T mActivity; private final QuickScrubController mQuickScrubController; @@ -125,19 +124,27 @@ public abstract class RecentsView // Keeps track of the previously known visible tasks for purposes of loading/unloading task data private final SparseBooleanArray mHasVisibleTaskData = new SparseBooleanArray(); + private boolean mIsClearAllButtonFullyRevealed; + /** * TODO: Call reloadIdNeeded in onTaskStackChanged. */ private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() { @Override public void onTaskSnapshotChanged(int taskId, ThumbnailData snapshot) { + if (!mHandleTaskStackChanges) { + return; + } updateThumbnail(taskId, snapshot); } @Override public void onActivityPinned(String packageName, int userId, int taskId, int stackId) { + if (!mHandleTaskStackChanges) { + return; + } // Check this is for the right user - if (!checkCurrentUserId(userId, false /* debug */)) { + if (!checkCurrentOrManagedUserId(userId, getContext())) { return; } @@ -150,21 +157,71 @@ public abstract class RecentsView @Override public void onActivityUnpinned() { + if (!mHandleTaskStackChanges) { + return; + } // TODO: Re-enable layout transitions for addition of the unpinned task reloadIfNeeded(); } + + @Override + public void onTaskRemoved(int taskId) { + if (!mHandleTaskStackChanges) { + return; + } + BackgroundExecutor.get().submit(() -> { + TaskView taskView = getTaskView(taskId); + if (taskView == null) { + return; + } + Handler handler = taskView.getHandler(); + if (handler == null) { + return; + } + + // TODO: Add callbacks from AM reflecting adding/removing from the recents list, and + // remove all these checks + Task.TaskKey taskKey = taskView.getTask().key; + if (PackageManagerWrapper.getInstance().getActivityInfo(taskKey.getComponent(), + taskKey.userId) == null) { + // The package was uninstalled + handler.post(() -> + dismissTask(taskView, true /* animate */, false /* removeTask */)); + } else { + RecentsTaskLoadPlan loadPlan = new RecentsTaskLoadPlan(getContext()); + RecentsTaskLoadPlan.PreloadOptions opts = + new RecentsTaskLoadPlan.PreloadOptions(); + opts.loadTitles = false; + loadPlan.preloadPlan(opts, mModel.getRecentsTaskLoader(), -1, + UserHandle.myUserId()); + if (loadPlan.getTaskStack().findTaskWithId(taskId) == null) { + // The task was removed from the recents list + handler.post(() -> + dismissTask(taskView, true /* animate */, false /* removeTask */)); + } + } + }); + } + + @Override + public void onPinnedStackAnimationStarted() { + // Needed for activities that auto-enter PiP, which will not trigger a remote + // animation to be created + mActivity.clearForceInvisibleFlag(INVISIBLE_BY_STATE_HANDLER); + } }; private int mLoadPlanId = -1; // Only valid until the launcher state changes to NORMAL private int mRunningTaskId = -1; + private boolean mRunningTaskTileHidden; private Task mTmpRunningTask; - private boolean mFirstTaskIconScaledDown = false; + private boolean mRunningTaskIconScaledDown = false; private boolean mOverviewStateEnabled; - private boolean mTaskStackListenerRegistered; + private boolean mHandleTaskStackChanges; private Runnable mNextPageSwitchRunnable; private boolean mSwipeDownShouldLaunchApp; @@ -178,6 +235,8 @@ public abstract class RecentsView // Keeps track of task views whose visual state should not be reset private ArraySet mIgnoreResetTaskViews = new ArraySet<>(); + private View mClearAllButton; + // Variables for empty state private final Drawable mEmptyIcon; private final CharSequence mEmptyMessage; @@ -187,6 +246,14 @@ public abstract class RecentsView private boolean mShowEmptyMessage; private Layout mEmptyTextLayout; + private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener = + (inMultiWindowMode) -> { + if (!inMultiWindowMode && mOverviewStateEnabled) { + // TODO: Re-enable layout transitions for addition of the unpinned task + reloadIfNeeded(); + } + }; + public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing)); @@ -199,7 +266,11 @@ public abstract class RecentsView mQuickScrubController = new QuickScrubController(mActivity, this); mModel = RecentsModel.getInstance(context); - onSharedPreferenceChanged(Utilities.getPrefs(context), PREF_FLIP_RECENTS); + mIsRtl = Utilities.isRtl(getResources()); + if (FLIP_RECENTS) { + mIsRtl = !mIsRtl; + } + setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); mEmptyIcon = context.getDrawable(R.drawable.ic_empty_recents); mEmptyIcon.setCallback(this); @@ -211,17 +282,7 @@ public abstract class RecentsView mEmptyMessagePadding = getResources() .getDimensionPixelSize(R.dimen.recents_empty_message_text_padding); setWillNotDraw(false); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) { - if (s.equals(PREF_FLIP_RECENTS)) { - mIsRtl = Utilities.isRtl(getResources()); - if (sharedPreferences.getBoolean(PREF_FLIP_RECENTS, false)) { - mIsRtl = !mIsRtl; - } - setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); - } + updateEmptyMessage(); } public boolean isRtl() { @@ -229,14 +290,11 @@ public abstract class RecentsView } public TaskView updateThumbnail(int taskId, ThumbnailData thumbnailData) { - for (int i = 0; i < getChildCount(); i++) { - final TaskView taskView = (TaskView) getChildAt(i); - if (taskView.getTask().key.id == taskId) { - taskView.onTaskDataLoaded(taskView.getTask(), thumbnailData); - return taskView; - } + TaskView taskView = getTaskView(taskId); + if (taskView != null) { + taskView.onTaskDataLoaded(taskView.getTask(), thumbnailData); } - return null; + return taskView; } @Override @@ -249,14 +307,16 @@ public abstract class RecentsView protected void onAttachedToWindow() { super.onAttachedToWindow(); updateTaskStackListenerState(); - Utilities.getPrefs(getContext()).registerOnSharedPreferenceChangeListener(this); + mActivity.addMultiWindowModeChangedListener(mMultiWindowModeChangedListener); + ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); updateTaskStackListenerState(); - Utilities.getPrefs(getContext()).unregisterOnSharedPreferenceChangeListener(this); + mActivity.removeMultiWindowModeChangedListener(mMultiWindowModeChangedListener); + ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mTaskStackListener); } @Override @@ -271,6 +331,7 @@ public abstract class RecentsView loader.unloadTaskData(task); loader.getHighResThumbnailLoader().onTaskInvisible(task); } + onChildViewsChanged(); } public boolean isTaskViewVisible(TaskView tv) { @@ -309,11 +370,69 @@ public abstract class RecentsView } } + private int getScrollEnd() { + return mIsRtl ? 0 : mMaxScrollX; + } + + private float calculateClearAllButtonAlpha() { + final int childCount = getChildCount(); + if (mShowEmptyMessage || childCount == 0 || mPageScrolls == null + || childCount != mPageScrolls.length) { + return 0; + } + + final int scrollEnd = getScrollEnd(); + final int oldestChildScroll = getScrollForPage(childCount - 1); + + final int clearAllButtonMotionRange = scrollEnd - oldestChildScroll; + if (clearAllButtonMotionRange == 0) return 0; + + final float alphaUnbound = ((float) (getScrollX() - oldestChildScroll)) / + clearAllButtonMotionRange; + if (alphaUnbound > 1) return 0; + + return Math.max(alphaUnbound, 0); + } + + private void updateClearAllButtonAlpha() { + if (mClearAllButton != null) { + final float alpha = calculateClearAllButtonAlpha(); + mIsClearAllButtonFullyRevealed = alpha == 1; + mClearAllButton.setAlpha(alpha * mContentAlpha); + } + } + + @Override + protected void onScrollChanged(int l, int t, int oldl, int oldt) { + super.onScrollChanged(l, t, oldl, oldt); + updateClearAllButtonAlpha(); + } + + @Override + protected void restoreScrollOnLayout() { + if (mIsClearAllButtonFullyRevealed) { + scrollAndForceFinish(getScrollEnd()); + } else { + super.restoreScrollOnLayout(); + } + } + @Override public boolean onTouchEvent(MotionEvent ev) { - super.onTouchEvent(ev); - // Do not let touch escape to siblings below this view. - return true; + if (ev.getAction() == MotionEvent.ACTION_DOWN && mTouchState == TOUCH_STATE_REST + && mScroller.isFinished() && mIsClearAllButtonFullyRevealed) { + mClearAllButton.getHitRect(mTempRect); + mTempRect.offset(-getLeft(), -getTop()); + if (mTempRect.contains((int) ev.getX(), (int) ev.getY())) { + // If nothing is in motion, let the Clear All button process the event. + return false; + } + } + + if (ev.getAction() == MotionEvent.ACTION_UP && mShowEmptyMessage) { + onAllTasksRemoved(); + } + return super.onTouchEvent(ev); } private void applyLoadPlan(RecentsTaskLoadPlan loadPlan) { @@ -356,7 +475,6 @@ public abstract class RecentsView taskView.bind(task); } resetTaskVisuals(); - applyIconScale(false /* animate */); if (oldChildCount != getChildCount()) { mQuickScrubController.snapToNextTaskIfAvailable(); @@ -373,6 +491,10 @@ public abstract class RecentsView taskView.resetVisualProperties(); } } + if (mRunningTaskTileHidden) { + setRunningTaskHidden(mRunningTaskTileHidden); + } + applyIconScale(false /* animate */); updateCurveProperties(); // Update the set of visible task's data @@ -380,18 +502,13 @@ public abstract class RecentsView } private void updateTaskStackListenerState() { - boolean registerStackListener = mOverviewStateEnabled && isAttachedToWindow() + boolean handleTaskStackChanges = mOverviewStateEnabled && isAttachedToWindow() && getWindowVisibility() == VISIBLE; - if (registerStackListener != mTaskStackListenerRegistered) { - if (registerStackListener) { - ActivityManagerWrapper.getInstance() - .registerTaskStackListener(mTaskStackListener); + if (handleTaskStackChanges != mHandleTaskStackChanges) { + mHandleTaskStackChanges = handleTaskStackChanges; + if (handleTaskStackChanges) { reloadIfNeeded(); - } else { - ActivityManagerWrapper.getInstance() - .unregisterTaskStackListener(mTaskStackListener); } - mTaskStackListenerRegistered = registerStackListener; } } @@ -400,15 +517,20 @@ public abstract class RecentsView mInsets.set(insets); DeviceProfile dp = mActivity.getDeviceProfile(); getTaskSize(dp, mTempRect); + mTempRect.top -= getResources() .getDimensionPixelSize(R.dimen.task_thumbnail_top_margin); setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top, - dp.widthPx - mTempRect.right - mInsets.right, - dp.heightPx - mTempRect.bottom - mInsets.bottom); + dp.availableWidthPx + mInsets.left - mTempRect.right, + dp.availableHeightPx + mInsets.top - mTempRect.bottom); } protected abstract void getTaskSize(DeviceProfile dp, Rect outRect); + public void getTaskSize(Rect outRect) { + getTaskSize(mActivity.getDeviceProfile(), outRect); + } + @Override protected boolean computeScrollHelper() { boolean scrolling = super.computeScrollHelper(); @@ -506,13 +628,16 @@ public abstract class RecentsView mHasVisibleTaskData.clear(); } - protected abstract void onAllTasksRemoved(); public void reset() { - unloadVisibleTaskData(); mRunningTaskId = -1; + mRunningTaskTileHidden = false; + + unloadVisibleTaskData(); setCurrentPage(0); + + OverviewCallbacks.get(getContext()).onResetOverview(); } /** @@ -546,12 +671,17 @@ public abstract class RecentsView new ActivityManager.TaskDescription(), 0, new ComponentName("", ""), false); taskView.bind(mTmpRunningTask); } - setCurrentTask(mRunningTaskId); + setCurrentTask(runningTaskId); + } - // Hide the task that we are animating into, ignore if there is no associated task (ie. the - // assistant) - if (getPageAt(mCurrentPage) != null) { - getPageAt(mCurrentPage).setAlpha(0); + /** + * Hides the tile associated with {@link #mRunningTaskId} + */ + public void setRunningTaskHidden(boolean isHidden) { + mRunningTaskTileHidden = isHidden; + TaskView runningTask = getTaskView(mRunningTaskId); + if (runningTask != null) { + runningTask.setAlpha(isHidden ? 0 : mContentAlpha); } } @@ -559,7 +689,15 @@ public abstract class RecentsView * Similar to {@link #showTask(int)} but does not put any restrictions on the first tile. */ public void setCurrentTask(int runningTaskId) { + boolean runningTaskTileHidden = mRunningTaskTileHidden; + boolean runningTaskIconScaledDown = mRunningTaskIconScaledDown; + + setRunningTaskIconScaledDown(false, false); + setRunningTaskHidden(false); mRunningTaskId = runningTaskId; + setRunningTaskIconScaledDown(runningTaskIconScaledDown, false); + setRunningTaskHidden(runningTaskTileHidden); + setCurrentPage(0); // Load the tasks (if the loading is already @@ -587,22 +725,22 @@ public abstract class RecentsView return mQuickScrubController; } - public void setFirstTaskIconScaledDown(boolean isScaledDown, boolean animate) { - if (mFirstTaskIconScaledDown == isScaledDown) { + public void setRunningTaskIconScaledDown(boolean isScaledDown, boolean animate) { + if (mRunningTaskIconScaledDown == isScaledDown) { return; } - mFirstTaskIconScaledDown = isScaledDown; + mRunningTaskIconScaledDown = isScaledDown; applyIconScale(animate); } private void applyIconScale(boolean animate) { - float scale = mFirstTaskIconScaledDown ? 0 : 1; - TaskView firstTask = (TaskView) getChildAt(0); + float scale = mRunningTaskIconScaledDown ? 0 : 1; + TaskView firstTask = getTaskView(mRunningTaskId); if (firstTask != null) { if (animate) { - firstTask.animateIconToScale(scale); + firstTask.animateIconToScaleAndDim(scale); } else { - firstTask.setIconScale(scale); + firstTask.setIconScaleAndDim(scale); } } } @@ -640,8 +778,26 @@ public abstract class RecentsView mIgnoreResetTaskViews.remove(taskView); } + private void addDismissedTaskAnimations(View taskView, AnimatorSet anim, long duration) { + addAnim(ObjectAnimator.ofFloat(taskView, ALPHA, 0), duration, ACCEL_2, anim); + addAnim(ObjectAnimator.ofFloat(taskView, TRANSLATION_Y, -taskView.getHeight()), + duration, LINEAR, anim); + } + + private void removeTask(Task task, int index, PendingAnimation.OnEndListener onEndListener, + boolean shouldLog) { + if (task != null) { + ActivityManagerWrapper.getInstance().removeTask(task.key.id); + if (shouldLog) { + mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss( + onEndListener.logAction, Direction.UP, index, + TaskUtils.getComponentKeyForTask(task.key)); + } + } + } + public PendingAnimation createTaskDismissAnimation(TaskView taskView, boolean animateTaskView, - boolean removeTask, long duration) { + boolean shouldRemoveTask, long duration) { if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) { throw new IllegalStateException("Another pending animation is still running"); } @@ -659,26 +815,43 @@ public abstract class RecentsView int[] newScroll = new int[count]; getPageScrolls(newScroll, false, (v) -> v.getVisibility() != GONE && v != taskView); - int maxScrollDiff = 0; - int lastPage = mIsRtl ? 0 : count - 1; - if (getChildAt(lastPage) == taskView) { - if (count > 1) { - int secondLastPage = mIsRtl ? 1 : count - 2; - maxScrollDiff = oldScroll[lastPage] - newScroll[secondLastPage]; - } + int scrollDiffPerPage = 0; + int leftmostPage = mIsRtl ? count -1 : 0; + int rightmostPage = mIsRtl ? 0 : count - 1; + if (count > 1) { + int secondRightmostPage = mIsRtl ? 1 : count - 2; + scrollDiffPerPage = oldScroll[rightmostPage] - oldScroll[secondRightmostPage]; } + int draggedIndex = indexOfChild(taskView); boolean needsCurveUpdates = false; for (int i = 0; i < count; i++) { View child = getChildAt(i); if (child == taskView) { if (animateTaskView) { - addAnim(ObjectAnimator.ofFloat(taskView, ALPHA, 0), duration, ACCEL_2, anim); - addAnim(ObjectAnimator.ofFloat(taskView, TRANSLATION_Y, -taskView.getHeight()), - duration, LINEAR, anim); + addDismissedTaskAnimations(taskView, anim, duration); } } else { - int scrollDiff = newScroll[i] - oldScroll[i] + maxScrollDiff; + // If we just take newScroll - oldScroll, everything to the right of dragged task + // translates to the left. We need to offset this in some cases: + // - In RTL, add page offset to all pages, since we want pages to move to the right + // Additionally, add a page offset if: + // - Current page is rightmost page (leftmost for RTL) + // - Dragging an adjacent page on the left side (right side for RTL) + int offset = mIsRtl ? scrollDiffPerPage : 0; + if (mCurrentPage == draggedIndex) { + int lastPage = mIsRtl ? leftmostPage : rightmostPage; + if (mCurrentPage == lastPage) { + offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage; + } + } else { + // Dragging an adjacent page. + int negativeAdjacent = mCurrentPage - 1; // (Right in RTL, left in LTR) + if (draggedIndex == negativeAdjacent) { + offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage; + } + } + int scrollDiff = newScroll[i] - oldScroll[i] + offset; if (scrollDiff != 0) { addAnim(ObjectAnimator.ofFloat(child, TRANSLATION_X, scrollDiff), duration, ACCEL, anim); @@ -701,18 +874,18 @@ public abstract class RecentsView mPendingAnimation = pendingAnimation; mPendingAnimation.addEndListener((onEndListener) -> { if (onEndListener.isSuccess) { - if (removeTask) { - Task task = taskView.getTask(); - if (task != null) { - ActivityManagerWrapper.getInstance().removeTask(task.key.id); - mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss( - onEndListener.logAction, Direction.UP, - TaskUtils.getComponentKeyForTask(task.key)); - } + if (shouldRemoveTask) { + removeTask(taskView.getTask(), draggedIndex, onEndListener, true); + } + int pageToSnapTo = mCurrentPage; + if (draggedIndex < pageToSnapTo) { + pageToSnapTo -= 1; } removeView(taskView); if (getChildCount() == 0) { onAllTasksRemoved(); + } else if (!mIsClearAllButtonFullyRevealed) { + snapToPageImmediately(pageToSnapTo); } } resetTaskVisuals(); @@ -721,6 +894,33 @@ public abstract class RecentsView return pendingAnimation; } + public PendingAnimation createAllTasksDismissAnimation(long duration) { + if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) { + throw new IllegalStateException("Another pending animation is still running"); + } + AnimatorSet anim = new AnimatorSet(); + PendingAnimation pendingAnimation = new PendingAnimation(anim); + + int count = getChildCount(); + for (int i = 0; i < count; i++) { + addDismissedTaskAnimations(getChildAt(i), anim, duration); + } + + mPendingAnimation = pendingAnimation; + mPendingAnimation.addEndListener((onEndListener) -> { + if (onEndListener.isSuccess) { + while (getChildCount() != 0) { + TaskView taskView = getPageAt(getChildCount() - 1); + removeTask(taskView.getTask(), -1, onEndListener, false); + removeView(taskView); + } + onAllTasksRemoved(); + } + mPendingAnimation = null; + }); + return pendingAnimation; + } + private static void addAnim(ObjectAnimator anim, long duration, TimeInterpolator interpolator, AnimatorSet set) { anim.setDuration(duration).setInterpolator(interpolator); @@ -744,9 +944,7 @@ public abstract class RecentsView } } - public void dismissTask(TaskView taskView, boolean animateTaskView, boolean removeTask) { - PendingAnimation pendingAnim = createTaskDismissAnimation(taskView, animateTaskView, - removeTask, DISMISS_TASK_DURATION); + private void runDismissAnimation(PendingAnimation pendingAnim) { AnimatorPlaybackController controller = AnimatorPlaybackController.wrap( pendingAnim.anim, DISMISS_TASK_DURATION); controller.dispatchOnStart(); @@ -755,6 +953,15 @@ public abstract class RecentsView controller.start(); } + public void dismissTask(TaskView taskView, boolean animateTaskView, boolean removeTask) { + runDismissAnimation(createTaskDismissAnimation(taskView, animateTaskView, removeTask, + DISMISS_TASK_DURATION)); + } + + public void dismissAllTasks() { + runDismissAnimation(createAllTasksDismissAnimation(DISMISS_TASK_DURATION)); + } + @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { @@ -789,21 +996,24 @@ public abstract class RecentsView snapToPageRelative(1); } - public void setContentAlpha(float alpha) { - if (mContentAlpha == alpha) { - return; - } + public float getContentAlpha() { + return mContentAlpha; + } + public void setContentAlpha(float alpha) { + alpha = Utilities.boundToRange(alpha, 0, 1); mContentAlpha = alpha; for (int i = getChildCount() - 1; i >= 0; i--) { - getChildAt(i).setAlpha(alpha); + TaskView child = getPageAt(i); + if (!mRunningTaskTileHidden || child.getTask().key.id != mRunningTaskId) { + getChildAt(i).setAlpha(alpha); + } } int alphaInt = Math.round(alpha * 255); mEmptyMessagePaint.setAlpha(alphaInt); mEmptyIcon.setAlpha(alphaInt); - - setVisibility(alpha > 0 ? VISIBLE : GONE); + updateClearAllButtonAlpha(); } public void setAdjacentScale(float adjacentScale) { @@ -815,15 +1025,13 @@ public abstract class RecentsView if (currTask == null) { return; } - currTask.setScaleX(mAdjacentScale); - currTask.setScaleY(mAdjacentScale); + currTask.setZoomScale(mAdjacentScale); if (mCurrentPage - 1 >= 0) { TaskView adjacentTask = getPageAt(mCurrentPage - 1); float[] scaleAndTranslation = getAdjacentScaleAndTranslation(currTask, adjacentTask, mAdjacentScale, 0); - adjacentTask.setScaleX(scaleAndTranslation[0]); - adjacentTask.setScaleY(scaleAndTranslation[0]); + adjacentTask.setZoomScale(scaleAndTranslation[0]); adjacentTask.setTranslationX(-scaleAndTranslation[1]); adjacentTask.setTranslationY(scaleAndTranslation[2]); } @@ -831,8 +1039,7 @@ public abstract class RecentsView TaskView adjacentTask = getPageAt(mCurrentPage + 1); float[] scaleAndTranslation = getAdjacentScaleAndTranslation(currTask, adjacentTask, mAdjacentScale, 0); - adjacentTask.setScaleX(scaleAndTranslation[0]); - adjacentTask.setScaleY(scaleAndTranslation[0]); + adjacentTask.setZoomScale(scaleAndTranslation[0]); adjacentTask.setTranslationX(scaleAndTranslation[1]); adjacentTask.setTranslationY(scaleAndTranslation[2]); } @@ -841,11 +1048,10 @@ public abstract class RecentsView private float[] getAdjacentScaleAndTranslation(TaskView currTask, TaskView adjacentTask, float currTaskToScale, float currTaskToTranslationY) { float displacement = currTask.getWidth() * (currTaskToScale - currTask.getCurveScale()); - return new float[] { - currTaskToScale * adjacentTask.getCurveScale(), - mIsRtl ? -displacement : displacement, - currTaskToTranslationY - }; + sTempFloatArray[0] = currTaskToScale; + sTempFloatArray[1] = mIsRtl ? -displacement : displacement; + sTempFloatArray[2] = currTaskToTranslationY; + return sTempFloatArray; } @Override @@ -853,6 +1059,7 @@ public abstract class RecentsView super.onViewAdded(child); child.setAlpha(mContentAlpha); setAdjacentScale(mAdjacentScale); + onChildViewsChanged(); } @Override @@ -883,10 +1090,11 @@ public abstract class RecentsView boolean hasValidSize = getWidth() > 0 && getHeight() > 0; if (sizeChanged && hasValidSize) { mEmptyTextLayout = null; + mLastMeasureSize.set(getWidth(), getHeight()); } + updateClearAllButtonAlpha(); if (mShowEmptyMessage && hasValidSize && mEmptyTextLayout == null) { - mLastMeasureSize.set(getWidth(), getHeight()); int availableWidth = mLastMeasureSize.x - mEmptyMessagePadding - mEmptyMessagePadding; mEmptyTextLayout = StaticLayout.Builder.obtain(mEmptyMessage, 0, mEmptyMessage.length(), mEmptyMessagePaint, availableWidth) @@ -909,8 +1117,13 @@ public abstract class RecentsView protected void maybeDrawEmptyMessage(Canvas canvas) { if (mShowEmptyMessage && mEmptyTextLayout != null) { - mEmptyIcon.draw(canvas); + // Offset to center in the visible (non-padded) part of RecentsView + mTempRect.set(mInsets.left + getPaddingLeft(), mInsets.top + getPaddingTop(), + mInsets.right + getPaddingRight(), mInsets.bottom + getPaddingBottom()); canvas.save(); + canvas.translate(getScrollX() + (mTempRect.left - mTempRect.right) / 2, + (mTempRect.top - mTempRect.bottom) / 2); + mEmptyIcon.draw(canvas); canvas.translate(mEmptyMessagePadding, mEmptyIcon.getBounds().bottom + mEmptyMessagePadding); mEmptyTextLayout.draw(canvas); @@ -924,17 +1137,18 @@ public abstract class RecentsView * If launching one of the adjacent tasks, parallax the center task and other adjacent task * to the right. */ - public AnimatorSet createAdjacentPageAnimForTaskLaunch(TaskView tv) { + public AnimatorSet createAdjacentPageAnimForTaskLaunch( + TaskView tv, ClipAnimationHelper clipAnimationHelper) { AnimatorSet anim = new AnimatorSet(); int taskIndex = indexOfChild(tv); int centerTaskIndex = getCurrentPage(); boolean launchingCenterTask = taskIndex == centerTaskIndex; - TaskWindowBounds endInterpolation = tv.getRecentsInterpolator().interpolate(1); - float toScale = endInterpolation.taskScale; - float toTranslationY = endInterpolation.taskY; - + float toScale = clipAnimationHelper.getSourceRect().width() + / clipAnimationHelper.getTargetRect().width(); + float toTranslationY = clipAnimationHelper.getSourceRect().centerY() + - clipAnimationHelper.getTargetRect().centerY(); if (launchingCenterTask) { TaskView centerTask = getPageAt(centerTaskIndex); if (taskIndex - 1 >= 0) { @@ -968,68 +1182,143 @@ public abstract class RecentsView return anim; } - private ObjectAnimator createAnimForChild(View child, float[] toScaleAndTranslation) { - return ObjectAnimator.ofPropertyValuesHolder(child, + private Animator createAnimForChild(TaskView child, float[] toScaleAndTranslation) { + AnimatorSet anim = new AnimatorSet(); + anim.play(ObjectAnimator.ofFloat(child, TaskView.ZOOM_SCALE, toScaleAndTranslation[0])); + anim.play(ObjectAnimator.ofPropertyValuesHolder(child, new PropertyListBuilder() - .scale(child.getScaleX() * toScaleAndTranslation[0]) .translationX(toScaleAndTranslation[1]) .translationY(toScaleAndTranslation[2]) - .build()); + .build())); + return anim; } public PendingAnimation createTaskLauncherAnimation(TaskView tv, long duration) { if (FeatureFlags.IS_DOGFOOD_BUILD && mPendingAnimation != null) { throw new IllegalStateException("Another pending animation is still running"); } - AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv); int count = getChildCount(); if (count == 0) { - return new PendingAnimation(anim); + return new PendingAnimation(new AnimatorSet()); } - final RecentsAnimationInterpolator recentsInterpolator = tv.getRecentsInterpolator(); - ValueAnimator targetViewAnim = ValueAnimator.ofFloat(0, 1); - targetViewAnim.addUpdateListener((animation) -> { - float percent = animation.getAnimatedFraction(); - TaskWindowBounds tw = recentsInterpolator.interpolate(percent); - tv.setScaleX(tw.taskScale); - tv.setScaleY(tw.taskScale); - tv.setTranslationX(tw.taskX); - tv.setTranslationY(tw.taskY); + tv.setVisibility(INVISIBLE); + int targetSysUiFlags = tv.getThumbnail().getSysUiStatusNavFlags(); + TaskViewDrawable drawable = new TaskViewDrawable(tv, this); + getOverlay().add(drawable); + + ObjectAnimator drawableAnim = + ObjectAnimator.ofFloat(drawable, TaskViewDrawable.PROGRESS, 1, 0); + drawableAnim.setInterpolator(LINEAR); + drawableAnim.addUpdateListener((animator) -> { + // Once we pass a certain threshold, update the sysui flags to match the target tasks' + // flags + mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, + animator.getAnimatedFraction() > UPDATE_SYSUI_FLAGS_THRESHOLD + ? targetSysUiFlags + : 0); }); - anim.play(targetViewAnim); + + AnimatorSet anim = createAdjacentPageAnimForTaskLaunch(tv, + drawable.getClipAnimationHelper()); + anim.play(drawableAnim); anim.setDuration(duration); + Consumer onTaskLaunchFinish = (result) -> { + onTaskLaunched(result); + tv.setVisibility(VISIBLE); + getOverlay().remove(drawable); + }; + mPendingAnimation = new PendingAnimation(anim); mPendingAnimation.addEndListener((onEndListener) -> { if (onEndListener.isSuccess) { - tv.launchTask(false); + Consumer onLaunchResult = (result) -> { + onTaskLaunchFinish.accept(result); + if (!result) { + tv.notifyTaskLaunchFailed(TAG); + } + }; + tv.launchTask(false, onLaunchResult, getHandler()); Task task = tv.getTask(); if (task != null) { mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss( - onEndListener.logAction, Direction.DOWN, + onEndListener.logAction, Direction.DOWN, indexOfChild(tv), TaskUtils.getComponentKeyForTask(task.key)); } } else { - resetTaskVisuals(); + onTaskLaunchFinish.accept(false); } mPendingAnimation = null; }); return mPendingAnimation; } + public abstract boolean shouldUseMultiWindowTaskSizeStrategy(); + + protected void onTaskLaunched(boolean success) { + resetTaskVisuals(); + } + @Override protected void notifyPageSwitchListener(int prevPage) { super.notifyPageSwitchListener(prevPage); - View currChild = getChildAt(mCurrentPage); - if (currChild != null) { - currChild.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); - } + loadVisibleTaskData(); } @Override protected String getCurrentPageDescription() { return ""; } + + private int additionalScrollForClearAllButton() { + return (int) getResources().getDimension( + R.dimen.clear_all_container_width) - getPaddingEnd(); + } + + @Override + protected int computeMaxScrollX() { + if (getChildCount() == 0) { + return super.computeMaxScrollX(); + } + + // Allow a clear_all_container_width-sized gap after the last task. + return super.computeMaxScrollX() + (mIsRtl ? 0 : additionalScrollForClearAllButton()); + } + + @Override + protected int offsetForPageScrolls() { + return mIsRtl ? additionalScrollForClearAllButton() : 0; + } + + public void setClearAllButton(View clearAllButton) { + mClearAllButton = clearAllButton; + updateClearAllButtonAlpha(); + } + + private void onChildViewsChanged() { + final int childCount = getChildCount(); + mClearAllButton.setVisibility(childCount == 0 ? INVISIBLE : VISIBLE); + } + + public void revealClearAllButton() { + scrollTo(mIsRtl ? 0 : computeMaxScrollX(), 0); + } + + @Override + public void addChildrenForAccessibility(ArrayList outChildren) { + if (FLIP_RECENTS) { + for (int i = getChildCount() - 1; i >= 0; --i) { + outChildren.add(getChildAt(i)); + } + } else { + super.addChildrenForAccessibility(outChildren); + } + } + + @Override + protected boolean isPageOrderFlipped() { + return FLIP_RECENTS; + } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java new file mode 100644 index 0000000000..429432b2fa --- /dev/null +++ b/quickstep/src/com/android/quickstep/views/RecentsViewContainer.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.quickstep.views; + +import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.TAP; +import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.CLEAR_ALL_BUTTON; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.util.FloatProperty; +import android.view.Gravity; +import android.view.MotionEvent; + +import com.android.launcher3.InsettableFrameLayout; +import com.android.launcher3.R; + +public class RecentsViewContainer extends InsettableFrameLayout { + public static final FloatProperty CONTENT_ALPHA = + new FloatProperty("contentAlpha") { + @Override + public void setValue(RecentsViewContainer view, float v) { + view.setContentAlpha(v); + } + + @Override + public Float get(RecentsViewContainer view) { + return view.mRecentsView.getContentAlpha(); + } + }; + + private final Rect mTempRect = new Rect(); + + private RecentsView mRecentsView; + private ClearAllButton mClearAllButton; + + public RecentsViewContainer(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + mClearAllButton = findViewById(R.id.clear_all_button); + mClearAllButton.setOnClickListener((v) -> { + mRecentsView.mActivity.getUserEventDispatcher() + .logActionOnControl(TAP, CLEAR_ALL_BUTTON); + mRecentsView.dismissAllTasks(); + }); + + mRecentsView = findViewById(R.id.overview_panel); + final InsettableFrameLayout.LayoutParams params = + (InsettableFrameLayout.LayoutParams) mClearAllButton.getLayoutParams(); + params.gravity = Gravity.TOP | (RecentsView.FLIP_RECENTS ? Gravity.START : Gravity.END); + mClearAllButton.setLayoutParams(params); + mClearAllButton.forceHasOverlappingRendering(false); + + mRecentsView.setClearAllButton(mClearAllButton); + mClearAllButton.setRecentsView(mRecentsView); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + + mRecentsView.getTaskSize(mTempRect); + + mClearAllButton.setTranslationX( + (mRecentsView.isRtl() ? 1 : -1) * + (getResources().getDimension(R.dimen.clear_all_container_width) + - mClearAllButton.getMeasuredWidth()) / 2); + mClearAllButton.setTranslationY( + mTempRect.top + (mTempRect.height() - mClearAllButton.getMeasuredHeight()) / 2 + - mClearAllButton.getTop()); + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + super.onTouchEvent(ev); + // Do not let touch escape to siblings below this view. This prevents scrolling of the + // workspace while in Recents. + return true; + } + + public void setContentAlpha(float alpha) { + if (alpha == mRecentsView.getContentAlpha()) { + return; + } + mRecentsView.setContentAlpha(alpha); + setVisibility(alpha > 0 ? VISIBLE : GONE); + } +} \ No newline at end of file diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java new file mode 100644 index 0000000000..24afd4868e --- /dev/null +++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.quickstep.views; + +import static android.support.v4.graphics.ColorUtils.compositeColors; +import static android.support.v4.graphics.ColorUtils.setAlphaComponent; + +import static com.android.launcher3.LauncherState.OVERVIEW; +import static com.android.launcher3.anim.Interpolators.ACCEL_2; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Path.Direction; +import android.graphics.Path.Op; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; +import android.util.AttributeSet; + +import com.android.launcher3.DeviceProfile; +import com.android.launcher3.R; +import com.android.launcher3.uioverrides.OverviewState; +import com.android.launcher3.util.Themes; +import com.android.launcher3.views.ScrimView; + +/** + * Scrim used for all-apps and shelf in Overview + * In transposed layout, it behaves as a simple color scrim. + * In portrait layout, it draws a rounded rect such that + * From normal state to overview state, the shelf just fades in and does not move + * From overview state to all-apps state the shelf moves up and fades in to cover the screen + */ +public class ShelfScrimView extends ScrimView { + + private static final int THRESHOLD_ALPHA_DARK = 102; + private static final int THRESHOLD_ALPHA_LIGHT = 46; + private static final int THRESHOLD_ALPHA_SUPER_LIGHT = 128; + private static final int CLEAR_ALL_TASKS = R.string.recents_clear_all; + + // In transposed layout, we simply draw a flat color. + private boolean mDrawingFlatColor; + + // For shelf mode + private final int mEndAlpha; + private final int mThresholdAlpha; + private final float mRadius; + private final float mMaxScrimAlpha; + private final Paint mPaint; + + // Max vertical progress after which the scrim stops moving. + private float mMoveThreshold; + // Minimum visible size of the scrim. + private int mMinSize; + + private float mScrimMoveFactor = 0; + private int mShelfColor; + private int mRemainingScreenColor; + + private final Path mTempPath = new Path(); + private final Path mRemainingScreenPath = new Path(); + private boolean mRemainingScreenPathValid = false; + + public ShelfScrimView(Context context, AttributeSet attrs) { + super(context, attrs); + mMaxScrimAlpha = OVERVIEW.getWorkspaceScrimAlpha(mLauncher); + + mEndAlpha = Color.alpha(mEndScrim); + if (Themes.getAttrBoolean(mLauncher, R.attr.isMainColorDark)) { + mThresholdAlpha = THRESHOLD_ALPHA_DARK; + } else if (Themes.getAttrBoolean(mLauncher, R.attr.isWorkspaceDarkText)) { + mThresholdAlpha = THRESHOLD_ALPHA_SUPER_LIGHT; + } else { + mThresholdAlpha = THRESHOLD_ALPHA_LIGHT; + } + mRadius = mLauncher.getResources().getDimension(R.dimen.shelf_surface_radius); + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + + // Just assume the easiest UI for now, until we have the proper layout information. + mDrawingFlatColor = true; + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mRemainingScreenPathValid = false; + } + + @Override + public void reInitUi() { + DeviceProfile dp = mLauncher.getDeviceProfile(); + mDrawingFlatColor = dp.isVerticalBarLayout(); + + if (!mDrawingFlatColor) { + float swipeLength = OverviewState.getDefaultSwipeHeight(mLauncher); + mMoveThreshold = 1 - swipeLength / mLauncher.getAllAppsController().getShiftRange(); + mMinSize = dp.hotseatBarSizePx + dp.getInsets().bottom; + mRemainingScreenPathValid = false; + updateColors(); + } + updateDragHandleAlpha(); + invalidate(); + } + + @Override + public void updateColors() { + super.updateColors(); + if (mDrawingFlatColor) { + return; + } + + if (mProgress >= mMoveThreshold) { + mScrimMoveFactor = 1; + + if (mProgress >= 1) { + mShelfColor = 0; + } else { + int alpha = Math.round(mThresholdAlpha * ACCEL_2.getInterpolation( + (1 - mProgress) / (1 - mMoveThreshold))); + mShelfColor = setAlphaComponent(mEndScrim, alpha); + } + + mRemainingScreenColor = 0; + } else if (mProgress <= 0) { + mScrimMoveFactor = 0; + mShelfColor = mCurrentFlatColor; + mRemainingScreenColor = 0; + + } else { + mScrimMoveFactor = mProgress / mMoveThreshold; + mRemainingScreenColor = setAlphaComponent(mScrimColor, + Math.round((1 - mScrimMoveFactor) * mMaxScrimAlpha * 255)); + + // Merge the remainingScreenColor and shelfColor in one to avoid overdraw. + int alpha = mEndAlpha - Math.round((mEndAlpha - mThresholdAlpha) * mScrimMoveFactor); + mShelfColor = compositeColors(setAlphaComponent(mEndScrim, alpha), + mRemainingScreenColor); + } + } + + @Override + protected void updateDragHandleAlpha() { + if (mDrawingFlatColor) { + super.updateDragHandleAlpha(); + } else if (mDragHandle != null) { + mDragHandle.setAlpha(255); + } + } + + @Override + protected void onDraw(Canvas canvas) { + float translate = drawBackground(canvas); + + if (mDragHandle != null) { + canvas.translate(0, -translate); + mDragHandle.draw(canvas); + canvas.translate(0, translate); + } + } + + private float drawBackground(Canvas canvas) { + if (mDrawingFlatColor) { + if (mCurrentFlatColor != 0) { + canvas.drawColor(mCurrentFlatColor); + } + return 0; + } + + if (mShelfColor == 0) { + return 0; + } else if (mScrimMoveFactor <= 0) { + canvas.drawColor(mShelfColor); + return getHeight(); + } + + float minTop = getHeight() - mMinSize; + float top = minTop * mScrimMoveFactor - mDragHandleSize; + + // Draw the scrim over the remaining screen if needed. + if (mRemainingScreenColor != 0) { + if (!mRemainingScreenPathValid) { + mTempPath.reset(); + // Using a arbitrary '+10' in the bottom to avoid any left-overs at the + // corners due to rounding issues. + mTempPath.addRoundRect(0, minTop, getWidth(), getHeight() + mRadius + 10, + mRadius, mRadius, Direction.CW); + + mRemainingScreenPath.reset(); + mRemainingScreenPath.addRect(0, 0, getWidth(), getHeight(), Direction.CW); + mRemainingScreenPath.op(mTempPath, Op.DIFFERENCE); + } + + float offset = minTop - top; + canvas.translate(0, -offset); + mPaint.setColor(mRemainingScreenColor); + canvas.drawPath(mRemainingScreenPath, mPaint); + canvas.translate(0, offset); + } + + mPaint.setColor(mShelfColor); + canvas.drawRoundRect(0, top, getWidth(), getHeight() + mRadius, + mRadius, mRadius, mPaint); + return minTop - mDragHandleSize - top; + } + + @NonNull + @Override + protected AccessibilityHelper createAccessibilityHelper() { + return new ShelfScrimAccessibilityHelper(); + } + + protected class ShelfScrimAccessibilityHelper extends AccessibilityHelper { + @Override + protected void onPopulateNodeForVirtualView(int virtualViewId, + AccessibilityNodeInfoCompat node) { + super.onPopulateNodeForVirtualView(virtualViewId, node); + + if (mLauncher.isInState(OVERVIEW)) { + final RecentsView overviewPanel = mLauncher.getOverviewPanel(); + if (overviewPanel.getChildCount() != 0) { + node.addAction( + new AccessibilityNodeInfoCompat.AccessibilityActionCompat( + CLEAR_ALL_TASKS, + getContext().getText(CLEAR_ALL_TASKS))); + } + } + } + + @Override + protected boolean onPerformActionForVirtualView( + int virtualViewId, int action, Bundle arguments) { + if (super.onPerformActionForVirtualView(virtualViewId, action, arguments)) return true; + + if (action == CLEAR_ALL_TASKS) { + if (mLauncher.isInState(OVERVIEW)) { + mLauncher.getOverviewPanel().dismissAllTasks(); + } + return true; + } + + return false; + } + } +} diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java index 58b7db7b22..128a19e06a 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java @@ -16,6 +16,8 @@ package com.android.quickstep.views; +import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN; + import android.content.Context; import android.content.res.Configuration; import android.graphics.Bitmap; @@ -28,12 +30,15 @@ import android.graphics.Paint; import android.graphics.Rect; import android.graphics.Shader; import android.util.AttributeSet; +import android.util.FloatProperty; +import android.util.Property; import android.view.View; import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; +import com.android.launcher3.util.SystemUiController; import com.android.quickstep.TaskOverlayFactory; import com.android.quickstep.TaskOverlayFactory.TaskOverlay; import com.android.systemui.shared.recents.model.Task; @@ -46,6 +51,19 @@ public class TaskThumbnailView extends View { private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256]; + public static final Property DIM_ALPHA_MULTIPLIER = + new FloatProperty("dimAlphaMultiplier") { + @Override + public void setValue(TaskThumbnailView thumbnail, float dimAlphaMultiplier) { + thumbnail.setDimAlphaMultipler(dimAlphaMultiplier); + } + + @Override + public Float get(TaskThumbnailView thumbnailView) { + return thumbnailView.mDimAlphaMultiplier; + } + }; + private final float mCornerRadius; private final BaseActivity mActivity; @@ -62,6 +80,7 @@ public class TaskThumbnailView extends View { protected BitmapShader mBitmapShader; private float mDimAlpha = 1f; + private float mDimAlphaMultiplier = 1f; public TaskThumbnailView(Context context) { this(context, null); @@ -109,8 +128,15 @@ public class TaskThumbnailView extends View { updateThumbnailPaintFilter(); } + public void setDimAlphaMultipler(float dimAlphaMultipler) { + mDimAlphaMultiplier = dimAlphaMultipler; + setDimAlpha(mDimAlpha); + } + /** * Sets the alpha of the dim layer on top of this view. + * + * If dimAlpha is 0, no dimming is applied; if dimAlpha is 1, the thumbnail will be black. */ public void setDimAlpha(float dimAlpha) { mDimAlpha = dimAlpha; @@ -124,32 +150,53 @@ public class TaskThumbnailView extends View { return new Rect(); } + public int getSysUiStatusNavFlags() { + if (mThumbnailData != null) { + int flags = 0; + flags |= (mThumbnailData.systemUiVisibility & SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0 + ? SystemUiController.FLAG_LIGHT_STATUS + : SystemUiController.FLAG_DARK_STATUS; + flags |= (mThumbnailData.systemUiVisibility & SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR) != 0 + ? SystemUiController.FLAG_LIGHT_NAV + : SystemUiController.FLAG_DARK_NAV; + return flags; + } + return 0; + } + @Override protected void onDraw(Canvas canvas) { - if (mTask == null) { - return; - } - int width = getMeasuredWidth(); - int height = getMeasuredHeight(); - if (mClipBottom > 0 && !mTask.isLocked) { - canvas.save(); - canvas.clipRect(0, 0, width, mClipBottom); + drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(), mCornerRadius); + } - canvas.drawRoundRect(0, 0, width, height, mCornerRadius, mCornerRadius, mPaint); - canvas.restore(); + public float getCornerRadius() { + return mCornerRadius; + } + + public void drawOnCanvas(Canvas canvas, float x, float y, float width, float height, + float cornerRadius) { + // Draw the background in all cases, except when the thumbnail data is opaque + final boolean drawBackgroundOnly = mTask == null || mTask.isLocked || mBitmapShader == null + || mThumbnailData == null; + if (drawBackgroundOnly || mClipBottom > 0 || mThumbnailData.isTranslucent) { + canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mBackgroundPaint); + if (drawBackgroundOnly) { + return; + } + } + + if (mClipBottom > 0) { canvas.save(); - canvas.clipRect(0, mClipBottom, width, height); - canvas.drawRoundRect(0, 0, width, height, mCornerRadius, mCornerRadius, - mBackgroundPaint); + canvas.clipRect(x, y, width, mClipBottom); + canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mPaint); canvas.restore(); } else { - canvas.drawRoundRect(0, 0, width, height, mCornerRadius, - mCornerRadius, mTask.isLocked ? mBackgroundPaint : mPaint); + canvas.drawRoundRect(x, y, width, height, cornerRadius, cornerRadius, mPaint); } } private void updateThumbnailPaintFilter() { - int mul = (int) (mDimAlpha * 255); + int mul = (int) ((1 - mDimAlpha * mDimAlphaMultiplier) * 255); if (mBitmapShader != null) { LightingColorFilter filter = getLightingColorFilter(mul); mPaint.setColorFilter(filter); @@ -167,9 +214,9 @@ public class TaskThumbnailView extends View { if (mBitmapShader != null && mThumbnailData != null) { float scale = mThumbnailData.scale; Rect thumbnailInsets = mThumbnailData.insets; - float thumbnailWidth = mThumbnailData.thumbnail.getWidth() - + final float thumbnailWidth = mThumbnailData.thumbnail.getWidth() - (thumbnailInsets.left + thumbnailInsets.right) * scale; - float thumbnailHeight = mThumbnailData.thumbnail.getHeight() - + final float thumbnailHeight = mThumbnailData.thumbnail.getHeight() - (thumbnailInsets.top + thumbnailInsets.bottom) * scale; final float thumbnailScale; @@ -185,7 +232,8 @@ public class TaskThumbnailView extends View { // Rotate the screenshot if not in multi-window mode rotate = FeatureFlags.OVERVIEW_USE_SCREENSHOT_ORIENTATION && configuration.orientation != mThumbnailData.orientation && - !mActivity.isInMultiWindowModeCompat(); + !mActivity.isInMultiWindowModeCompat() && + mThumbnailData.windowingMode == WINDOWING_MODE_FULLSCREEN; // Scale the screenshot to always fit the width of the card. thumbnailScale = rotate ? getMeasuredWidth() / thumbnailHeight @@ -216,7 +264,8 @@ public class TaskThumbnailView extends View { mMatrix.postScale(thumbnailScale, thumbnailScale); mBitmapShader.setLocalMatrix(mMatrix); - float bitmapHeight = Math.max(thumbnailHeight * thumbnailScale, 0); + float bitmapHeight = Math.max((rotate ? thumbnailWidth : thumbnailHeight) + * thumbnailScale, 0); if (Math.round(bitmapHeight) < getMeasuredHeight()) { mClipBottom = bitmapHeight; } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index f04acaf12e..82aa45a18c 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -16,28 +16,34 @@ package com.android.quickstep.views; +import static android.widget.Toast.LENGTH_SHORT; +import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA_MULTIPLIER; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.app.ActivityOptions; import android.content.Context; import android.content.res.Resources; import android.graphics.Outline; -import android.graphics.Rect; import android.os.Bundle; import android.os.Handler; import android.util.AttributeSet; +import android.util.FloatProperty; +import android.util.Log; +import android.util.Property; import android.view.View; import android.view.ViewOutlineProvider; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; -import android.widget.ImageView; +import android.widget.Toast; import com.android.launcher3.BaseActivity; import com.android.launcher3.BaseDraggingActivity; -import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; -import com.android.quickstep.RecentsAnimationInterpolator; import com.android.quickstep.TaskSystemShortcut; import com.android.quickstep.TaskUtils; import com.android.quickstep.views.RecentsView.PageCallbacks; @@ -54,6 +60,8 @@ import java.util.function.Consumer; */ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallbacks { + private static final String TAG = TaskView.class.getSimpleName(); + /** A curve of x from 0 to 1, where 0 is the center of the screen and 1 is the edge. */ private static final TimeInterpolator CURVE_INTERPOLATOR = x -> (float) -Math.cos(x * Math.PI) / 2f + .5f; @@ -69,12 +77,28 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback */ private static final float EDGE_SCALE_DOWN_FACTOR = 0.03f; - private static final long SCALE_ICON_DURATION = 120; + public static final long SCALE_ICON_DURATION = 120; + private static final long DIM_ANIM_DURATION = 700; + + public static final Property ZOOM_SCALE = + new FloatProperty("zoomScale") { + @Override + public void setValue(TaskView taskView, float v) { + taskView.setZoomScale(v); + } + + @Override + public Float get(TaskView taskView) { + return taskView.mZoomScale; + } + }; private Task mTask; private TaskThumbnailView mSnapshotView; - private ImageView mIconView; + private IconView mIconView; private float mCurveScale; + private float mZoomScale; + private Animator mDimAlphaAnim; public TaskView(Context context) { this(context, null); @@ -87,11 +111,13 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback public TaskView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setOnClickListener((view) -> { - if (mTask != null) { - launchTask(true /* animate */); - BaseActivity.fromContext(context).getUserEventDispatcher().logTaskLaunchOrDismiss( - Touch.TAP, Direction.NONE, TaskUtils.getComponentKeyForTask(mTask.key)); + if (getTask() == null) { + return; } + launchTask(true /* animate */); + BaseActivity.fromContext(context).getUserEventDispatcher().logTaskLaunchOrDismiss( + Touch.TAP, Direction.NONE, ((RecentsView) getParent()).indexOfChild(this), + TaskUtils.getComponentKeyForTask(getTask().key)); }); setOutlineProvider(new TaskOutlineProvider(getResources())); } @@ -124,8 +150,16 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback return mSnapshotView; } + public IconView getIconView() { + return mIconView; + } + public void launchTask(boolean animate) { - launchTask(animate, null, null); + launchTask(animate, (result) -> { + if (!result) { + notifyTaskLaunchFailed(TAG); + } + }, getHandler()); } public void launchTask(boolean animate, Consumer resultCallback, @@ -146,7 +180,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback @Override public void onTaskDataLoaded(Task task, ThumbnailData thumbnailData) { mSnapshotView.setThumbnail(task, thumbnailData); - mIconView.setImageDrawable(task.icon); + mIconView.setDrawable(task.icon); mIconView.setOnClickListener(icon -> TaskMenuView.showForTask(this)); mIconView.setOnLongClickListener(icon -> { requestDisallowInterceptTouchEvent(true); @@ -157,7 +191,7 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback @Override public void onTaskDataUnloaded() { mSnapshotView.setThumbnail(null, null); - mIconView.setImageDrawable(null); + mIconView.setDrawable(null); mIconView.setOnLongClickListener(null); } @@ -166,23 +200,37 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback // Do nothing } - public void animateIconToScale(float scale) { + public void animateIconToScaleAndDim(float scale) { mIconView.animate().scaleX(scale).scaleY(scale).setDuration(SCALE_ICON_DURATION).start(); + mDimAlphaAnim = ObjectAnimator.ofFloat(mSnapshotView, DIM_ALPHA_MULTIPLIER, 1 - scale, + scale); + mDimAlphaAnim.setDuration(DIM_ANIM_DURATION); + mDimAlphaAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mDimAlphaAnim = null; + } + }); + mDimAlphaAnim.start(); } - protected void setIconScale(float iconScale) { + protected void setIconScaleAndDim(float iconScale) { mIconView.animate().cancel(); mIconView.setScaleX(iconScale); mIconView.setScaleY(iconScale); + if (mDimAlphaAnim != null) { + mDimAlphaAnim.cancel(); + } + mSnapshotView.setDimAlphaMultipler(iconScale); } public void resetVisualProperties() { - setScaleX(1f); - setScaleY(1f); + setZoomScale(1); setTranslationX(0f); setTranslationY(0f); setTranslationZ(0); setAlpha(1f); + setIconScaleAndDim(1); } @Override @@ -190,40 +238,52 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(scrollState.linearInterpolation); - mSnapshotView.setDimAlpha(1 - curveInterpolation * MAX_PAGE_SCRIM_ALPHA); + mSnapshotView.setDimAlpha(curveInterpolation * MAX_PAGE_SCRIM_ALPHA); + setCurveScale(getCurveScaleForCurveInterpolation(curveInterpolation)); + } - mCurveScale = 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR; - setScaleX(mCurveScale); - setScaleY(mCurveScale); + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + setPivotX((right - left) * 0.5f); + setPivotY(mSnapshotView.getTop() + mSnapshotView.getHeight() * 0.5f); + } + + public float getCurveScaleForInterpolation(float linearInterpolation) { + float curveInterpolation = CURVE_INTERPOLATOR.getInterpolation(linearInterpolation); + return getCurveScaleForCurveInterpolation(curveInterpolation); + } + + private float getCurveScaleForCurveInterpolation(float curveInterpolation) { + return 1 - curveInterpolation * EDGE_SCALE_DOWN_FACTOR; + } + + private void setCurveScale(float curveScale) { + mCurveScale = curveScale; + onScaleChanged(); } public float getCurveScale() { return mCurveScale; } + public void setZoomScale(float adjacentScale) { + mZoomScale = adjacentScale; + onScaleChanged(); + } + + private void onScaleChanged() { + float scale = mCurveScale * mZoomScale; + setScaleX(scale); + setScaleY(scale); + } + @Override public boolean hasOverlappingRendering() { // TODO: Clip-out the icon region from the thumbnail, since they are overlapping. return false; } - public RecentsAnimationInterpolator getRecentsInterpolator() { - Rect taskViewBounds = new Rect(); - BaseDraggingActivity activity = BaseDraggingActivity.fromContext(getContext()); - DeviceProfile dp = activity.getDeviceProfile(); - activity.getDragLayer().getDescendantRectRelativeToSelf(this, taskViewBounds); - - // TODO: Use the actual target insets instead of the current thumbnail insets in case the - // device state has changed - return new RecentsAnimationInterpolator( - new Rect(0, 0, dp.widthPx, dp.heightPx), - getThumbnail().getInsets(), - taskViewBounds, - new Rect(0, getThumbnail().getTop(), 0, 0), - getScaleX(), - getTranslationX()); - } - private static final class TaskOutlineProvider extends ViewOutlineProvider { private final int mMarginTop; @@ -281,4 +341,13 @@ public class TaskView extends FrameLayout implements TaskCallbacks, PageCallback return super.performAccessibilityAction(action, arguments); } + + public void notifyTaskLaunchFailed(String tag) { + String msg = "Failed to launch task"; + if (mTask != null) { + msg += " (task=" + mTask.key.baseIntent + " userId=" + mTask.key.userId + ")"; + } + Log.w(tag, msg); + Toast.makeText(getContext(), R.string.activity_not_available, LENGTH_SHORT).show(); + } } diff --git a/res/animator-v23/discovery_bounce.xml b/res/animator-v23/discovery_bounce.xml index 8d0e8fdfb5..f5548537b1 100644 --- a/res/animator-v23/discovery_bounce.xml +++ b/res/animator-v23/discovery_bounce.xml @@ -26,14 +26,14 @@ android:fraction="0" android:value="1f" /> + android:value="0.9738f" /> + android:width="@dimen/vertical_drag_handle_size" + android:height="@dimen/vertical_drag_handle_size" + android:viewportWidth="36.0" + android:viewportHeight="36.0" > + android:translateX="11.5" + android:translateY="11.5"> diff --git a/res/drawable/ic_drag_indicator.xml b/res/drawable/ic_drag_indicator.xml deleted file mode 100644 index d50bdd3fdf..0000000000 --- a/res/drawable/ic_drag_indicator.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/res/layout/all_apps.xml b/res/layout/all_apps.xml index 450d1074c9..5e7b117c43 100644 --- a/res/layout/all_apps.xml +++ b/res/layout/all_apps.xml @@ -31,8 +31,6 @@ - diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml index a4acf06be5..da17b2b315 100644 --- a/res/layout/launcher.xml +++ b/res/layout/launcher.xml @@ -18,7 +18,6 @@ android:id="@+id/launcher" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="?attr/workspaceStatusBarScrim" android:fitsSystemWindows="true"> @@ -57,6 +56,9 @@ android:id="@+id/drop_target_bar" layout="@layout/drop_target_bar" /> + + - - - + android:layout_width="match_parent" + android:layout_height="match_parent" + android:id="@+id/scrim_view" /> \ No newline at end of file diff --git a/res/layout/search_container_all_apps.xml b/res/layout/search_container_all_apps.xml index 14d7b53b65..fd9cb60fc7 100644 --- a/res/layout/search_container_all_apps.xml +++ b/res/layout/search_container_all_apps.xml @@ -20,7 +20,6 @@ android:layout_height="@dimen/all_apps_search_bar_field_height" android:layout_centerHorizontal="true" android:layout_gravity="top|center_horizontal" - android:layout_marginTop="8dp" android:background="@drawable/bg_all_apps_searchbox" android:elevation="1dp" android:focusableInTouchMode="true" diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index 02dd1c98a4..87924e79b3 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -79,8 +79,10 @@ "Vouer: %1$s" "Legstukke" "Muurpapiere" - "Home-instellings" + "Tuis-instellings" "Gedeaktiveer deur jou administrateur" + "Laat toe dat tuisskerm gedraai word" + "Wanneer foon gedraai word" "Kennisgewingkolle" "Aan" "Af" @@ -128,8 +130,8 @@ "Verminder hoogte" "Legstukgrootte is verander na breedte %1$s hoogte %2$s" "Kortpaaie" - "%1$d kortpaaie vir %2$s" - "%1$d kortpaaie en %2$d kennisgewings vir %3$s" + + "Maak toe" "Kennisgewing is toegemaak" "Persoonlik" diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index 21b01ddb09..46647c62d9 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -81,6 +81,8 @@ "የግድግዳ ወረቀቶች" "የመነሻ ቅንብሮች" "በእርስዎ አስተዳዳሪ የተሰናከለ" + "የመነሻ ማያ ገጽ ማሽከርከርን ይፍቀዱ" + "ስልኩ ሲዞር" "የማሳወቂያ ነጥቦች" "በርቷል" "ጠፍቷል" @@ -128,8 +130,8 @@ "ቁመት ይቀንሱ" "የመግብር መጠን ወደ ስፋት %1$s ቁመት %2$s ተለውጧል" "አቋራጮች" - "%1$d%2$s አቋራጮች" - "%1$d አቋራጮች እና %2$d ማሳወቂያዎች ለ%3$s" + + "አሰናብት" "ማሳወቂያ ተሰናብቷል" "የግል" diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index 8598a8bb85..c094c3ad8b 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -24,13 +24,13 @@ "العمل" "لم يتم تثبيت التطبيق." "التطبيق ليس متاحًا" - "تم تعطيل التطبيق الذي تم تنزيله في الوضع الآمن" - "الأدوات معطلة في الوضع الآمن" + "تم إيقاف التطبيق الذي تم تنزيله في الوضع الآمن" + "الأدوات غير مفعّلة في الوضع الآمن" "الاختصار غير متاح" "الشاشة الرئيسية" "الإجراءات المخصّصة" "المس مع الاستمرار لاختيار إحدى الأدوات." - "انقر نقرًا مزدوجًا مع الاستمرار لاختيار أداة أو استخدم الإجراءات المخصصة." + "انقر مرّتين مع الاستمرار لاختيار أداة أو استخدم الإجراءات المخصصة." "%1$d × %2$d" "‏العرض %1$d الطول %2$d" "انقر مع الاستمرار لإضافة العنصر يدويًا" @@ -41,7 +41,7 @@ "البحث عن مزيد من التطبيقات" "الإشعارات" "انقر مع الاستمرار لاختيار اختصار." - "يمكنك النقر نقرًا مزدوجًا مع الاستمرار لاختيار اختصار أو استخدام الإجراءات المخصصة." + "يمكنك النقر مرّتين مع الاستمرار لاختيار اختصار أو استخدام الإجراءات المخصصة." "ليس هناك مساحة أخرى في هذه الشاشة الرئيسية." "لا يوجد المزيد من الحقول في علبة المفضلة" "قائمة التطبيقات" @@ -63,7 +63,7 @@ "الإعداد" "هذا تطبيق نظام وتتعذر إزالته." "مجلد بدون اسم" - "تم تعطيل %1$s" + "تم إيقاف %1$s" %1$s، به %2$d إشعار %1$s، به إشعاران (%2$d) @@ -84,11 +84,13 @@ "الأدوات" "الخلفيات" "إعدادات الصفحة الرئيسية" - "عطَّل المشرف هذه الميزة" + "أوقف المشرف هذه الميزة" + "السماح بتدوير الشاشة الرئيسية" + "عند تدوير الهاتف" "نقاط الإشعارات" "قيد التشغيل" - "قيد الإيقاف" - "يلزم تمكين الوصول إلى الإشعارات" + "غير مفعّل" + "يلزم تفعيل الوصول إلى الإشعارات" "لعرض نقاط الإشعارات، يجب تشغيل إشعارات التطبيق في %1$s" "تغيير الإعدادات" "عرض نقاط الإشعارات" @@ -96,7 +98,7 @@ "للتطبيقات الجديدة" "تغيير شكل الرمز" "على الشاشة الرئيسية" - "استخدام الإعداد الافتراضي للنظام" + "استخدام الإعداد التلقائي للنظام" "مربّع" "رمز دائري مربّع" "دائرة" @@ -132,8 +134,8 @@ "تقليل الارتفاع" "تم تغيير حجم الأداة إلى العرض %1$s والارتفاع %2$s" "الاختصارات" - "%1$d اختصار لتطبيق %2$s" - "هناك %1$d اختصار و%2$d إشعار عن %3$s" + + "تجاهل" "تم تجاهل الإشعار" "شخصية" diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml new file mode 100644 index 0000000000..41deec31ec --- /dev/null +++ b/res/values-as/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "কৰ্মস্থান" + "এপটো ইনষ্টল কৰা নহ\'ল।" + "এপটো নাই" + "ডাউনল\'ড কৰা এপটোক সুৰক্ষিত ম\'ডত অক্ষম কৰা হ\'ল" + "ৱিজেটবোৰক সুৰক্ষিত ম\'ডত অক্ষম কৰা হ\'ল" + "শ্বৰ্টকাট নাই" + "গৃহ স্ক্ৰীণ" + "উপযোগিতা অনুসৰি কৰা কাৰ্যবিলাক" + "কোনো ৱিজেট বাছনি কৰিবলৈ স্পৰ্শ কৰি থাকক।" + "কোনো ৱিজেট বাছনি কৰিবলৈ অথবা উপযোগিতা অনুসৰি কাৰ্যবিলাক ব্য়ৱহাৰ কৰিবলৈ দুবাৰ টিপি থাকক।" + "%1$d × %2$d" + "%1$d বহল x %2$d ওখ" + "মেনুৱেলভাৱে ৰাখিবলৈ স্পৰ্শ কৰি থাকক" + "স্বয়ংক্ৰিয়ভাবে যোগ কৰক" + "এপসমূহ সন্ধান কৰক" + "এপসমূহ ল’ড কৰি থকা হৈছে…" + "\"%1$s\"ৰ সৈতে মিলা কোনো এপ্ বিচাৰি পোৱা নগ\'ল" + "আৰু অধিক এপবোৰ সন্ধান কৰক" + "জাননীসমূহ" + "কোনো শ্বৰ্টকাট বাছনি কৰিবলৈ স্পৰ্শ কৰি হেঁচি ধৰক।" + "কোনো শ্বৰ্টকাট বাছনি কৰিবলৈ দুবাৰ টিপি হেঁচি ধৰক, বা নিজৰ উপযোগিতা অনুসৰি সৃষ্টি কৰা কাৰ্যসমূহ ব্যৱহাৰ কৰক।" + "এই গৃহ স্ক্ৰীণত আৰু বেছি ঠাই নাই।" + "পছন্দৰ ট্ৰে\'ত আৰু বেছি ঠাই নাই" + "এপৰ সূচী" + "ব্যক্তিগত এপৰ তালিকা" + "কৰ্মস্থানৰ এপৰ তালিকা" + "গৃহপৃষ্ঠা" + "আঁতৰাওক" + "আনইনষ্টল কৰক" + "এপ সম্পৰ্কীয় তথ্য" + "ইনষ্টল কৰক" + "শ্বৰ্টকাট ইনষ্টল কৰিব পাৰে" + "ব্য়ৱহাৰকাৰীৰ হস্তক্ষেপ অবিহনেই কোনো এপক শ্বৰ্টকাটবোৰ যোগ কৰাৰ অনুমতি দিয়ে।" + "গৃহ ছেটিং আৰু শ্বৰ্টকাটবোৰ পঢ়িব পাৰে" + "এপটোক গৃহ পৃষ্ঠাত ছেটিং আৰু শ্বৰ্টকাটসমূহ পঢ়াৰ অনুমতি দিয়ে।" + "গৃহ ছেটিং আৰু শ্বৰ্টকাটবোৰ লিখিব পাৰে" + "এপটোক গৃহ পৃষ্ঠাত ছেটিং আৰু শ্বৰ্টকাটসমূহ সলনি কৰাৰ অনুমতি দিয়ে।" + "%1$sক ফ\'ন কলবোৰ কৰাৰ অনুমতি দিয়া হোৱা নাই" + "ৱিজেট ল\'ড কৰাত সমস্য়া" + "ছেটআপ কৰক" + "এইটো এটা ছিষ্টেম এপ আৰু ইয়াক আনইনষ্টল কৰিব নোৱৰি" + "নামবিহীন ফ\'ল্ডাৰ" + "%1$s অক্ষম কৰা হ\'ল" + + %1$s%2$dটা জাননী আছে + %1$s%2$dটা জাননী আছে + + "%2$dৰ %1$d পৃষ্ঠা" + "গৃহ স্ক্ৰীণ %2$dৰ %1$d" + "গৃহ স্ক্ৰীণৰ নতুন পৃষ্ঠা" + "ফ’ল্ডাৰ খোলা হ\'ল, %1$d x %2$d" + "ফ\'ল্ডাৰ বন্ধ কৰিবলৈ টিপক" + "সলনি কৰা নাম ছেভ কৰিবলৈ টিপক" + "ফ\'ল্ডাৰ বন্ধ কৰা হ\'ল" + "ফ\'ল্ডাৰৰ নাম সলনি কৰি %1$s কৰা হৈছে" + "ফ’ল্ডাৰ: %1$s" + "ৱিজেটসমূহ" + "ৱালপেপাৰসমূহ" + "গৃহ ছেটিংসমূহ" + "আপোনাৰ প্ৰশাসকে অক্ষম কৰি ৰাখিছে" + "গৃহ স্ক্ৰীণ ঘূৰোৱাৰ অনুমতি দিয়ক" + "ফ\'নটো যেতিয়া ঘূৰোৱা হয়" + "জাননী সম্পৰ্কীয় বিন্দুবোৰ" + "অন অৱস্থাত আছে" + "অফ অৱস্থাত আছে" + "জাননী চাবলৈ অনুমতিৰ প্ৰয়োজন" + "জাননী সম্পৰ্কীয় বিন্দুবোৰ দেখুৱাবলৈ %1$sৰ বাবে এপৰ জাননীসমূহ অন কৰক" + "ছেটিংসমূহ সলনি কৰক" + "জাননী বিন্দুসমূহ দেখুৱাওক" + "গৃহ স্ক্ৰীণত আইকনটো যোগ কৰক" + "নতুন এপসমূহৰ বাবে" + "আইকনৰ আকৃতি সলনি কৰক" + "গৃহ স্ক্ৰীণত" + "ছিষ্টেম ডিফ\'ল্ট ব্য়ৱহাৰ কৰক" + "বৰ্গাকাৰ" + "বৰ্গবৃত্তাকাৰ" + "পৰিচিত মানুহৰ গোট" + "চকুপানীৰ টোপাল" + "আইকনৰ আকৃতিত কৰা পৰিবৰ্তনবোৰ প্ৰয়োগ কৰি থকা হৈছে" + "অজ্ঞাত" + "আঁতৰাওক" + "সন্ধান কৰক" + "এই এপটো ইনষ্টল কৰা হোৱা নাই" + "এই আইকনৰ এপটো ইনষ্টল কৰা হোৱা নাই। আপুনি এইটো আঁতৰাব পাৰে অথবা এপটো বিচাৰি মেনুৱেলভাৱে ইনষ্টল কৰিব পাৰে।" + "%1$s ডাউনল\'ড কৰি থকা হৈছে, %2$s সম্পূৰ্ণ হ\'ল" + "%1$s ইনষ্টল হোৱালৈ অপেক্ষা কৰি থকা হৈছে" + "%1$s ৱিজেট" + "গৃহ স্ক্ৰীণত যোগ কৰক" + "বস্তুটো ইয়ালৈ স্থানান্তৰ কৰক" + "বস্তুটো গৃহ স্ক্ৰীণত যোগ কৰা হ\'ল" + "বস্তুটো আঁতৰোৱা হ\'ল" + "বস্তু স্থানান্তৰ কৰক" + "শাৰী %1$s স্তম্ভ %2$sলৈ স্থানান্তৰিত কৰক" + "পছন্দৰ অৱস্থান %1$sলৈ স্থানান্তৰিত কৰক" + "পছন্দৰ অৱস্থান %1$sলৈ স্থানান্তৰিত কৰক" + "বস্তুটো স্থানান্তৰ কৰা হ\'ল" + "ফ\'ল্ডাৰত যোগ কৰক: %1$s" + "%1$sসহ ফ\'ল্ডাৰত যোগ কৰক" + "বস্তুটো ফ\'ল্ডাৰত যোগ কৰা হ\'ল" + "%1$s: ৰ জৰিয়তে ফ\'ল্ডাৰ সৃষ্টি কৰক" + "ফ\'ল্ডাৰ সৃষ্টি কৰা হ\'ল" + "হ\'ম স্ক্ৰীণলৈ স্থানান্তৰ কৰক" + "আকাৰ সলনি কৰক" + "প্ৰস্থ বৃদ্ধি কৰক" + "উচ্চতা বৃদ্ধি কৰক" + "প্ৰস্থ হ্ৰাস কৰক" + "উচ্চতা হ্ৰাস কৰক" + "ৱিজেটৰ আকাৰ সলনি কৰি প্ৰস্থ %1$s আৰু উচ্চতা %2$s কৰা হ\'ল" + "শ্বৰ্টকাটসমূহ" + + + "অগ্ৰাহ্য কৰক" + "জাননী অগ্ৰাহ্য কৰা হৈছে" + "ব্যক্তিগত" + "কৰ্মস্থান" + "কৰ্মস্থানৰ প্ৰ\'ফাইল" + "ইয়াত কৰ্মস্থানৰ এপ্ বিচাৰি পাওক" + "কৰ্মস্থানৰ প্ৰতিটো এপৰে একোটা প্ৰতীক আছে আৰু তাক আপোনাৰ প্ৰতিষ্ঠানে সুৰক্ষিত কৰি ৰাখে। ব্যৱহাৰ কৰাত সুবিধা হ\'বলৈ এপসমূহ আপোনাৰ গৃহ স্ক্ৰীণলৈ স্থানান্তৰ কৰক।" + "আপোনাৰ প্ৰতিষ্ঠানৰ দ্বাৰা পৰিচালিত" + "জাননী আৰু এপসমূহ অফ হৈ আছে" + "বন্ধ কৰক" + "বন্ধ" + diff --git a/res/values-az-rAZ/strings.xml b/res/values-az-rAZ/strings.xml new file mode 100644 index 0000000000..ed86f91552 --- /dev/null +++ b/res/values-az-rAZ/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "İş" + "Tətbiq quraşdırılmayıb." + "Tətbiq əlçatmazdır" + "Güvənli rejimdə icazə verilməyən tətbiq endirildi" + "Vidcetlər Güvənli rejimdə deaktiv edilib" + "Qısayol əlçatan deyil" + "Əsas ekran" + "Fərdi əməliyyatlar" + "Vidceti götürmək üçün toxunub saxlayın." + "Vidceti götürmək üçün & iki dəfə toxunub saxlayın və ya fərdi fəaliyyətləri istifadə edin." + "%1$d × %2$d" + "%2$d hündürlük %1$d enində" + "Manual olaraq yerləşdirmək üçün toxunaraq basıb saxlayın" + "Avtomatik əlavə edin" + "Tətbiqləri axtarın" + "Tətbiqlər yüklənir…" + "%1$s sorğusuna uyğun tətbiq tapılmadı" + "Daha çox tətbiq üçün axtarış edin" + "Bildirişlər" + "Qısayolu seçmək üçün basıb saxlayın." + "Qısayolu seçmək üçün iki dəfə basıb saxlayın və ya fərdi əməliyyatlardan istifadə edin." + "Bu Əsas ekranda boş yer yoxdur." + "Favoritlər-də yer yoxdur" + "Tətbiq siyahısı" + "Şəxsi tətbiqlərin siyahısı" + "İş tətbiqlərinin siyahısı" + "Əsas səhifə" + "Silin" + "Sistemdən sil" + "Tətbiq məlumatı" + "Quraşdırın" + "qısayolları quraşdır" + "Tətbiqə istifadəçi müdaxiləsi olmadan qısayolları əlavə etməyə icazə verir." + "Əsas Səhifə ayarlarını və qısayolları oxuyun" + "Tətbiqə Əsas Səhifədə parametrləri və qısayolları oxumağa icazə verir." + "Əsas Səhifə ayarlarını və qısayolları yazın" + "Tətbiqə Əsas Səhifədə ayarları və qısayolları dəyişməyə icazə verir." + "%1$s tətbiqinə telefon zəngləri etmək üçün icazə verilmir" + "Vidcet yükləmə problemi" + "Quraşdırma" + "Bu sistem tətbiqi olduğu üçün sistemdən silinə bilməz." + "Adsız Qovluq" + "%1$s deaktiv edildi" + + %1$s tətbiqində %2$d bildiriş var + %1$s tətbiqində %2$d bildiriş var + + "Səhifə %1$d of %2$d" + "Əsas Səhifə ekranı %1$d of %2$d" + "Yeni əsas ekran səhifəsi" + "Qovluq açıldı, %2$d hündürlük ilə %1$d enində" + "Qovluq bağlamaq üçün toxunun" + "Ad dəyişikliyini yadda saxlamaq üçün toxunun" + "Qovluq bağlıdır" + "Qovluq adı %1$s ilə dəyişdirildi" + "Qovluq: %1$s" + "Vidcet" + "Divar kağızları" + "Home ayarları" + "Admininiz tərəfindən deaktiv edilib" + "Əsas ekranın firlanmağına icazə verin" + "Telefon çevrilən zaman" + "Bildiriş nişanı" + "Aktiv" + "Deaktiv" + "Bildiriş girişi tələb edilir" + "Bildiriş Nöqtələrini göstərmək üçün %1$s bildirişlərini aktiv edin" + "Ayarları dəyişin" + "Bildiriş nöqtələrini göstərin" + "Əsas ekrana ikona əlavə edin" + "Yeni tətbiqlər üçün" + "İkona formasını dəyişin" + "Əsas səhifə ekranında" + "Sistem defoltu istifadə edin" + "Kvadrat" + "Kənarları dairəvi kvadrat" + "Çevrə" + "Gözyaşı damlası" + "İkona formasına etdiyiniz dəyişikliklər tətbiq edilir" + "Naməlum" + "Yığışdır" + "Axtarış" + "Bu tətbiq quraşdırılmayıb" + "Bu ikona üçün tətbiq quraşdırılmayıb. Onu silə bilərsiniz, və ya tətbiqi taparaq manual yol ilə quraşdıra bilərsiniz." + "%1$s endirilir, %2$s tamamlandı" + "%1$s yüklənmək üçün gözləyir" + "%1$s vidcetləri" + "Əsas ekrana əlavə edin" + "Elementi bura köçürün" + "Element əsas ekrana əlavə edildi" + "Element silindi" + "Elementi köçürün" + "Sıra %1$s sütun %2$s köçürün" + "%1$s mövqeyinə köçürün" + "%1$s sevimlilər mövqeyinə köçürün" + "Elementin yeri dəyişildi" + "Qovluğa əlavə edin: %1$s" + "%1$s adlı qovluğa əlavə edin" + "Element qovluğa əlavə edildi" + "Qovluq yaradın: %1$s" + "Qovluq yaradıldı" + "Əsas ekrana köçürün" + "Ölçüsünü dəyişin" + "Eni artırın" + "Hündürlüyü artırın" + "Eni azaldın" + "Hündürlüyü azaldın" + "Vidcetin eni %1$s hündürlüyü %2$s kimi ölçüləndirildi" + "Qısa yollar" + "%1$d üçün %2$s qısa yolu" + "%3$s üçün %1$d qısayol və %2$d bildiriş" + "Rədd edin" + "Bildiriş rədd edildi" + "Şəxsi" + "İş" + "İş profili" + "Burada iş tətbiqləri axtarın" + "Hər bir iş tətbiqində təşkilat tərəfindən qorunduğunu göstərən narıncı nişan var. Tətbiqləri daha asan giriş üçün Əsas Səhifə Ekranına köçürün." + "Təşkilatınız tərəfindən idarə olunur" + "Bildiriş və tətbiqlər deaktivdir" + "Bağlayın" + "Bağlıdır" + diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index a0a1f57731..dd0f022a1b 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -81,6 +81,8 @@ "Divar kağızları" "Home ayarları" "Admininiz tərəfindən deaktiv edilib" + "Əsas ekranın firlanmağına icazə verin" + "Telefon çevrilən zaman" "Bildiriş nişanı" "Aktiv" "Deaktiv" @@ -128,8 +130,8 @@ "Hündürlüyü azaldın" "Vidcetin eni %1$s hündürlüyü %2$s kimi ölçüləndirildi" "Qısa yollar" - "%1$d üçün %2$s qısa yolu" - "%3$s üçün %1$d qısayol və %2$d bildiriş" + + "Rədd edin" "Bildiriş rədd edildi" "Şəxsi" diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 275cf0f250..9a2062f84f 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -82,6 +82,8 @@ "Pozadine" "Podešavanja početnog ekrana" "Administrator je onemogućio" + "Dozvoli rotaciju početnog ekrana" + "Kada se telefon rotira" "Tačke za obaveštenja" "Uključeno" "Isključeno" @@ -129,8 +131,8 @@ "Smanji visinu" "Veličina vidžeta je promenjena na širinu %1$s i visinu %2$s" "Prečice" - "%1$d prečice(a) za %2$s" - "Prečice (%1$d) i obaveštenja (%2$d) za %3$s" + + "Odbaci" "Obaveštenje je odbačeno" "Lične" diff --git a/res/values-be-rBY/strings.xml b/res/values-be-rBY/strings.xml new file mode 100644 index 0000000000..399ae763e7 --- /dev/null +++ b/res/values-be-rBY/strings.xml @@ -0,0 +1,148 @@ + + + + + "Launcher3" + + "Працоўная" + "Праграма не ўсталявана." + "Праграма недаступная" + "Спампаваная праграма адключана ў Бяспечным рэжыме" + "Віджэты адключаны ў Бяспечным рэжыме" + "Ярлык недаступны" + "Галоўны экран" + "Спецыяльныя дзеянні" + "Дакраніцеся і ўтрымлiвайце віджэт, каб выбр. яго." + "Дакраніцеся двойчы і ўтрымлівайце, каб выбраць віджэт або выкарыстоўваць карыстальніцкія дзеянні." + "%1$d × %2$d" + "Шырына: %1$d, вышыня: %2$d" + "Каб размясціць уручную, дакраніцеся і ўтрымлівайце" + "Дадаць аўтаматычна" + "Пошук праграм" + "Праграмы загружаюцца…" + "Праграм, якія адпавядаюць запыту \"%1$s\", не знойдзена" + "Шукаць іншыя праграмы" + "Апавяшчэнні" + "Дакраніцеся і ўтрымлiвайце ярлык, каб дадаць яго." + "Дакраніцеся двойчы і ўтрымлівайце, каб выбраць ярлык або выкарыстоўваць спецыяльныя дзеянні." + "На гэтым Галоўным экране больш няма месца." + "У латку \"Абранае\" больш няма месца" + "Спіс праграм" + "Спіс персанальных праграм" + "Спіс працоўных праграм" + "Галоўная" + "Выдаліць" + "Выдаліць" + "Звесткі пра праграмы" + "Усталяваць" + "усталёўваць ярлыкі" + "Дазваляе праграмам дадаваць ярлыкі без умяшання карыстальніка." + "счытваць налады і ярлыкі на Галоўнай старонцы" + "Дазваляе праграме счытваць налады і ярлыкі на Галоўнай старонцы." + "запісваць налады і ярлыкі на галоўнай старонцы" + "Дазваляе праграме змяняць налады і ярлыкі на Галоўнай старонцы." + "%1$s не мае дазволу на здзяйсненне тэлефонных званкоў" + "Праблема загрузкі віджэта" + "Наладжванне" + "Гэта сістэмная праграма, яе нельга выдаліць." + "Папка без назвы" + "%1$s адключана" + + %1$s: ёсць %2$d апавяшчэнне + %1$s: ёсць %2$d апавяшчэнні + %1$s: ёсць %2$d апавяшчэнняў + %1$s: ёсць %2$d апавяшчэння + + "Старонка %1$d з %2$d" + "Галоўны экран %1$d з %2$d" + "Новая старонка галоўнага экрана" + "Папка адкрыта, %1$d на %2$d" + "Краніце, каб закрыць папку" + "Краніце, каб захаваць новую назву" + "Папка закрыта" + "Папка перайменавана ў %1$s" + "Папка: %1$s" + "Віджэты" + "Шпалеры" + "Налады галоўнага экрана" + "Адключаная адміністратарам" + "Дазволіць паварот галоўнага экрана" + "Пры павароце тэлефона" + "Значкі апавяшчэнняў" + "Уключана" + "Выключана" + "Патрабуецца доступ да апавяшчэнняў" + "Каб паказваліся значкі апавяшчэнняў, уключыце апавяшчэнні праграм для %1$s" + "Змяніць налады" + "Паказаць значкі апавяшчэнняў" + "Дадаць значок на Галоўны экран" + "Для новых праграм" + "Змяніць форму значка" + "на галоўным экране" + "Выкарыстоўваць стандартныя формы" + "Квадрат" + "Прамавугольнік са скругленымі вугламі" + "Круг" + "Сляза" + "Змены формы значка прымяняюцца" + "Невядома" + "Выдаліць" + "Шукаць" + "Гэта праграма не ўсталявана" + "Праграма для гэтага значка не ўсталявана. Вы можаце выдаліць яе або выканаць пошук і ўсталяваць яе ўручную." + "Ідзе спампоўка %1$s, %2$s завершана" + "%1$s чакае ўсталёўкі" + "Віджэты %1$s" + "Дадаць на Галоўны экран" + "Перамясціць элемент сюды" + "Элемент дададзены на галоўны экран" + "Элемент выдалены" + "Перамясціць элемент" + "Перамясціць у радок %1$s слупок %2$s" + "Перамясціць у пазіцыю %1$s" + "Перамясціць у абранае, у пазіцыю %1$s" + "Элемент перамешчаны" + "Дадаць у папку: %1$s" + "Дадаць у папку з %1$s" + "Элемент дададзены ў папку" + "Стварыць папку з: %1$s" + "Папка створана" + "Перамясціць на Галоўны экран" + "Змяніць памер" + "Павялічыць шырыню" + "Павялічыць вышыню" + "Паменшыць шырыню" + "Паменшыць вышыню" + "Памеры віджэта зменены на: шырыня %1$s, вышыня %2$s" + "Ярлыкі" + "Ярлыкі (%1$d) для %2$s" + "Ярлыкі (%1$d) і апавяшчэнні (%2$d) для %3$s" + "Адхіліць" + "Апавяшчэнне адхілена" + "Асабістыя" + "Праца" + "Працоўны профіль" + "Знайдзіце працоўныя праграмы тут" + "Кожная працоўная праграма мае значок і знаходзіцца пад аховай вашай арганізацыі. Для больш простага доступу перамясціце праграмы на Галоўны экран." + "Пад кіраваннем вашай арганізацыі" + "Апавяшчэнні і праграмы выключаны" + "Закрыць" + "Закрытыя" + diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index a1f1d8912a..ea312e7b18 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -83,6 +83,8 @@ "Шпалеры" "Налады галоўнага экрана" "Адключаная адміністратарам" + "Дазволіць паварот галоўнага экрана" + "Пры павароце тэлефона" "Значкі апавяшчэнняў" "Уключана" "Выключана" @@ -130,8 +132,8 @@ "Паменшыць вышыню" "Памеры віджэта зменены на: шырыня %1$s, вышыня %2$s" "Ярлыкі" - "Ярлыкі (%1$d) для %2$s" - "Ярлыкі (%1$d) і апавяшчэнні (%2$d) для %3$s" + + "Адхіліць" "Апавяшчэнне адхілена" "Асабістыя" diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index 3c04905775..92000496d7 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -79,8 +79,10 @@ "Папка: „%1$s“" "Приспособления" "Тапети" - "Настройки за Google Home" + "Настройки за началния екран" "Деактивирано от администратора ви" + "Разрешаване на завъртането на началния екран" + "При завъртане на телефона" "Точки за известия" "Включено" "Изключено" @@ -128,8 +130,8 @@ "Намаляване на височината" "Приспособлението е преоразмерено към ширина %1$s и височина %2$s" "Преки пътища" - "%1$d преки пътища за %2$s" - "%1$d преки пътища и %2$d известия за %3$s" + + "Отхвърляне" "Известието е отхвърлено" "Лични" diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml new file mode 100644 index 0000000000..ffeeed76ab --- /dev/null +++ b/res/values-bn-rBD/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "কাজ" + "অ্যাপ্লিকেশান ইনস্টল করা নেই৷" + "অ্যাপ্লিকেশান অনুপলব্ধ" + "ডাউনলোড করা অ্যাপ্লিকেশান নিরাপদ মোডে অক্ষম রয়েছে" + "সুরক্ষিত মোডে উইজেট নিষ্ক্রিয় থাকে" + "শর্টকাটগুলি অনুপলব্ধ" + "হোম স্ক্রিন" + "কাস্টম অ্যাকশন" + "একটি উইজেট তুলতে তা স্পর্শ করে ধরে রাখুন৷" + "কোনো উইজেট বেছে নিতে দুবার-আলতো চেপে ধরে থাকুন অথবা কাস্টম ক্রিয়াগুলি ব্যবহার করুন৷" + "%1$d × %2$d" + "%2$d উচ্চতা অনুযায়ী %1$d প্রস্থ" + "নিজে যোগ করতে টাচ করে ধরে রাখুন" + "স্বয়ংক্রিয়ভাবে যোগ করুন" + "অ্যাপ খুঁজুন" + "অ্যাপ লোড হচ্ছে…" + "\"%1$s\" এর সাথে মেলে এমন কোনো অ্যাপ পাওয়া যায়নি" + "আরও অ্যাপ্লিকেশানের জন্য খুঁজুন" + "বিজ্ঞপ্তি" + "কোনও শর্টকাট বেছে নিতে টাচ করে ধরে থাকুন।" + "কোনও শর্টকাট বেছে নিতে ডবল ট্যাপ করে ধরে থাকুন অথবা কাস্টম অ্যাকশন ব্যবহার করুন।" + "এই হোম স্ক্রীনে আর কোনো জায়গা নেই৷" + "পছন্দসই ট্রে-তে আর কোনো জায়গা নেই" + "অ্যাপ্লিকেশানগুলির তালিকা" + "ব্যক্তিগত অ্যাপের তালিকা" + "কাজের অ্যাপের তালিকা" + "হোম" + "সরান" + "আনইনস্টল করুন" + "অ্যাপের তথ্য" + "ইনস্টল করুন" + "শর্টকাটগুলি ইনস্টল করে" + "একটি অ্যাপ্লিকেশানকে ব্যবহারকারীর হস্তক্ষেপ ছাড়াই শর্টকাটগুলি যোগ করার অনুমতি দেয়৷" + "হোম সেটিংস এবং শর্টকাটগুলি পড়ে" + "হোমে অ্যাপ্লিকেশানটিকে সেটিংস এবং শর্টকাটগুলি পড়তে দেয়৷" + "হোম সেটিংস এবং শর্টকাটগুলি লেখে" + "হোমে অ্যাপ্লিকেশানটিকে সেটিংস এবং শর্টকাটগুলি পরিবর্তন করতে দেয়৷" + "ফোন কলগুলি করার জন্য %1$s এর অনুমতি নেই" + "উইজেট লোড হতে সমস্যা হয়েছে" + "সেটআপ" + "এটি একটি সিস্টেম অ্যাপ্লিকেশান এবং আনইনস্টল করা যাবে না৷" + "নামবিহীন ফোল্ডার" + "%1$s অক্ষম করা হয়েছে" + + %1$s%2$dটি বিজ্ঞপ্তি আছে + %1$s%2$dটি বিজ্ঞপ্তি আছে + + "%2$dটির মধ্যে %1$dটি পৃষ্ঠা" + "%2$dটির %1$d নম্বর হোম স্ক্রিন" + "নতুন হোম স্ক্রীনের পৃষ্ঠা" + "ফোল্ডার খোলা হয়েছে, %1$d বাই %2$d" + "ফোল্ডার বন্ধ করতে আলতো চাপ দিন" + "পুনঃনামকরণ সংরক্ষণ করতে আলতো চাপ দিন" + "ফোল্ডার বন্ধ করা হয়েছে" + "ফোল্ডারের নাম পাল্টে %1$s করা হয়েছে" + "ফোল্ডার: %1$s" + "উইজেট" + "ওয়ালপেপারগুলি" + "হোম সেটিংস" + "আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে" + "হোমস্ক্রীন ঘোরানোর অনুমতি দিন" + "যখন ফোনটি ঘোরানো হয়" + "বিজ্ঞপ্তি ডট" + "চালু হয়েছে" + "বন্ধ আছে" + "বিজ্ঞপ্তিতে অ্যাক্সেস প্রয়োজন" + "বিজ্ঞপ্তির ডটগুলি দেখানোর জন্য, %1$s এর অ্যাপ বিজ্ঞপ্তি চালু করুন" + "সেটিংস পরিবর্তন করুন" + "বিজ্ঞপ্তির ডট দেখুন" + "হোম স্ক্রিনে আইকন যোগ করুন" + "নতুন অ্যাপ্লিকেশানগুলির জন্যে" + "আইকনের আকৃতি পরিবর্তন করুন" + "হোম স্ক্রিনে" + "সিস্টেমের ডিফল্ট মান ব্যবহার করুন" + "চৌকো" + "চৌকো-গোলাকার" + "গোলাকার" + "চোখের জল" + "আইকনের আকৃতি পরিবর্তন করা হচ্ছে" + "অজানা" + "সরান" + "অনুসন্ধান" + "এই অ্যাপ্লিকেশানটি ইন্সটল করা নাই" + "এই আইকনের অ্যাপ্লিকেশানটি ইন্সটল করা নাই। আপনি এটি সরাতে পারেন বা অ্যাপ্লিকেশানটি অনুসন্ধান করে এটি নিজে ইন্সটল করতে পারেন।" + "%1$s ডাউনলোড হচ্ছে %2$s সম্পন্ন হয়েছে" + "%1$s ইনস্টলের অপেক্ষায় রয়েছে" + "%1$s উইজেট" + "হোম স্ক্রীনে যোগ করুন" + "এখানে আইটেম সরান" + "হোম স্ক্রীনে আইটেম যোগ করা হয়েছে" + "আইটেম সরানো হয়েছে" + "আইটেম সরান" + "সারি %1$s কলাম %2$s এ সরান" + "অবস্থানে সরান %1$s" + "পছন্দসই অবস্থানে সরান %1$s" + "আইটেম সরানো হয়েছে" + "ফোল্ডারে যোগ করুন: %1$s" + "%1$s সহ ফোল্ডারে যোগ করা হয়েছে" + "আইটেম ফোল্ডারে যোগ করা হয়েছে" + "এর সাথে ফোল্ডার তৈরি করুন: %1$s" + "ফোল্ডার তৈরি করা হয়েছে" + "হোম স্ক্রীনে সরান" + "আবার আকার দিন" + "প্রস্থ বাড়ান" + "উচ্চতা বাড়ান" + "প্রস্থ কমান" + "উচ্চতা কমান" + "উইজেটের আকার প্রস্থ %1$s উচ্চতা %2$s তে পরিবর্তন করা হয়েছে" + "শর্টকাট" + "%2$s এর %1$dটি শর্টকার্ট" + "%3$s এর জন্য %1$dটি শর্টকাট এবং %2$dটি বিজ্ঞপ্তি" + "খারিজ করুন" + "বিজ্ঞপ্তি খারিজ করা হয়েছে" + "ব্যক্তিগত" + "অফিস" + "অফিসের প্রোফাইল" + "এখানে কাজের অ্যাপ্সগুলি খুঁজুন" + "প্রতিটি কাজের অ্যাপে একটি করে ব্যাজ রয়েছে এবং অ্যাপগুলি আপনার প্রতিষ্ঠানের দ্বারা সুরক্ষিত। সহজে অ্যাক্সেস করার জন্য অ্যাপগুলি হোম স্ক্রিনে রাখুন।" + "আপনার প্রতিষ্ঠানের দ্বারা পরিচালিত" + "বিজ্ঞপ্তি এবং অ্যাপ বন্ধ আছে" + "বন্ধ করুন" + "বন্ধ" + diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index a0e4812cc3..b11fae9ad9 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -77,10 +77,12 @@ "ফোল্ডার বন্ধ করা হয়েছে" "ফোল্ডারের নাম পাল্টে %1$s করা হয়েছে" "ফোল্ডার: %1$s" - "উইজেটগুলি" + "উইজেট" "ওয়ালপেপারগুলি" - "হোম এর সেটিংস" + "হোম সেটিংস" "আপনার প্রশাসক দ্বারা অক্ষম করা হয়েছে" + "হোমস্ক্রীন ঘোরানোর অনুমতি দিন" + "যখন ফোনটি ঘোরানো হয়" "বিজ্ঞপ্তি ডট" "চালু হয়েছে" "বন্ধ আছে" @@ -128,8 +130,8 @@ "উচ্চতা কমান" "উইজেটের আকার প্রস্থ %1$s উচ্চতা %2$s তে পরিবর্তন করা হয়েছে" "শর্টকাট" - "%2$s এর %1$dটি শর্টকার্ট" - "%3$s এর জন্য %1$dটি শর্টকাট এবং %2$dটি বিজ্ঞপ্তি" + + "খারিজ করুন" "বিজ্ঞপ্তি খারিজ করা হয়েছে" "ব্যক্তিগত" diff --git a/res/values-bs-rBA/strings.xml b/res/values-bs-rBA/strings.xml new file mode 100644 index 0000000000..40c886603d --- /dev/null +++ b/res/values-bs-rBA/strings.xml @@ -0,0 +1,147 @@ + + + + + "Launcher3" + + "Posao" + "Aplikacija nije instalirana." + "Aplikacija nije dostupna" + "Preuzeta aplikacija je onemogućena u sigurnom načinu rada" + "Vidžeti su onemogućeni u sigurnom načinu rada." + "Prečica nije dostupna" + "Početni ekran" + "Prilagođene akcije" + "Dodirnite & i držite da biste uzeli dodatak." + "Dodirnite dvaput & i držite da biste uzeli vidžet ili koristite prilagođene radnje." + "%1$d × %2$d" + "Širina %1$d, visina %2$d" + "Dodirnite i držite da postavite ručno" + "Dodaj automatski" + "Pretražite aplikacije" + "Aplikacije se učitavaju…" + "Nije pronađena nijedna aplikacija za upit \"%1$s\"" + "Pretraži više aplikacija" + "Obavještenja" + "Dodirnite i držite da uzmete prečicu." + "Dodirnite dvaput i držite da uzmete prečicu ili koristite prilagođene akcije." + "Na ovom početnom ekranu nema više prostora." + "Nema više prostora u ladici Omiljeno" + "Spisak aplikacija" + "Lista ličnih aplikacija" + "Lista poslovnih aplikacija" + "Početna" + "Ukloni" + "Deinstaliraj" + "Informacije o aplikaciji" + "Instaliraj" + "instaliraj prečice" + "Dopušta aplikaciji dodavanje prečica bez posredovanja korisnika." + "čitaj postavke na početnom ekranu i prečice" + "Dopušta aplikaciji čitanje postavki i prečica na početnom ekranu." + "zapisuj postavke na početnom ekranu i prečice" + "Dopušta aplikaciji promjenu postavki i prečica na početnom ekranu." + "%1$s nema odobrenje da uspostavlja telefonske pozive" + "Problem pri učitavanju dodatka" + "Postavljanje" + "Ovo je sistemska aplikacija i ne može se deinstalirati." + "Neimenovani folder" + "Aplikacija %1$s je onemogućena" + + %1$s ima %2$d obavještenje + %1$s ima %2$d obavještenja + %1$s ima %2$d obavještenja + + "Strana %1$d od %2$d" + "Početni ekran %1$d od %2$d" + "Nova stranica početnog ekrana" + "Folder je otvoren, (š) %1$d (v) %2$d" + "Dodirnite da zatvorite folder" + "Dodirnite da sačuvate promjenu naziva" + "Folder je zatvoren" + "Ime foldera je promijenjeno u %1$s" + "Folder: %1$s" + "Dodaci" + "Pozadinske slike" + "Postavke početnog ekrana" + "Onemogućio vaš administrator" + "Dozvoli rotiranje početnog ekrana" + "Kada se telefon zarotira" + "Tačke za obavještenja" + "Uključeno" + "Isključeno" + "Potreban je pristup obavještenjima" + "Za prikaz tačaka obavještenja, uključite obavještenja za aplikacije za aplikaciju %1$s" + "Promijeni postavke" + "Prikaži tačke za obavještenja" + "Dodaj ikonu na početni ekran" + "Za nove aplikacije" + "Promjena oblika ikona" + "na Početnom ekranu" + "Koristite sistemski zadano" + "Kvadrat" + "Zaobljeni kvadrat" + "Krug" + "Suza" + "Primjenjivanje promjena oblika ikona" + "Nepoznato" + "Ukloni" + "Pretraži" + "Ova aplikacija nije instalirana" + "Aplikacija za ovu ikonu nije instalirana. Možete je ukloniti ili potražiti aplikaciju i ručno je instalirati." + "%1$s se preuzima, završeno %2$s" + "%1$s čeka da se instalira" + "Vidžeti za aplikaciju %1$s" + "Dodaj na početni ekran" + "Premjesti stavku ovdje" + "Stavka je dodana na Početni ekran." + "Stavka je uklonjena" + "Premjesti stavku" + "Pomjeri stavku u red %1$s kolonu %2$s" + "Pomjeri stavku na poziciju %1$s" + "Pomjeri stavku na poziciju %1$s među omiljenim" + "Stavka je premještena" + "Dodaj u folder: %1$s" + "Dodaj u folder sa aplikacijom %1$s" + "Stavka je dodana u folder" + "Kreirajte folder sa stavkom: %1$s" + "Folder je kreiran" + "Pomjeri na početni ekran" + "Promijeni veličinu" + "Povećaj širinu" + "Povećaj visinu" + "Smanji širinu" + "Smanji visinu" + "Veličina vidžeta je promijenjena na širinu %1$s visinu %2$s" + "Prečice" + "%1$d prečica za aplikaciju %2$s" + "Za aplikaciju %3$s broj prečica je %1$d, a broj obavještenja je %2$d" + "Odbaci" + "Obavještenje je odbačeno" + "Lične" + "Poslovne" + "Radni profil" + "Pronađite poslovne aplikacije ovdje" + "Svaka poslovna aplikacija ima značku i osigurava je vaša organizacija. Premjestite aplikacije na Početni ekran, radi lakšeg pristupa." + "Upravlja vaša organizacija" + "Notifikacije i aplikacije su isključene" + "Zatvori" + "Zatvoreno" + diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 08a453360d..94d3ca0676 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -30,7 +30,7 @@ "Početni ekran" "Prilagođene akcije" "Dodirnite & i držite da biste uzeli dodatak." - "Dvaput dodirnite & i držite da biste uzeli vidžet ili koristite prilagođene radnje." + "Dodirnite dvaput & i držite da biste uzeli vidžet ili koristite prilagođene radnje." "%1$d × %2$d" "Širina %1$d, visina %2$d" "Dodirnite i držite da postavite ručno" @@ -41,7 +41,7 @@ "Pretraži više aplikacija" "Obavještenja" "Dodirnite i držite da uzmete prečicu." - "Dvaput dodirnite i držite da uzmete prečicu ili koristite prilagođene akcije." + "Dodirnite dvaput i držite da uzmete prečicu ili koristite prilagođene akcije." "Na ovom početnom ekranu nema više prostora." "Nema više prostora u ladici Omiljeno" "Spisak aplikacija" @@ -80,8 +80,10 @@ "Folder: %1$s" "Dodaci" "Pozadinske slike" - "Postavke za Home" + "Postavke početnog ekrana" "Onemogućio vaš administrator" + "Dozvoli rotiranje početnog ekrana" + "Kada se telefon zarotira" "Tačke za obavještenja" "Uključeno" "Isključeno" @@ -101,7 +103,7 @@ "Primjenjivanje promjena oblika ikona" "Nepoznato" "Ukloni" - "Traži" + "Pretraži" "Ova aplikacija nije instalirana" "Aplikacija za ovu ikonu nije instalirana. Možete je ukloniti ili potražiti aplikaciju i ručno je instalirati." "%1$s se preuzima, završeno %2$s" @@ -129,8 +131,8 @@ "Smanji visinu" "Veličina vidžeta je promijenjena na širinu %1$s visinu %2$s" "Prečice" - "%1$d prečica za aplikaciju %2$s" - "Za aplikaciju %3$s broj prečica je %1$d, a broj obavještenja je %2$d" + + "Odbaci" "Obavještenje je odbačeno" "Lične" diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index 27b2979e15..2364e722e0 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -50,7 +50,7 @@ "Inici" "Suprimeix" "Desinstal·la" - "Dades de l\'aplicació" + "Informació de l\'aplicació" "Instal·la" "instal·la dreceres" "Permet que una aplicació afegeixi dreceres sense la intervenció de l\'usuari." @@ -79,8 +79,10 @@ "Carpeta: %1$s" "Widgets" "Fons de pantalla" - "Configuració de la pantalla d\'inici" + "Configuració de pantalla d\'inici" "Desactivada per l\'administrador" + "Permet la rotació de la pantalla d\'inici" + "En girar el telèfon" "Punts de notificació" "Activat" "Desactivat" @@ -128,8 +130,8 @@ "Redueix l\'alçada" "S\'ha canviat la mida del widget a l\'amplada %1$s i l\'alçada %2$s" "Dreceres" - "%1$d dreceres per a l\'aplicació %2$s" - "%1$d dreceres i %2$d notificacions per a %3$s" + + "Ignora" "S\'ha ignorat la notificació" "Personal" diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index eee945c209..f84e437c1c 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -83,6 +83,8 @@ "Tapety" "Nastavení plochy" "Zakázáno administrátorem" + "Povolit otáčení plochy" + "Při otočení telefonu" "Puntíky s oznámením" "Zapnuto" "Vypnuto" @@ -130,8 +132,8 @@ "Snížit výšku" "Velikost widgetu upravena: šířka %1$s, výška %2$s" "Zkratky" - "Počet zkratek pro aplikaci %2$s: %1$d" - "Zkratky (%1$d) a oznámení (%2$d) aplikace %3$s" + + "Zavřít" "Oznámení bylo zavřeno" "Osobní" diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 203a9da7d4..1d6984c757 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -81,6 +81,8 @@ "Baggrunde" "Indstillinger for startskærmen" "Deaktiveret af din administrator" + "Tillad rotation af startskærmen" + "Når telefonen roteres" "Underretningscirkler" "Til" "Fra" @@ -128,8 +130,8 @@ "Reducer højden" "Størrelsen for widgetten er ændret til bredde %1$s og højde %2$s" "Genveje" - "%1$d genveje til %2$s" - "%1$d genveje og %2$d underretninger for %3$s" + + "Afvis" "Underretningen blev afvist" "Personlige" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index f012a9ee63..af07f1c8f0 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -81,6 +81,8 @@ "Hintergründe" "Einstellungen für den Startbildschirm" "Von deinem Administrator deaktiviert" + "Drehung des Startbildschirms zulassen" + "Bei Drehung des Smartphones" "App-Benachrichtigungspunkte" "Aktiviert" "Deaktiviert" @@ -128,8 +130,8 @@ "Höhe verringern" "Größe des Widgets zu Breite %1$s und Höhe %2$s geändert" "Verknüpfungen" - "%1$d Verknüpfungen für %2$s" - "%1$d Verknüpfungen und %2$d Benachrichtigungen für %3$s" + + "Schließen" "Benachrichtigung geschlossen" "Privat" diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index 18eec841fa..3de0aaf5ac 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -79,8 +79,10 @@ "Φάκελος: %1$s" "Γραφικά στοιχεία" "Ταπετσαρίες" - "Ρυθμίσεις Αρχικής σελίδας" + "Ρυθμίσεις Αρχ. Οθ." "Απενεργοποιήθηκε από τον διαχειριστή σας" + "Να επιτρέπεται η περιστροφή της αρχικής οθόνης" + "Όταν το τηλέφωνο περιστρέφεται" "Κουκκίδες ειδοποίησης" "Ενεργή" "Ανενεργή" @@ -128,8 +130,8 @@ "Μείωση του ύψους" "Έγινε προσαρμογή του μεγέθους του γραφικού στοιχείου σε %1$s πλάτος και %2$s ύψος" "Συντομεύσεις" - "%1$d συντομεύσεις για %2$s" - "%1$d συντομεύσεις και %2$d ειδοποιήσεις για την εφαρμογή %3$s" + + "Παράβλεψη" "Η ειδοποίηση παραβλέφθηκε" "Προσωπικές" diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index c2e37b8e51..cca8e859da 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -81,6 +81,8 @@ "Wallpapers" "Home settings" "Disabled by your admin" + "Allow Homescreen rotation" + "When phone is rotated" "Notification dots" "On" "Off" diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index c2e37b8e51..cca8e859da 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -81,6 +81,8 @@ "Wallpapers" "Home settings" "Disabled by your admin" + "Allow Homescreen rotation" + "When phone is rotated" "Notification dots" "On" "Off" diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index c2e37b8e51..cca8e859da 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -81,6 +81,8 @@ "Wallpapers" "Home settings" "Disabled by your admin" + "Allow Homescreen rotation" + "When phone is rotated" "Notification dots" "On" "Off" diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index 989cd619e7..f991da7f86 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -79,8 +79,10 @@ "Carpeta: %1$s" "Widgets" "Fondos de pantalla" - "Configuración de Home" + "Configuración de página principal" "El administrador inhabilitó esta función" + "Permitir la rotación de la pantalla principal" + "Al girar el teléfono" "Puntos de notificación" "Activada" "Desactivada" @@ -92,7 +94,7 @@ "Para nuevas apps" "Cambiar forma de los íconos" "en la pantalla principal" - "Usar el sistema predeterminado" + "Usar valores predeterminados del sistema" "Cuadrado" "Cuadrado con esquinas redondeadas" "Círculo" @@ -128,8 +130,8 @@ "Reducir la altura" "Se cambió la dimensión del widget a %1$s de ancho y %2$s de alto." "Accesos directos" - "%1$d accesos directos para %2$s" - "%1$d accesos directos y %2$d notificaciones de %3$s" + + "Descartar" "Se descartó la notificación" "Personales" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 5b948da351..1dbe8e904d 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -79,11 +79,13 @@ "Carpeta: %1$s" "Widgets" "Fondos de pantalla" - "Ajustes de Home" + "Ajustes de la pantalla de inicio" "Inhabilitada por el administrador" - "Puntos de notificación" - "Activada" - "Desactivada" + "Permitir rotación de la pantalla de inicio" + "Al girar el teléfono" + "Burbujas de notificación" + "Activado" + "Desactivado" "Se necesita acceso a las notificaciones" "Para mostrar burbujas de notificación, activa las notificaciones de %1$s" "Cambiar ajustes" @@ -128,8 +130,8 @@ "Reducir altura" "Se ha modificado el tamaño del widget a %1$s de ancho y %2$s de alto" "Accesos directos" - "%1$d accesos directos de %2$s" - "%1$d accesos directos y %2$d notificaciones de %3$s" + + "Ignorar" "Notificación ignorada" "Personal" diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml new file mode 100644 index 0000000000..1bde8aac13 --- /dev/null +++ b/res/values-et-rEE/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "Töö" + "Rakendus pole installitud." + "Rakendus ei ole saadaval" + "Allalaetud rakendus on turvarežiimis keelatud" + "Turvarežiimis on vidinad keelatud" + "Otsetee pole saadaval" + "Avaekraan" + "Kohandatud toimingud" + "Vidina valimiseks vajutage ja hoidke seda all." + "Topeltpuudutage ja hoidke vidina valimiseks või kohandatud toimingute kasutamiseks." + "%1$d × %2$d" + "%1$d lai ja %2$d kõrge" + "Puudutage pikalt, et käsitsi asetada" + "Lisa automaatselt" + "Otsige rakendusi" + "Rakenduste laadimine …" + "Päringule „%1$s” ei vastanud ükski rakendus" + "Otsi rohkem rakendusi" + "Märguanded" + "Otsetee valimiseks puudutage seda pikalt." + "Topeltpuudutage ja hoidke otsetee valimiseks või kohandatud toimingute kasutamiseks." + "Sellel avaekraanil pole enam ruumi." + "Salves Lemmikud pole rohkem ruumi" + "Rakenduste loend" + "Isiklike rakenduste loend" + "Töörakenduste loend" + "Avaekraan" + "Eemalda" + "Desinstalli" + "Rakenduse teave" + "Installimine" + "installi otseteed" + "Võimaldab rakendusel lisada otseteid kasutaja sekkumiseta." + "loe avaekraani seadeid ja otseteid" + "Võimaldab rakendusel lugeda avaekraanil seadeid ja otseteid." + "kirjuta avaekraani seaded ja otseteed" + "Võimaldab rakendusel muuta avaekraanil seadeid ja otseteid." + "Rakendusel %1$s pole lubatud helistada" + "Probleem vidina laadimisel" + "Seadistamine" + "See on süsteemirakendus ja seda ei saa desinstallida." + "Nimetu kaust" + "Rakendus %1$s on keelatud" + + %1$s, %2$d märguannet + %1$s%2$d märguanne + + "Leht %1$d/%2$d" + "Avaekraan %1$d/%2$d" + "Uus avaekraan" + "Kaust on avatud, %1$d x %2$d" + "Puudutage kausta sulgemiseks" + "Puudutage ümbernimetamise salvestamiseks" + "Kaust on suletud" + "Kausta uus nimi: %1$s" + "Kaust: %1$s" + "Vidinad" + "Taustapildid" + "Avaekraani seaded" + "Keelas administraator" + "Luba avaekraani pööramine" + "Kui telefoni pööratakse" + "Märguandetäpid" + "Sees" + "Väljas" + "Vaja on juurdepääsu märguannetele" + "Märguandetäppide kuvamiseks lülitage sisse rakenduse %1$s märguanded" + "Seadete muutmine" + "Kuva märguandetäpid" + "Lisa ikoon avaekraanile" + "Uute rakenduste puhul" + "Ikooni kuju muutmine" + "avaekraanil" + "Kasuta süsteemi vaikeseadet" + "Ruut" + "Ümarate nurkadega ruut" + "Ring" + "Tilk" + "Ikooni kuju muudatuste rakendamine" + "Teadmata" + "Eemalda" + "Otsing" + "See rakendus ei ole installitud" + "Selle ikooni rakendust pole installitud. Saate selle eemaldada või rakendust otsida ja käsitsi installida." + "Rakenduse %1$s allalaadimine, %2$s on valmis" + "%1$s on installimise ootel" + "Teenuse %1$s vidinad" + "Lisa avaekraanile" + "Teisalda üksus siia" + "Üksus lisati avaekraanile" + "Üksus eemaldati" + "Teisalda üksus" + "Teisaldamine %1$s. rea %2$s. veergu" + "Teisaldamine %1$s. positsioonile" + "Teisaldamine lemmikute %1$s. positsioonile" + "Üksus teisaldati" + "Lisamine kausta: %1$s" + "Lisamine kausta nimega %1$s" + "Üksus lisati kausta" + "Kausta loomine nimega %1$s" + "Kaust on loodud" + "Teisalda avaekraanile" + "Muuda suurust" + "Suurenda laiust" + "Suurenda kõrgust" + "Vähenda laiust" + "Vähenda kõrgust" + "Vidina suurust muudeti. Laius: %1$s. Kõrgus: %2$s" + "Otseteed" + "%1$d otseteed rakenduse %2$s jaoks" + "%1$d otseteed ja %2$d märguannet rakendusele %3$s" + "Loobu" + "Märguandest loobuti" + "Isiklik" + "Töö" + "Tööprofiil" + "Töörakendused leiate siit" + "Igal töörakendusel on märk ja teie organisatsioon tagab selle turvalisuse. Teisaldage rakendused avaekraanile, et neile oleks lihtsam juurde pääseda." + "Haldab teie organisatsioon" + "Märguanded ja rakendused on välja lülitatud" + "Sule" + "Suletud" + diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index 2946076f5d..94b0103e61 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -79,8 +79,10 @@ "Kaust: %1$s" "Vidinad" "Taustapildid" - "Avalehe seaded" + "Avaekraani seaded" "Keelas administraator" + "Luba avaekraani pööramine" + "Kui telefoni pööratakse" "Märguandetäpid" "Sees" "Väljas" @@ -128,8 +130,8 @@ "Vähenda kõrgust" "Vidina suurust muudeti. Laius: %1$s. Kõrgus: %2$s" "Otseteed" - "%1$d otseteed rakenduse %2$s jaoks" - "%1$d otseteed ja %2$d märguannet rakendusele %3$s" + + "Loobu" "Märguandest loobuti" "Isiklik" diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml new file mode 100644 index 0000000000..128c6f42a3 --- /dev/null +++ b/res/values-eu-rES/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "Lana" + "Aplikazioa instalatu gabe dago." + "Ez dago erabilgarri aplikazioa" + "Deskargatutako aplikazioa modu seguruan desgaitu da" + "Widgetak desgaitu egin dira modu seguruan" + "Lasterbideak ez daude erabilgarri" + "Hasierako pantaila" + "Ekintza pertsonalizatuak" + "Eduki sakatuta widgeta aukeratzeko." + "Sakatu birritan eta eduki sakatuta widgeta aukeratzeko edo ekintza pertsonalizatuak erabiltzeko." + "%1$d × %2$d" + "%1$d zabal eta %2$d luze" + "Eduki sakatuta eskuz gehitzeko" + "Gehitu automatikoki" + "Bilatu aplikazioetan" + "Aplikazioak kargatzen…" + "Ez da aurkitu \"%1$s\" bilaketaren emaitzarik" + "Bilatu aplikazio gehiago" + "Jakinarazpenak" + "Eduki sakatuta lasterbide bat aukeratzeko." + "Sakatu birritan eta eduki sakatuta lasterbide bat aukeratzeko edo ekintza pertsonalizatuak erabiltzeko." + "Hasierako pantaila honetan ez dago toki gehiago." + "Ez dago toki gehiago Gogokoak erretiluan" + "Aplikazioen zerrenda" + "Aplikazio pertsonalen zerrenda" + "Laneko aplikazioen zerrenda" + "Hasiera" + "Kendu" + "Desinstalatu" + "Aplikazioaren datuak" + "Instalatu" + "Instalatu lasterbideak" + "Erabiltzaileak ezer egin gabe lasterbideak gehitzea baimentzen die aplikazioei." + "Irakurri hasierako ezarpenak eta lasterbideak" + "Hasierako pantailako ezarpenak eta lasterbideak irakurtzea baimentzen die aplikazioei." + "Idatzi hasierako ezarpenak eta lasterbideak" + "Hasierako pantailako ezarpenak eta lasterbideak aldatzea baimentzen die aplikazioei." + "%1$s aplikazioak ez du telefono-deiak egiteko baimenik" + "Arazo bat izan da widgeta kargatzean" + "Konfigurazioa" + "Sistema-aplikazioa da hau eta ezin da desinstalatu." + "Izenik gabeko karpeta" + "%1$s desgaituta dago" + + %2$d jakinarazpen dauzka %1$s aplikazioak + %2$d jakinarazpen dauka %1$s aplikazioak + + "%1$d/%2$d orria" + "%1$d/%2$d hasierako pantaila" + "Hasierako pantailaren orri berria" + "Karpeta ireki da: %1$d x %2$d" + "Karpeta ixteko, sakatu hau" + "Izen berria gordetzeko, sakatu hau" + "Karpeta itxi da" + "Karpetari %1$s izena eman zaio" + "Karpeta: %1$s" + "Widgetak" + "Horma-paperak" + "Hasierako pantailaren ezarpenak" + "Administratzaileak desgaitu du" + "Baimendu hasierako pantaila biratzea" + "Telefonoa biratzen denean" + "Jakinarazpen-biribiltxoak" + "Aktibatuta" + "Desaktibatuta" + "Jakinarazpenetarako sarbidea behar da" + "Jakinarazpen-biribiltxoak ikusteko, aktibatu %1$s aplikazioaren jakinarazpenak" + "Aldatu ezarpenak" + "Erakutsi jakinarazpen-biribiltxoak" + "Gehitu ikonoa hasierako pantailan" + "Aplikazio berrietan" + "Aldatu ikonoaren forma" + "Hasierako pantailan" + "Erabili sistemaren balio lehenetsiak" + "Karratua" + "Ertz biribilduko karratua" + "Zirkulua" + "Malkoa" + "Ikonoaren forman egindako aldaketak aplikatzen" + "Ezezaguna" + "Kendu" + "Bilatu" + "Aplikazio hau ez dago instalatuta" + "Ikono honen aplikazioa ez dago instalatuta. Ikonoa ken dezakezu, edo aplikazioa bilatu eta eskuz instalatu." + "%1$s deskargatzen, %2$s osatuta" + "%1$s instalatzeko zain" + "%1$s widgetak" + "Gehitu hasierako pantailan" + "Ekarri elementua hona" + "Gehitu da elementua hasierako pantailan" + "Kendu da elementua" + "Mugitu elementua" + "Eraman %1$s. errenkadara, %2$s. zutabera" + "Eraman %1$s. postura" + "Eraman gogokoen %1$s. postura" + "Elementua mugitu da" + "Gehitu %1$s karpetan" + "Gehitu %1$s duen karpetan" + "Elementua karpetan gehitu da" + "Sortu karpeta %1$s elementuarekin" + "Karpeta sortu da" + "Eraman hasierako pantailara" + "Aldatu tamaina" + "Handitu zabalera" + "Handitu altuera" + "Txikitu zabalera" + "Txikitu altuera" + "Aldatu da widgetaren tamaina. Zabalera: %1$s. Altuera: %2$s." + "Lasterbideak" + "%2$s aplikazioaren %1$d lasterbide" + "%3$s aplikazioaren %1$d lasterbide eta %2$d jakinarazpen" + "Baztertu" + "Baztertu egin da jakinarazpena" + "Pertsonalak" + "Lanekoak" + "Laneko profila" + "Hemen dituzu laneko aplikazioak" + "Laneko aplikazio bakoitzak bereizgarri bat dauka eta erakundeak babesten du. Aplikazioak errazago atzitzeko, eraman itzazu hasierako pantailara." + "Erakundeak kudeatzen du" + "Jakinarazpenak eta aplikazioak desaktibatuta daude" + "Itxi" + "Itxita" + diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index c3099bd98e..a13c49325a 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -81,13 +81,15 @@ "Horma-paperak" "Hasierako pantailaren ezarpenak" "Administratzaileak desgaitu du" - "Jakinarazteko biribiltxoak" + "Baimendu hasierako pantaila biratzea" + "Telefonoa biratzen denean" + "Jakinarazpen-biribiltxoak" "Aktibatuta" "Desaktibatuta" "Jakinarazpenetarako sarbidea behar da" - "Jakinarazteko biribiltxoak ikusteko, aktibatu %1$s aplikazioaren jakinarazpenak" + "Jakinarazpen-biribiltxoak ikusteko, aktibatu %1$s aplikazioaren jakinarazpenak" "Aldatu ezarpenak" - "Erakutsi jakinarazteko biribiltxoak" + "Erakutsi jakinarazpen-biribiltxoak" "Gehitu ikonoa hasierako pantailan" "Aplikazio berrietan" "Aldatu ikonoaren forma" @@ -128,8 +130,8 @@ "Txikitu altuera" "Aldatu da widgetaren tamaina. Zabalera: %1$s. Altuera: %2$s." "Lasterbideak" - "%2$s aplikazioaren %1$d lasterbide" - "%3$s aplikazioaren %1$d lasterbide eta %2$d jakinarazpen" + + "Baztertu" "Baztertu egin da jakinarazpena" "Pertsonalak" diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index 4843d6d9e4..da12ebe7b3 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -81,6 +81,8 @@ "کاغذدیواری‌ها" "تنظیمات صفحه اصلی" "توسط سرپرست سیستم غیرفعال شده است" + "امکان دادن به چرخش صفحه اصلی" + "وقتی تلفن چرخانده می‌شود" "نقطه‌های اعلان" "روشن" "خاموش" @@ -128,8 +130,8 @@ "کاهش ارتفاع" "اندازه ابزارک به عرض %1$s ارتفاع %2$s تغییر کرد" "میان‌برها" - "%1$d میانبر برای %2$s" - "%1$d میان‌بر و %2$d اعلان برای %3$s" + + "رد کردن" "اعلان رد شد" "شخصی" diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index 5ffc414558..96214d30ad 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -81,6 +81,8 @@ "Taustakuvat" "Kotiasetukset" "Järjestelmänvalvoja on poistanut toiminnon käytöstä." + "Salli aloitusnäytön kiertäminen" + "Kun puhelinta kierretään" "Pistemerkit" "Käytössä" "Pois käytöstä" @@ -128,8 +130,8 @@ "Vähennä korkeutta" "Widgetin kokoa muutettiin. Sen leveys on nyt %1$s ja korkeus %2$s." "Pikakuvakkeet" - "Sovelluksella %2$s on %1$d pikakuvaketta." - "%3$s: %1$d pikakuvaketta ja %2$d ilmoitusta" + + "Hylkää" "Ilmoitus hylätty" "Henkilökohtaiset" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index d6903efb1a..aebb42df2f 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -81,6 +81,8 @@ "Fonds d\'écran" "Paramètres d\'accueil" "Cette fonction est désactivée par votre administrateur" + "Autoriser la rotation de l\'écran d\'accueil" + "Lorsque vous faites pivoter le téléphone" "Points de notification" "Activé" "Désactivé" @@ -128,8 +130,8 @@ "Diminuer la hauteur" "Le widget a été redimensionné (largeur : %1$s, hauteur : %2$s)" "Raccourcis" - "%1$d raccourcis pour %2$s" - "%1$d raccourcis et %2$d notifications pour %3$s" + + "Ignorer" "Notification ignorée" "Personnel" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index e1b758124d..6c5c120690 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -79,8 +79,10 @@ "Dossier \"%1$s\"" "Widgets" "Fonds d\'écran" - "Paramètres de l\'écran d\'accueil" + "Paramètres accueil" "Désactivé par votre administrateur" + "Autoriser la rotation de l\'écran d\'accueil" + "Lorsque vous faites pivoter le téléphone" "Pastilles de notification" "Activé" "Désactivé" @@ -128,8 +130,8 @@ "Diminuer la hauteur" "Le widget a bien été redimensionné (largeur : %1$s, hauteur : %2$s)." "Raccourcis" - "%1$d raccourcis pour %2$s" - "%1$d raccourcis et %2$d notifications pour %3$s" + + "Ignorer" "Notification ignorée" "Personnelles" diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml new file mode 100644 index 0000000000..1efa5ceadd --- /dev/null +++ b/res/values-gl-rES/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "Traballo" + "A aplicación non está instalada" + "A aplicación non está dispoñible" + "A aplicación que descargaches está desactivada no modo seguro" + "Os widgets están desactivados no modo seguro" + "O atallo non está dispoñible" + "Pantalla de inicio" + "Accións personalizadas" + "Mantén premido un widget para seleccionalo." + "Toca dúas veces e mantén premido para seleccionar un widget ou utiliza accións personalizadas." + "%1$d × %2$d" + "%1$d de largo por %2$d de alto" + "Mantén premido o elemento para colocalo manualmente" + "Engadir automaticamente" + "Buscar aplicacións" + "Cargando aplicacións…" + "Non se atoparon aplicacións que coincidan con \"%1$s\"" + "Buscar máis aplicacións" + "Notificacións" + "Mantén premido un atallo para seleccionalo." + "Toca dúas veces e mantén premido para seleccionar un atallo ou utiliza accións personalizadas." + "Non hai máis espazo nesta pantalla de inicio." + "Non hai máis espazo na bandexa de favoritos" + "Lista de aplicacións" + "Lista de aplicacións persoais" + "Lista de aplicacións de traballo" + "Inicio" + "Eliminar" + "Desinstalar" + "Info. da aplicación" + "Instalar" + "instalar atallos" + "Permite a unha aplicación engadir atallos sen intervención do usuario." + "ler a configuración e os atallos da pantalla de inicio" + "Permite a unha aplicación ler a configuración e os atallos da páxina de inicio." + "modificar a configuración e os atallos da pantalla de inicio" + "Permite a unha aplicación cambiar a configuración e os atallos da pantalla de inicio." + "%1$s non ten permiso para facer chamadas telefónicas" + "Produciuse un problema ao cargar o widget" + "Configuración" + "Esta aplicación é do sistema e non se pode desinstalar." + "Cartafol sen nome" + "Desactivouse %1$s" + + %1$s, ten %2$d notificacións + %1$s, ten %2$d notificación + + "Páxina %1$d de %2$d" + "Pantalla de inicio %1$d de %2$d" + "Nova páxina da pantalla de inicio" + "Abriuse o cartafol, %1$d por %2$d" + "Toca fóra para pechar o cartafol" + "Toca fóra para cambiar o nome do cartafol" + "Pechouse o cartafol" + "O cartafol cambiou o nome a %1$s" + "Cartafol: %1$s" + "Widgets" + "Fondos de pantalla" + "Configuración da pantalla de Inicio" + "Función desactivada polo administrador" + "Permitir xirar a pantalla de inicio" + "Ao xirar o teléfono" + "Puntos de notificacións" + "Activado" + "Desactivado" + "Necesítase acceso ás notificacións" + "Para que se mostren os puntos de notificacións, activa as notificacións da aplicación %1$s" + "Cambiar configuración" + "Mostrar puntos de notificación" + "Engadir icona á pantalla de inicio" + "Para novas aplicacións" + "Cambiar forma das iconas" + "na pantalla de inicio" + "Usar valores predeterminados do sistema" + "Cadrado" + "Cadrado de bordos redondeados" + "Círculo" + "Bágoa" + "Aplicando cambios na forma das iconas" + "Descoñecido" + "Eliminar" + "Buscar" + "Esta aplicación non está instalada" + "A aplicación para esta icona non está instalada. Podes eliminala ou buscar a aplicación e instalala manualmente." + "Descargando %1$s (%2$s completado)" + "Esperando para instalar %1$s" + "Widgets de: %1$s" + "Engadir á pantalla de inicio" + "Mover elemento aquí" + "Engadiuse o elemento á pantalla de inicio" + "Eliminouse o elemento" + "Mover elemento" + "Mover á fila %1$s columna %2$s" + "Mover á posición %1$s" + "Mover á posición dos favoritos %1$s" + "Moveuse o elemento" + "Engadir ao cartafol: %1$s" + "Engadir ao cartafol con %1$s" + "Engadiuse o elemento ao cartafol" + "Crear cartafol con: %1$s" + "Creouse o cartafol" + "Mover á pantalla de inicio" + "Cambiar tamaño" + "Aumentar ancho" + "Aumentar altura" + "Reducir ancho" + "Reducir altura" + "Cambiouse o tamaño do widget polo ancho %1$s e a altura %2$s" + "Atallos" + "%1$d atallos para %2$s" + "%1$d atallos e %2$d notificacións para a aplicación %3$s" + "Ignorar" + "Ignorouse a notificación" + "Persoal" + "Traballo" + "Perfil de traballo" + "Buscar aplicacións do traballo aquí" + "As aplicacións do traballo teñen unha insignia e están protexidas pola túa organización. Traslada as aplicacións á pantalla de inicio para acceder a elas de forma máis fácil." + "Perfil xestionado pola túa organización" + "As notificacións e as aplicacións están desactivadas" + "Pechar" + "Pechada" + diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index 0cfdfa8991..4dd7ae71b1 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -79,8 +79,10 @@ "Cartafol: %1$s" "Widgets" "Fondos de pantalla" - "Configuración de inicio" + "Configuración da pantalla de Inicio" "Función desactivada polo administrador" + "Permitir xirar a pantalla de inicio" + "Ao xirar o teléfono" "Puntos de notificacións" "Activado" "Desactivado" @@ -128,8 +130,8 @@ "Reducir altura" "Cambiouse o tamaño do widget polo ancho %1$s e a altura %2$s" "Atallos" - "%1$d atallos para %2$s" - "%1$d atallos e %2$d notificacións para a aplicación %3$s" + + "Ignorar" "Ignorouse a notificación" "Persoal" diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml new file mode 100644 index 0000000000..234fadafcd --- /dev/null +++ b/res/values-gu-rIN/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "કાર્યાલય" + "ઍપ્લિકેશન ઇન્સ્ટોલ થઈ નથી." + "ઍપ્લિકેશન ઉપલબ્ધ નથી" + "સુરક્ષિત મોડમાં ડાઉનલોડ કરેલ ઍપ્લિકેશન અક્ષમ કરી" + "સુરક્ષિત મોડમાં વિજેટ્સ અક્ષમ કર્યા" + "શૉર્ટકટ ઉપલબ્ધ નથી" + "હોમ સ્ક્રીન" + "કસ્ટમ ક્રિયાઓ" + "વિજેટ ચૂંટવા માટે સ્પર્શ કરો અને પકડી રાખો." + "વિજેટ ચૂંટવા અથવા કસ્ટમ ક્રિયાઓનો ઉપયોગ કરવા માટે બે વાર ટેપ કરો અને પકડી રાખો." + "%1$d × %2$d" + "%1$d પહોળાઈ X %2$d ઊંચાઈ" + "મેન્યુઅલી મૂકવા માટે ટચ કરી દબાવી રાખો" + "આપમેળે ઉમેરો" + "શોધ ઍપ્લિકેશનો" + "ઍપ્લિકેશનો લોડ કરી રહ્યું છે…" + "\"%1$s\"થી મેળ ખાતી કોઈ ઍપ્લિકેશનો મળી નથી" + "વધુ ઍપ્લિકેશનો શોધો" + "નોટિફિકેશનો" + "એક શૉર્ટકટ ચૂંટવા માટે સ્પર્શ કરી રાખો." + "એક શૉર્ટકટ ચૂંટવા અથવા કોઈ કસ્ટમ ક્રિયાઓનો ઉપયોગ કરવા માટે બે વાર ટૅપ કરીને દબાવી રાખો." + "આ હોમ સ્ક્રીન પર વધુ જગ્યા નથી." + "મનપસંદ ટ્રે પર વધુ જગ્યા નથી" + "ઍપ્લિકેશનોની સૂચિ" + "વ્યક્તિગત ઍપની સૂચિ" + "કાર્યસ્થળની ઍપની સૂચિ" + "હોમ" + "દૂર કરો" + "અનઇન્સ્ટોલ કરો" + "ઍપ્લિકેશન માહિતી" + "ઇન્સ્ટૉલ કરો" + "શોર્ટકટ્સ ઇન્સ્ટોલ કરો" + "એપ્લિકેશનને વપરાશકર્તા હસ્તક્ષેપ વગર શોર્ટકટ્સ ઉમેરવાની મંજૂરી આપે છે." + "હોમ સેટિંગ્સ અને શોર્ટકટ્સ વાંચો" + "એપ્લિકેશનને હોમમાં સેટિંગ્સ અને શોર્ટકટ્સ વાંચવાની મંજૂરી આપે છે." + "હોમ સેટિંગ્સ અને શોર્ટકટ્સ લખો" + "એપ્લિકેશનને હોમમાં સેટિંગ્સ અને શોર્ટકટ્સ બદલવાની મંજૂરી આપે છે." + "%1$s ને ફોન કૉલ્સ કરવાની મંજૂરી નથી" + "વિજેટ લોડ કરવામાં સમસ્યા" + "સેટઅપ" + "આ એક સિસ્ટમ ઍપ્લિકેશન છે અને અનઇન્સ્ટોલ કરી શકાતી નથી." + "અનામી ફોલ્ડર" + "%1$s અક્ષમ કરી" + + %1$sના %2$d નોટિફિકેશન છે + %1$sના %2$d નોટિફિકેશન છે + + "%2$d માંથી %1$d પૃષ્ઠ" + "%2$d માંથી %1$d હોમ સ્ક્રીન" + "નવું હોમ સ્ક્રીન પૃષ્ઠ" + "%1$d બાય %2$d નું ફોલ્ડર ખોલ્યું" + "ફોલ્ડર બંધ કરવા માટે ટૅપ કરો" + "નામ બદલવાનું સાચવવા માટે ટૅપ કરો" + "ફોલ્ડર બંધ કર્યું" + "ફોલ્ડરનું નામ બદલીને %1$s કર્યું" + "ફોલ્ડર: %1$s" + "વિજેટ્સ" + "વૉલપેપર્સ" + "હોમ સેટિંગ્સ" + "તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ" + "હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો" + "જ્યારે ફોન ફેરવવામાં આવે ત્યારે" + "સૂચના બિંદુઓ" + "ચાલુ" + "બંધ" + "નોટિફિકેશનનો ઍક્સેસની જરૂરી છે" + "નોટિફિકેશન માટેનું ચિહ્ન બતાવવા હેતુ, %1$s માટેની ઍપ્લિકેશન નોટિફિકેશન ચાલુ કરો" + "સેટિંગ્સ બદલો" + "નોટિફિકેશન માટેનું ચિહ્ન બતાવો" + "હોમ સ્ક્રીન પર આઇકન ઉમેરો" + "નવી ઍપ્લિકેશનો માટે" + "આઇકનનો આકાર બદલો" + "હોમ સ્ક્રીન પર" + "સિસ્ટમ ડિફૉલ્ટનો ઉપયોગ કરો" + "ચોરસ" + "ચોરસ જેવું ગોળ" + "વર્તુળ" + "ટિઅરડ્રોપ" + "આઇકનના આકારમાં કરેલ ફેરફારો લાગુ કરી રહ્યા છીએ" + "અજાણ્યો" + "દૂર કરો" + "શોધો" + "આ ઍપ્લિકેશન ઇન્સ્ટોલ થયેલ નથી" + "આ આયકન માટેની ઍપ્લિકેશન ઇન્સ્ટોલ થયેલ નથી. તમે તેને દૂર કરી શકો છો અથવા ઍપ્લિકેશન માટે શોધ કરી અને તેને મેન્યુઅલી ઇન્સ્ટોલ કરી શકો છો." + "%1$s ડાઉનલોડ કરી રહ્યાં છે, %2$s પૂર્ણ" + "%1$s, ઇન્સ્ટૉલ થવાની રાહ જોઈ રહ્યું છે" + "%1$s વિજેટ" + "હોમ સ્ક્રીન પર ઉમેરો" + "આઇટમ અહીં ખસેડો" + "હોમ સ્ક્રીનમાં આઇટમ ઉમેરી" + "આઇટમ દૂર કરી" + "આઇટમ ખસેડો" + "%1$s પંક્તિ %2$s કૉલમ પર ખસેડો" + "%1$s સ્થિતિ પર ખસેડો" + "મનપસંદ સ્થિતિ %1$s પર ખસેડો" + "આઇટમ ખસેડી" + "ફોલ્ડરમાં ઉમેરો: %1$s" + "%1$s સાથે ફોલ્ડરમાં ઉમેરો" + "ફોલ્ડરમાં આઇટમ ઉમેરી" + "આની સાથે ફોલ્ડર બનાવો: %1$s" + "ફોલ્ડર બનાવ્યું" + "હોમ સ્ક્રીન પર ખસેડો" + "આકાર બદલો" + "પહોળાઈ વધારો" + "ઊંચાઈ વધારો" + "પહોળાઈ ઘટાડો" + "ઊંચાઈ ઘટાડો" + "વિજેટનો આકાર બદલીને %1$s પહોળાઈ %2$s ઊંચાઈ કર્યો" + "શૉર્ટકટ્સ" + "%2$s માટે %1$d શૉર્ટકટ" + "%3$s માટે %1$d શૉર્ટકટ અને %2$d સૂચનાઓ" + "છોડી દો" + "સૂચના છોડી દીધી" + "મનગમતી ઍપ" + "કાર્યાલયની ઍપ" + "કાર્યાલયની પ્રોફાઇલ" + "કાર્ય ઍપને અહીંથી મેળવો" + "દરેક કાર્ય ઍપ પાસે એક બૅજ હોય છે અને તમારી સંસ્થા દ્વારા તેને સુરક્ષિત રાખવામાં આવે છે. વધુ સરળ ઍક્સેસ માટે ઍપને તમારી હોમ સ્ક્રીન પર ખસેડો." + "તમારી સંસ્થા દ્વારા મેનેજ કરેલ" + "નોટિફિકેશન અને ઍપ બંધ છે" + "બંધ કરો" + "બંધ" + diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index efc953c809..aa0b3af1f0 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -81,6 +81,8 @@ "વૉલપેપર્સ" "હોમ સેટિંગ્સ" "તમારા વ્યવસ્થાપક દ્વારા અક્ષમ કરેલ" + "હોમ સ્ક્રીનને ફેરવવાની મંજૂરી આપો" + "જ્યારે ફોન ફેરવવામાં આવે ત્યારે" "સૂચના બિંદુઓ" "ચાલુ" "બંધ" @@ -128,8 +130,8 @@ "ઊંચાઈ ઘટાડો" "વિજેટનો આકાર બદલીને %1$s પહોળાઈ %2$s ઊંચાઈ કર્યો" "શૉર્ટકટ્સ" - "%2$s માટે %1$d શૉર્ટકટ" - "%3$s માટે %1$d શૉર્ટકટ અને %2$d સૂચનાઓ" + + "છોડી દો" "સૂચના છોડી દીધી" "મનગમતી ઍપ" diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index f98859df8c..1b47fcbbea 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -81,6 +81,8 @@ "वॉलपेपर" "होम पेज की सेटिंग" "आपके एडमिन ने बंद किया हुआ है" + "होमस्क्रीन घुमाने की अनुमति दें" + "फ़ोन घुुमाए जाने पर" "सूचना बिंदु" "चालू" "बंद" @@ -89,7 +91,7 @@ "सेटिंग बदलें" "नए नोटिफ़िकेशन बताने वाला गोल निशान दिखाएं" "होम स्क्रीन में आइकॉन जोड़ें" - "नए ऐप के लिए" + "नए ऐप्लिकेशन के लिए" "आइकॉन का आकार बदलें" "होम स्‍क्रीन पर" "सिस्टम डिफ़ॉल्ट का उपयोग करें" @@ -128,8 +130,8 @@ "ऊंचाई घटाएं" "विजेट का आकार बदलकर उसकी चौड़ाई %1$s और ऊंचाई %2$s कर दी गई" "शॉर्टकट" - "%2$s के लिए %1$d शॉर्टकट" - "%3$s के लिए %1$d शॉर्टकट और %2$d सूचनाएं हैं" + + "खारिज करें" "सूचना को खारिज किया गया" "निजी ऐप" diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index 35a7963936..077da67e25 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -80,8 +80,10 @@ "Mapa: %1$s" "Widgeti" "Pozadine" - "Postavke Homea" + "Postavke početnog zaslona" "Onemogućio administrator" + "Dopusti zakretanje početnog zaslona" + "Kada se telefon zakrene" "Točke obavijesti" "Uključeno" "Isključeno" @@ -129,8 +131,8 @@ "Smanjenje visine" "Širina widgeta promijenjena je na %1$s, a visina na %2$s" "Prečaci" - "Prečaca za aplikaciju %2$s: %1$d" - "Za aplikaciju %3$s ima prečaca (ukupno %1$d) i obavijesti (ukupno %2$d)" + + "Odbaci" "Obavijest je odbačena" "Osobno" diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index 4972e81924..797bde44ad 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -79,8 +79,10 @@ "Mappa: %1$s" "Modulok" "Háttérképek" - "A Home beállításai" + "Kezdőoldal beállításai" "A rendszergazda letiltotta" + "A kezdőképernyő elforgatásának engedélyezése" + "A telefon elforgatásakor" "Értesítési pöttyök" "Bekapcsolva" "Kikapcsolva" @@ -128,8 +130,8 @@ "Magasság csökkentése" "Modul átméretezve %1$s szélességre és %2$s magasságra" "Gyorsparancsok" - "%1$d gyorsparancs a(z) %2$s számára" - "%1$d parancsikon és %2$d értesítés a következő alkalmazásnál: %3$s" + + "Elvetés" "Értesítés elvetve" "Személyes" diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml new file mode 100644 index 0000000000..6844a27573 --- /dev/null +++ b/res/values-hy-rAM/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "Աշխատանքային" + "Ծրագիրը տեղադրված չէ:" + "Հավելվածը հասանելի չէ" + "Ներբեռնված ծրագիրն անջատված է Անվտանգ ռեժիմում" + "Վիջեթներն անջատված են անվտանգ ռեժիմում" + "Դյուրանցումն անհասանելի է" + "Հիմնական էկրան" + "Հատուկ գործողություններ" + "Հպեք և պահեք՝ վիջեթն ընտրելու համար:" + "Կրկնակի հպեք և պահեք՝ վիջեթ ավելացնելու համար կամ օգտվեք հարմարեցրած գործողություններից:" + "%1$d × %2$d" + "Լայնությունը՝ %1$d, բարձրությունը՝ %2$d" + "Հպեք և պահեք՝ ձեռքով տեղադրելու համար" + "Ավելացնել ավտոմատ կերպով" + "Որոնել հավելվածներ" + "Հավելվածների բեռնում…" + %1$s» հարցմանը համապատասխանող հավելվածներ չեն գտնվել" + "Որոնել այլ հավելվածներ" + "Ծանուցումներ" + "Կրկնակի հպեք և պահեք՝ դյուրանցում ընտրելու համար։" + "Կրկնակի հպեք և պահեք՝ դյուրանցում ընտրելու համար կամ օգտվեք հարմարեցրած գործողություններից:" + "Այլևս տեղ չկա այս հիմնական էկրանին:" + "Ընտրյալների ցուցակում այլևս ազատ տեղ չկա" + "Հավելվածների ցանկ" + "Անձնական հավելվածների ցանկ" + "Աշխատանքային հավելվածների ցանկ" + "Հիմնական" + "Հեռացնել" + "Հեռացնել" + "Հավելվածի տվյալներ" + "Տեղադրել" + "տեղադրել դյուրանցումներ" + "Ծրագրին թույլ է տալիս ավելացնել դյուրանցումներ՝ առանց օգտագործողի միջամտության:" + "կարդալ հիմնաէջի կարգավորումներն ու դյուրանցումները" + "Ծրագրին թույլ է տալիս կարդալ հիմնաէջի կարգավորումներն ու դյուրանցումները:" + "ստեղծել հիմնաէջի կարգավորումներ ու դյուրանցումներ" + "Ծրագրին թույլ է տալիս փոփոխել հիմնաէջի կարգավորումներն ու դյուրանցումները:" + "%1$s հավելվածին չի թույլատրվում հեռախոսազանգեր կատարել" + "Վիջեթի բեռնման խնդիր կա" + "Կարգավորում" + "Սա համակարգային ծրագիր է և չի կարող ապատեղադրվել:" + "Անանուն պանակ" + "%1$s հավելվածն անջատված է" + + %1$s, ունի %2$d ծանուցում + %1$s, ունի %2$d ծանուցում + + "Էջ %1$d՝ %2$d-ից" + "Հիմնական էկրան %1$d` %2$d-ից" + "Հիմնական էկրանի նոր էջ" + "Պանակը բաց է, %1$d-ից %2$d" + "Հպեք՝ պանակը փակելու համար" + "Հպեք՝ նոր անվանումը պահելու համար" + "Պանակը փակ է" + "Պանակը վերանվանվեց %1$s" + "Պանակ՝ %1$s" + "Վիջեթներ" + "Պաստառներ" + "Գլխավոր էջի կարգավորումներ" + "Անջատվել է ձեր ադմինիստրատորի կողմից" + "Թույլ տալ հիմնական էկրանի պտտումը" + "Հեռախոսը պտտելու դեպքում" + "Ծանուցումների կետիկներ" + "Միացված է" + "Անջատված է" + "Անհրաժեշտ է ծանուցման թույլտվություն" + "Ծանուցումների կետիկները ցուցադրելու համար միացրեք ծանուցումները %1$s-ի համար" + "Փոխել կարգավորումները" + "Ցուցադրել ծանուցումների կետիկները" + "Ավելացնել պատկերակը Հիմնական էկրանին" + "Նոր հավելվածների համար" + "Փոխել պատկերակների տեսքը" + "հիմնական էկրանին" + "Օգտագործել համակարգի կանխադրված կարգավորումը" + "Քառակուսի" + "Քառանկյուն" + "Օղակ" + "Արցունքաձև" + "Պատկերակների տեսքի փոփոխությունները կիրառվում են" + "Անհայտ է" + "Հեռացնել" + "Գտնել" + "Այս ծրագիրը տեղադրված չէ:" + "Այս պատկերակի ծրագիրը տեղադրված չէ: Դուք կարող եք հեռացնել այն կամ գտնել ծրագիրը և տեղադրել այն ձեռքով:" + "%1$s–ի ներբեռնում (%2$s)" + "%1$s-ի տեղադրման սպասում" + "%1$s վիջեթներ" + "Ավելացնել Հիմնական էկրանին" + "Տեղափոխել տարրն այստեղ" + "Տարրն ավելացվեց հիմնական էկրանին" + "Տարրը հեռացվեց" + "Տեղափոխել տարրը" + "Տեղափոխել տող %1$s սյունակ %2$s" + "Տեղափոխել դիրք %1$s" + "Տեղափոխել նախընտրած դիրք՝ %1$s" + "Տարրը տեղափոխվեց" + "Ավելացնել թղթապանակում՝ %1$s" + "Ավելացնել «%1$s» պանակին" + "Տարրն ավելացվեց թղթապանակում" + "Ստեղծել թղթապանակ, օգտագործելով՝ %1$s" + "Պանակը ստեղծվեց" + "Տեղափոխել Հիմնական էկրան" + "Չափափոխել" + "Ավելացնել լայնությունը" + "Ավելացնել բարձրությունը" + "Նվազեցնել լայնությունը" + "Նվազեցնել բարձրությունը" + "Վիջեթի լայնությունը փոխվել է %1$s-ի, իսկ բարձրությունը՝ %2$s-ի" + "Դյուրանցումներ" + "%1$d դյուրանցումներ %2$s հավելվածի համար" + "%1$d դյուրացում և %2$d ծանուցում %3$s-ի համար" + "Անտեսել" + "Ծանուցումը մերժված է" + "Անձնական" + "Աշխատանքային" + "Աշխատանքային պրոֆիլ" + "Գտեք աշխատանքային հավելվածներ այստեղ" + "Աշխատանքային հավելվածները նշված են հատուկ նշանով: Նման հավելվածների անվտանգությունը ապահովում է ձեր կազմակերպությունը։ Հարմարության համար աշխատանքային հավելվածները կարող եք տեղափոխել հիմնական էկրան։" + "Կառավարվում է ձեր կազմակերպության կողմից" + "Ծանուցումներն ու հավելվածներն անջատված են" + "Փակել" + "Փակվեց" + diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index 8c3ae2591d..79210f3a77 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -81,6 +81,8 @@ "Պաստառներ" "Գլխավոր էջի կարգավորումներ" "Անջատվել է ձեր ադմինիստրատորի կողմից" + "Թույլ տալ հիմնական էկրանի պտտումը" + "Հեռախոսը պտտելու դեպքում" "Ծանուցումների կետիկներ" "Միացված է" "Անջատված է" @@ -128,8 +130,8 @@ "Նվազեցնել բարձրությունը" "Վիջեթի լայնությունը փոխվել է %1$s-ի, իսկ բարձրությունը՝ %2$s-ի" "Դյուրանցումներ" - "%1$d դյուրանցումներ %2$s հավելվածի համար" - "%1$d դյուրացում և %2$d ծանուցում %3$s-ի համար" + + "Անտեսել" "Ծանուցումը մերժված է" "Անձնական" diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index ea0ea4af12..6e8f46a2cd 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -30,7 +30,7 @@ "Layar utama" "Tindakan khusus" "Sentuh lama untuk memilih widget." - "Ketuk dua kalip & tahan untuk mengambil widget atau menggunakan tindakan khusus." + "Tap dua kalip & tahan untuk mengambil widget atau menggunakan tindakan khusus." "%1$d × %2$d" "lebar %1$d x tinggi %2$d" "Sentuh & tahan untuk menempatkan secara manual" @@ -72,8 +72,8 @@ "Layar utama %1$d dari %2$d" "Halaman layar utama baru" "Folder dibuka, %1$d x %2$d" - "Ketuk untuk menutup folder" - "Ketuk untuk menyimpan ganti nama" + "Tap untuk menutup folder" + "Tap untuk menyimpan ganti nama" "Folder ditutup" "Folder diganti namanya menjadi %1$s" "Folder: %1$s" @@ -81,6 +81,8 @@ "Wallpaper" "Setelan layar Utama" "Dinonaktifkan oleh admin" + "Izinkan layar Utama diputar" + "Saat ponsel diputar" "Titik notifikasi" "Aktif" "Nonaktif" @@ -128,8 +130,8 @@ "Kurangi tinggi" "Widget diubah ukurannya menjadi lebar %1$s tinggi %2$s" "Pintasan" - "%1$d pintasan untuk %2$s" - "%1$d pintasan dan %2$d notifikasi untuk %3$s" + + "Tutup" "Notifikasi ditutup" "Pribadi" diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml new file mode 100644 index 0000000000..3b5dabacce --- /dev/null +++ b/res/values-is-rIS/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "Vinna" + "Forritið er ekki uppsett." + "Forritið er ekki í boði" + "Sótt forrit er óvirkt í öryggisstillingu" + "Græjur eru óvirkar í öruggri stillingu" + "Flýtileið er ekki tiltæk" + "Heimaskjár" + "Sérsniðnar aðgerðir" + "Haltu fingri á græju til að grípa hana." + "Ýttu tvisvar og haltu fingri á græju til að grípa hana eða notaðu sérsniðnar aðgerðir." + "%1$d × %2$d" + "%1$d á breidd og %2$d á hæð" + "Haltu inni til að staðsetja handvirkt" + "Bæta sjálfkrafa við" + "Leita í forritum" + "Hleður forrit…" + "Ekki fundust forrit sem samsvara „%1$s“" + "Leita að fleiri forritum" + "Tilkynningar" + "Haltu fingri á flýtileið til að grípa hana." + "Ýttu tvisvar og haltu fingri á flýtileið til að grípa hana eða notaðu sérsniðnar aðgerðir." + "Ekki meira pláss á þessum heimaskjá." + "Ekki meira pláss í bakka fyrir uppáhald" + "Forritalisti" + "Listi yfir eigin forrit" + "Listi yfir vinnuforrit" + "Heim" + "Fjarlægja" + "Fjarlægja" + "Forritsupplýsingar" + "Setja upp" + "setja upp flýtileiðir" + "Leyfir forriti að bæta við flýtileiðum án íhlutunar notanda." + "lesa stillingar og flýtileiðir heimaskjás" + "Leyfir forriti að lesa stillingar og flýtileiðir heimaskjás." + "skrifa stillingar og flýtileiðir heimaskjás" + "Leyfir forriti að breyta stillingum og flýtileiðum heimaskjás." + "%1$s hefur ekki leyfi til að hringja símtöl" + "Vandamál við að hlaða græju" + "Uppsetning" + "Þetta er kerfisforrit sem ekki er hægt að fjarlægja." + "Ónefnd mappa" + "Óvirkt %1$s" + + %1$s, er með %2$d tilkynningu + %1$s, er með %2$d tilkynningar + + "Síða %1$d af %2$d" + "Heimaskjár %1$d af %2$d" + "Ný síða á heimaskjá" + "Mappa opnuð, %1$d sinnum %2$d" + "Ýttu til að loka möppunni" + "Ýttu til að vista breytt heiti" + "Möppu lokað" + "Heiti möppu breytt í %1$s" + "Mappa: %1$s" + "Græjur" + "Veggfóður" + "Heimastillingar" + "Gert óvirkt af kerfisstjóra" + "Leyfa snúning fyrir heimaskjá" + "Þegar símanum er snúið" + "Tilkynningapunktar" + "Kveikt" + "Slökkt" + "Aðgangs að tilkynningum er krafist" + "Til að sýna tilkynningarpunkta skaltu kveikja á forritstilkynningum fyrir %1$s" + "Breyta stillingum" + "Sýna tilkynningapunkta" + "Bæta tákni á heimaskjáinn" + "Fyrir ný forrit" + "Breyta formi tákns" + "á heimaskjá" + "Nota sjálfgildi kerfis" + "Ferningur" + "Ferhringur" + "Hringur" + "Dropi" + "Breytir formi tákns" + "Óþekkt" + "Fjarlægja" + "Leita" + "Þetta forrit er ekki uppsett" + "Forritið fyrir þetta tákn er ekki uppsett. Þú getur fjarlægt það eða leitað að forritinu og sett það upp handvirkt." + "%1$s í niðurhali, %2$s lokið" + "%1$s bíður uppsetningar" + "%1$s-græjur" + "Bæta á heimaskjá" + "Færa atriði hingað" + "Atriði bætt á heimaskjáinn" + "Atriði fjarlægt" + "Færa atriði" + "Færa í línu %1$s, dálk %2$s" + "Færa í stöðu %1$s" + "Færa í stöðu %1$s á festisvæði" + "Atriði fært" + "Setja í möppu: %1$s" + "Setja í möppu með %1$s" + "Atriði sett í möppu" + "Búa til möppu með: %1$s" + "Mappa búin til" + "Færa á heimaskjá" + "Breyta stærð" + "Auka breidd" + "Auka hæð" + "Minnka breidd" + "Minnka hæð" + "Stærð græju breytt í %1$s á breidd og %2$s á hæð" + "Flýtileiðir" + "%1$d flýtileiðir fyrir %2$s" + "%1$d flýtileiðir og %2$d tilkynningar fyrir %3$s" + "Hunsa" + "Tilkynningu lokað" + "Persónulegt" + "Vinna" + "Vinnusnið" + "Hér finnurðu vinnuforrit" + "Öll vinnuforrit eru með merki og fyrirtækið þitt tryggir öryggi þeirra. Færðu forrit yfir á heimaskjáinn til að fá auðveldari aðgang að þeim." + "Stjórnað af fyrirtækinu þínu" + "Slökkt er á tilkynningum og forritum" + "Loka" + "Lokað" + diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index 3dc2d22118..49843b668c 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -81,6 +81,8 @@ "Veggfóður" "Heimastillingar" "Gert óvirkt af kerfisstjóra" + "Leyfa snúning fyrir heimaskjá" + "Þegar símanum er snúið" "Tilkynningapunktar" "Kveikt" "Slökkt" @@ -128,8 +130,8 @@ "Minnka hæð" "Stærð græju breytt í %1$s á breidd og %2$s á hæð" "Flýtileiðir" - "%1$d flýtileiðir fyrir %2$s" - "%1$d flýtileiðir og %2$d tilkynningar fyrir %3$s" + + "Hunsa" "Tilkynningu lokað" "Persónulegt" diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 44e12c0e40..5fc68a51b5 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -81,6 +81,8 @@ "Sfondi" "Impostazioni Home" "Disattivata dall\'amministratore" + "Consenti rotazione della schermata Home" + "Con il telefono ruotato" "Indicatori notifica" "Attiva" "Non attiva" @@ -128,8 +130,8 @@ "Riduci altezza" "Widget ridimensionato a larghezza %1$s, altezza %2$s" "Scorciatoie" - "%1$d scorciatoie per %2$s" - "%1$d scorciatoie e %2$d notifiche relative a %3$s" + + "Ignora" "Notifica ignorata" "Personali" diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index bc2061ba28..806aeefb5c 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -83,6 +83,8 @@ "טפטים" "הגדרות דף הבית" "הושבת על ידי מנהל המערכת שלך" + "אפשרות סיבוב של מסך דף הבית" + "כאשר הטלפון מסובב" "סימני הודעות" "מופעלת" "כבויה" @@ -130,8 +132,8 @@ "הקטן גובה" "גודל הווידג\'ט שונה - רוחב %1$s גובה %2$s" "קיצורי דרך" - "%1$d קיצורי דרך עבור %2$s" - "%1$d קיצורי דרך ו-%2$d הודעות של %3$s" + + "סגור" "ההודעה נסגרה" "אישיות" diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index c5ab31039c..baa59ab94e 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -81,6 +81,8 @@ "壁紙" "ホームの設定" "管理者により無効にされています" + "ホーム画面の回転を許可" + "スマートフォンが回転したとき" "通知ドット" "ON" "OFF" @@ -128,8 +130,8 @@ "高さを低くする" "ウィジェットのサイズを幅%1$s、高さ%2$sに変更しました" "ショートカット" - "%2$s用の %1$d 件のショートカット" - "%3$s: %1$d 個のショートカットと %2$d 件の通知" + + "表示しない" "通知を非表示にしました" "個人用" diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml new file mode 100644 index 0000000000..521ec80f8c --- /dev/null +++ b/res/values-ka-rGE/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "სამუშაო" + "აპი არ არის დაყენებული." + "აპი მიუწვდომელია" + "უსაფრთხო რეჟიმში ჩამოტვირთული აპი გაუქმებულია" + "უსაფრთხო რეჟიმში ვიჯეტი გამორთულია" + "მალსახმობი მიუწვდომელია" + "მთავარი ეკრანი" + "მორგებული ქმედებები" + "შეეხეთ და დააყოვნეთ ვიჯეტის ასარჩევად." + "ორმაგად შეეხეთ და გეჭიროთ ვიჯეტის ასარჩევად ან მორგებული მოქმედებების გამოსაყენებლად." + "%1$d × %2$d" + "სიგრძე: %1$d, სიგანე: %2$d" + "ხანგრძლივად შეეხეთ ხელით განსათავსებლად" + "ავტომატურად დამატება" + "აპების ძიება" + "აპები იტვირთება…" + "„%1$s“-ის თანხვედრი აპები არ მოიძებნა" + "მეტი აპის პოვნა" + "შეტყობინებები" + "შეეხეთ და დააყოვნეთ მალსახმობის ასარჩევად." + "ორმაგად შეეხეთ და გეჭიროთ მალსახმობის ასარჩევად ან მორგებული მოქმედებების გამოსაყენებლად." + "ამ მთავარ ეკრანზე ადგილი აღარ არის." + "რჩეულების თაროზე ადგილი არ არის" + "აპების სია" + "პერსონალური აპების სია" + "სამსახურის აპების სია" + "მთავარი" + "ამოშლა" + "დეინსტალაცია" + "აპის შესახებ" + "ინსტალაცია" + "მალსახმობების დაყენება" + "აპისთვის მალსახმობების დამოუკიდებლად დამატების უფლების მიცემა." + "მთავარი ეკრანის პარამეტრებისა და მალსახმობების წაკითხვა" + "აპისთვის მთავარი ეკრანის პარამეტრებისა და მალსახმობების წაკითხვის უფლების მიცემა." + "მთავარი ეკრანის პარამეტრებისა და მალსახმობების ჩაწერა" + "აპისთვის მთავარი ეკრანის პარამეტრებისა და მალსახმობების შეცვლის უფლების მიცემა." + "%1$s-ს არ აქვს სატელეფონო ზარების განხორციელების უფლება" + "პრობლემა ვიჯეტის ჩატვირთვისას" + "დაყენება" + "ეს სისტემური აპია და მისი წაშლა შეუძლებელია." + "უსახელო საქაღალდე" + "%1$s გაითიშა" + + %1$s-ში %2$d შეტყობინებაა + %1$s-ში %2$d შეტყობინებაა + + "გვერდი %1$d %2$d-დან" + "მთავარი ეკრანი %1$d, %2$d-დან" + "მთავარი ეკრანის ახალი გვერდი" + "საქაღალდე გახსნილია, %1$d x %2$d" + "შეეხეთ საქაღალდის დასახურად" + "შეეხეთ გადარქმეული სახელის შესანახად" + "საქაღალდე დაიხურა" + "საქაღალდეს შეეცვალა სახელი „%1$s“-ად" + "საქაღალდე: %1$s" + "ვიჯეტები" + "ფონები" + "მთავარი გვერდის პარამეტრები" + "გათიშულია თქვენი ადმინისტრატორის მიერ" + "მთავარი ეკრანის შეტრიალების დაშვება" + "ტელეფონის შეტრიალებისას" + "შეტყობინების ნიშნულები" + "ჩართული" + "გამორთული" + "საჭიროა შეტყობინებებზე წვდომა" + "შეტყობინებათა ნიშნულების საჩვენებლად, ჩართეთ აპის შეტყობინებები %1$s-ისთვის" + "პარამეტრების შეცვლა" + "შეტყობინების ნიშნულების ჩვენება" + "ხატულას მთავარ ეკრანზე დამატება" + "ახალი აპებისთვის" + "ხატულას ფორმის შეცვლა" + "მთავარ ეკრანზე" + "ნაგულისხმევი სისტემური პარამეტრების გამოყენება" + "კვადრატი" + "წრეკუთხედი" + "წრე" + "წვეთი" + "მიმდინარეობს ხატულას ფორმის ცვლილებების მიყენება" + "უცნობი" + "ამოშლა" + "ძიება" + "ეს აპი დაყენებული არ არის" + "ამ ხატულის აპი დაყენებული არ არის. შეგიძლიათ ამოშალოთ, ან მოიძიოთ აპი და ხელით მოახდინოთ მისი ინსტალაცია." + "მიმდინარეობს %1$s-ის ჩამოტვირთვა, %2$s დასრულდა" + "%1$s ელოდება ინსტალაციას" + "%1$s-ის ვიჯეტები" + "მთავარ ეკრანზე დამატება" + "ერთეულის გადაადგილება აქ" + "ერთეული დაემატა მთავარ ეკრანს" + "ერთეული წაიშალა" + "ერთეულის გადაადგილება" + "გადატანა რიგში %1$s სვეტში %2$s" + "გადატანა %1$s პოზიციაზე" + "გადატანა რჩეულთა პოზიციაზე %1$s" + "ერთეული გადაადგილდა" + "საქაღალდეში დამატება: %1$s" + "საქაღალდეში დამატება %1$s-ით" + "ერთეული დაემატა საქაღალდეს" + "საქაღალდის შექმნა ერთეულით: %1$s" + "საქაღალდე შექმნილია" + "მთავარ ეკრანზე გადატანა" + "ზომის შეცვლა" + "სიგანის გაზრდა" + "სიმაღლის გაზრდა" + "სიგანის შემცირება" + "სიმაღლის შემცირება" + "ვიჯეტის ზომები შეიცვალა: სიგანე %1$s სიმაღლე %2$s" + "მალსახმობები" + "%2$s-ს აქვს %1$d მალსახმობი" + "%3$s-ის %1$d მალსახმობი და %2$d შეტყობინება" + "დახურვა" + "შეტყობინება დაიხურა" + "პირადი" + "სამსახური" + "სამსახურის პროფილი" + "აქ თავმოყრილია სამსახურის აპები" + "სამსახურის თითოეულ აპს აქვს ბეჯი, რაც ნიშნავს, რომ მათ უსაფრთხოებას თქვენი ორგანიზაცია უზრუნველყოფს. მარტივი წვდომისთვის, შეგიძლიათ სამსახურის აპები მთავარი ეკრანზე გადაიტანოთ." + "იმართება თქვენი ორგანიზაციის მიერ" + "შეტყობინებები და აპები გამორთულია" + "დახურვა" + "დახურული" + diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index 02ca8628ed..64c8573e12 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -81,6 +81,8 @@ "ფონები" "მთავარი გვერდის პარამეტრები" "გათიშულია თქვენი ადმინისტრატორის მიერ" + "მთავარი ეკრანის შეტრიალების დაშვება" + "ტელეფონის შეტრიალებისას" "შეტყობინების ნიშნულები" "ჩართული" "გამორთული" @@ -128,8 +130,8 @@ "სიმაღლის შემცირება" "ვიჯეტის ზომები შეიცვალა: სიგანე %1$s სიმაღლე %2$s" "მალსახმობები" - "%2$s-ს აქვს %1$d მალსახმობი" - "%3$s-ის %1$d მალსახმობი და %2$d შეტყობინება" + + "დახურვა" "შეტყობინება დაიხურა" "პირადი" diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml new file mode 100644 index 0000000000..7ab73d95dd --- /dev/null +++ b/res/values-kk-rKZ/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "Жұмыс" + "Қолданба орнатылмаған." + "Қолданба қол жетімді емес" + "Жүктелген қолданба қауіпсіз режимде өшірілген" + "Қауіпсіз режимде виджеттер өшіріледі" + "Таңбаша қолжетімді емес" + "Негізгі экран" + "Арнаулы әрекеттер" + "Виджетті таңдау үшін түртіп, мықтап ұстаңыз." + "Виджетті таңдау немесе арнаулы әрекеттерді таңдау үшін екі рет түртіп, ұстап тұрыңыз." + "%1$d × %2$d" + "Ені: %1$d, биіктігі: %2$d" + "Қолмен қою үшін басып тұрыңыз" + "Автоматты енгізу" + "Қолданбаларды іздеу" + "Қолданбалар жүктелуде…" + "\"%1$s\" сұрауына сәйкес келетін қолданбалар жоқ" + "Қосымша қолданбалар іздеу" + "Хабарландырулар" + "Таңбашаны таңдау үшін оны басып, ұстап тұрыңыз." + "Екі рет басып, ұстап тұрып, таңбашаны таңдаңыз немесе арнаулы әрекеттерді пайдаланыңыз." + "Бұл Негізгі экранда орын қалмады." + "Қалаулылар науасында орын қалмады" + "Қолданбалар тізімі" + "Жеке қолданбалар тізімі" + "Жұмыс қолданбаларының тізімі" + "Негізгі" + "Жою" + "Жою" + "Қолданба ақпараты" + "Орнату" + "төте пернелерді орнату" + "Қолданбаға пайдаланушының қатысуынсыз төте пернелерді қосу мүмкіндігін береді." + "Негізгі экрандағы параметрлер мен төте пернелерді оқу" + "Қолданбаға Негізгі экрандағы параметрлер мен төте пернелерді оқу мүмкіндігін береді." + "Негізгі экран параметрлері мен төте пернелерін жазу" + "Қолданбаға Негізгі экрандағы параметрлер мен төте пернелерді өзгерту мүмкіндігін береді." + "%1$s арқылы телефон қоңырауларын соғуға рұқсат етілмеген" + "Виджетті жүктеу барысында мәселе орын алды" + "Орнату" + "Бұл жүйе қолданбасы, сондықтан оны алу мүмкін емес." + "Атауы жоқ қалта" + "%1$s өшірілді" + + %1$s қолданбасында %2$d хабарландыру бар + %1$s қолданбасында %2$d хабарландыру бар + + "%1$d бет, барлығы %2$d" + "%1$d негізгі экран, барлығы %2$d" + "Жаңа негізгі экран беті" + "Қалта ашылды, %1$d және %2$d" + "Қалтаны жабу үшін түртіңіз" + "Қайта атауды сақтау үшін түртіңіз" + "Қалта жабылды" + "Қалта атауы %1$s болып өзгертілді" + "Қалта: %1$s" + "Виджеттер" + "Тұсқағаздар" + "Негізгі экран параметрлері" + "Әкімші өшірді" + "Негізгі экранның бұрылуына рұқсат ету" + "Телефон бұрылғанда" + "Хабарландыру белгілері" + "Қосулы" + "Өшірулі" + "Хабарландыруға кіру рұқсаты қажет" + "Хабарландыру белгілерін көрсету үшін %1$s қолданбасының қолданба хабарландыруларын қосыңыз" + "Параметрлерді өзгерту" + "Хабарландыру белгілерін көрсету" + "Негізгі экранға белгіше енгізу" + "Жаңа қолданбаларға арналған" + "Белгіше пішінін өзгерту" + "Негізгі экранда" + "Жүйенің әдепкі параметрін пайдалану" + "Шаршы" + "Жұмыр төртбұрыш" + "Шеңбер" + "Тамшы" + "Белгіше пішіні өзгерістері күшіне енуде" + "Белгісіз" + "Алып тастау" + "Іздеу" + "Бұл қолданба орнатылмаған" + "Осы белгіше үшін қолданба орнатылмаған. Оны жоюға болады немесе қолданбаны іздеп, қолмен орнатуға болады." + "%1$s жүктелуде, %2$s аяқталды" + "%1$s орнату күтілуде" + "%1$s виджеті" + "Негізгі экранға қосу" + "Элементті мұнда жылжыту" + "Элемент негізгі экранға қосылды" + "Элемент жойылды" + "Элементті жылжыту" + "%1$s-жол, %2$s-бағанға жылжыту" + "%1$s-орынға жылжыту" + "%1$s нөмірлі таңдаулы орынға жылжыту" + "Элемент жылжытылды" + "Қалтаға қосу: %1$s" + "%1$s бар қалтаға қосу" + "Элемент қалтаға қосылды" + "Мына бар қалтаны жасау: %1$s" + "Қалта жасалды" + "Негізгі экранға жылжыту" + "Өлшемін өзгерту" + "Енін арттыру" + "Биіктігін арттыру" + "Енін азайту" + "Биіктігін азайту" + "Виджет өлшемінің ені %1$s, биіктігі %2$s болып өзгертілді" + "Таңбашалар" + "%2$s қолданбасына арналған %1$d таңбаша" + "%3$s қолданбасының %1$d таңбашасы мен %2$d хабарландыруы" + "Бас тарту" + "Хабарландырудан бас тартылды" + "Жеке" + "Жұмыс" + "Жұмыс профилі" + "Жұмыс қолданбалары осы жерде берілген" + "Әрбір жұмыс қолданбасында танымбелгі бар. Ол оның қауіпсіздігі ұйым арқылы қамтамасыз етілетінін білдіреді. Жұмыс қолданбаларына оңай кіру үшін, оларды Негізгі экранға жылжытуға болады." + "Ұйым арқылы басқарылады" + "Хабарландырулар мен қолданбалар өшірулі" + "Жабу" + "Жабық" + diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index b66fe69a39..2ad595458d 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -81,6 +81,8 @@ "Тұсқағаздар" "Негізгі экран параметрлері" "Әкімші өшірді" + "Негізгі экранның бұрылуына рұқсат ету" + "Телефон бұрылғанда" "Хабарландыру белгілері" "Қосулы" "Өшірулі" @@ -128,8 +130,8 @@ "Биіктігін азайту" "Виджет өлшемінің ені %1$s, биіктігі %2$s болып өзгертілді" "Таңбашалар" - "%2$s қолданбасына арналған %1$d таңбаша" - "%3$s қолданбасының %1$d таңбашасы мен %2$d хабарландыруы" + + "Бас тарту" "Хабарландырудан бас тартылды" "Жеке" diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml new file mode 100644 index 0000000000..582bb33dd2 --- /dev/null +++ b/res/values-km-rKH/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "ការងារ" + "មិន​បាន​ដំឡើង​កម្មវិធី។" + "មិន​មាន​កម្មវិធី" + "បាន​បិទ​កម្មវិធី​ដែល​បាន​ទាញ​យក​ក្នុង​របៀប​សុវត្ថិភាព" + "បាន​បិទ​ធាតុ​ក្រាហ្វិក​ក្នុង​របៀប​សុវត្ថិភាព" + "ផ្លូវកាត់មិនអាចប្រើបានទេ" + "អេក្រង់ដើម" + "សកម្មភាព​ផ្ទាល់ខ្លួន" + "ប៉ះ & សង្កត់ ដើម្បី​ជ្រើស​ធាតុ​ក្រាហ្វិក។" + "ប៉ះពីរដង ហើយចុចឲ្យជាប់ដើម្បីជ្រើសយកធាតុក្រាហ្វិក ឬប្រើសកម្មភាពផ្ទាល់ខ្លួន។" + "%1$d × %2$d" + "ទទឺង %1$d គុណនឹងកម្ពស់ %2$d" + "ចុច​ឲ្យជាប់​ដើម្បី​បញ្ចូលវា​ដោយផ្ទាល់" + "បញ្ចូល​ដោយ​ស្វ័យ​ប្រវត្តិ" + "ស្វែងរក​កម្មវិធី" + "កំពុងផ្ទុកកម្មវិធី…" + "រកមិនឃើញកម្មវិធី​ដែលត្រូវគ្នាជាមួយ \"%1$s\" ទេ" + "ស្វែងរកកម្មវិធីច្រើនទៀត" + "ការ​ជូនដំណឹង" + "ចុច​ឱ្យ​ជាប់​ដើម្បី​ជ្រើស​រើស​ផ្លូវកាត់​មួយ។" + "ចុច​ពីរ​ដង ហើយ​ចុច​ឱ្យ​ជាប់​ដើម្បី​ជ្រើសរើស​ផ្លូវកាត់​មួយ ឬ​ប្រើ​សកម្មភាព​ផ្ទាល់ខ្លួន។" + "គ្មាន​បន្ទប់​នៅ​លើ​អេក្រង់​ដើម​នេះ​ទៀត​ទេ។" + "គ្មាន​បន្ទប់​​ក្នុង​ថាស​និយម​ប្រើ" + "បញ្ជីកម្មវិធី" + "បញ្ជី​កម្មវិធី​ផ្ទាល់ខ្លួន" + "បញ្ជី​កម្មវិធី​ការងារ" + "ដើម" + "យកចេញ" + "លុបការដំឡើង" + "ព័ត៌មាន​កម្មវិធី" + "ដំឡើង" + "ដំឡើង​ផ្លូវកាត់" + "អនុញ្ញាត​ឲ្យ​កម្មវិធី​បន្ថែម​ផ្លូវកាត់​ ដោយ​មិន​ចាំបាច់​​អំពើ​ពី​អ្នក​ប្រើ។" + "អាន​ការ​កំណត់​ និង​ផ្លូវកាត់​​អេក្រង់​ដើម" + "អនុញ្ញាត​ឲ្យ​កម្មវិធី​អាន​ការ​កំណត់ និង​ផ្លូវកាត់​ក្នុង​អេក្រង់​ដើម។" + "សរសេរ​ការ​កំណត់ ​និង​ផ្លូវកាត់​​លើ​អេក្រង់​ដើម" + "អនុញ្ញាត​ឲ្យ​កម្មវិធី​ប្ដូរ​ការ​កំណត់ និង​ផ្លូវ​កាត់​ក្នុង​អេក្រង់​ដើម។" + "%1$s មិនត្រូវបានអនុញ្ញាតឲ្យធ្វើការហៅទូរស័ព្ទទេ" + "បញ្ហា​ក្នុង​ការ​ផ្ទុក​ធាតុ​​ក្រាហ្វិក" + "រៀបចំ" + "នេះ​​​ជា​កម្មវិធី​ប្រព័ន្ធ មិន​អាច​លុប​បាន​ទេ។" + "ថត​គ្មាន​ឈ្មោះ" + "បានបិទដំណើរការ %1$s" + + %1$s មាន​ការ​ជូន​ដំណឹង %2$d + %1$s មាន​ការ​ជូន​ដំណឹង %2$d + + "ទំព័រ %1$d នៃ %2$d" + "អេក្រង់​ដើម %1$d នៃ %2$d" + "ទំព័រអេក្រង់ដើមថ្មី" + "បាន​បើក​ថត %1$d ដោយ %2$d" + "ប៉ះ ដើម្បីបិទថត" + "ប៉ះដើម្បីរក្សាទុកឈ្មោះដែលបានប្តូរ" + "បាន​បិទ​ថត" + "បាន​ប្ដូរ​ឈ្មោះ​ថត​ជា %1$s" + "ថត៖ %1$s" + "ធាតុ​ក្រាហ្វិក" + "ផ្ទាំង​រូបភាព" + "ការកំណត់​ទំព័រដើម" + "បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក" + "អនុញ្ញាតការបងិ្វលអេក្រង់ដើម" + "នៅពេលដែលបង្វិលទូរស័ព្ទរបស់អ្នក" + "ស្លាកជូនដំណឹង" + "បើក" + "បិទ" + "តម្រូវ​ឲ្យមាន​សិទ្ធិចូល​ប្រើប្រាស់​ការជូនដំណឹង" + "ដើម្បីបង្ហាញស្លាកជូនដំណឹង សូមបើកការជូនដំណឹងកម្មវិធីសម្រាប់ %1$s" + "ប្ដូរ​ការកំណត់" + "បង្ហាញ​ស្លាក​ជូនដំណឹង" + "បញ្ចូល​រូបតំណាង​ទៅ​អេក្រង់​ដើម" + "សម្រាប់កម្មវិធីថ្មី" + "ប្តូររូបរាងរូបតំណាង" + "នៅ​លើ​អេក្រង់​ដើម" + "ប្រើលំនាំដើមរបស់ប្រព័ន្ធ" + "ការ៉េ" + "ការ៉េជ្រុងកោង" + "រង្វង់" + "តំណក់​ទឹកភ្នែក" + "កំពុងអនុវត្ត​ការប្តូររូបរាងរូបតំណាង" + "មិន​ស្គាល់" + "លុបចេញ" + "ស្វែងរក" + "មិន​បាន​ដំឡើង​កម្មវិធី​នេះ" + "មិន​បាន​ដំឡើង​កម្មវិធី​សម្រាប់​រូបតំណាង​នេះ។ អ្នក​អាច​លុប​វា ឬ​ស្វែងរក​កម្មវិធី និង​ដំឡើង​វា​ដោយ​ដៃ។" + "កំពុងដោនឡូត %1$s បានបញ្ចប់ %2$s" + "%1$s កំពុងរង់ចាំការដំឡើង" + "ធាតុ​ក្រាហ្វិក %1$s" + "បន្ថែមទៅអេក្រង់ដើម" + "ផ្លាស់ធាតុមកទីនេះ" + "ធាតុដែលត្រូវបានបន្ថែមទៅអេក្រង់ដើម" + "ធាតុដែលបានដកចេញ" + "ផ្លាស់ទីធាតុ" + "ផ្លាស់ទីទៅជួរដេកទី %1$s ជួរឈរទី %2$s" + "ផ្លាស់ទីទៅទីតាំង %1$s" + "ផ្លាស់ទីទៅការចូលចិត្តទីតាំងទី %1$s" + "បានផ្លាស់ទីធាតុ" + "បន្ថែមទៅថតឯកសារ៖ %1$s" + "បន្ថែមទៅថតឯកសារដែលមានឈ្មោះ %1$s" + "បានបន្ថែមធាតុទៅថតឯកសារ" + "បង្កើតថតឯកសារជាមួយ៖ %1$s" + "បានបង្កើតថតឯកសារ" + "ផ្លាស់ទៅអេក្រង់ដើម" + "ប្ដូរទំហំ" + "បង្កើនទទឹង" + "បង្កើនកម្ពស់" + "បន្ថយទទឹង" + "បន្ថយកម្ពស់" + "ធាតុក្រាហ្វិកដែលបានប្តូរទំហំទៅទទឹងប្រវែង %1$s កម្ពស់ប្រវែង %2$s" + "ផ្លូវកាត់" + "%1$d ផ្លូវកាត់សម្រាប់ %2$s" + "ផ្លូវកាត់ចំនួន %1$d និង​ការជូនដំណឹងចំនួន %2$d សម្រាប់ %3$s" + "បដិសេធ" + "បាន​បដិសេធ​ការជូនដំណឹង" + "ផ្ទាល់ខ្លួន" + "ការងារ" + "កម្រងព័ត៌មានការងារ" + "ស្វែង​រក​កម្មវិធី​ការងារ​នៅទីនេះ" + "កម្មវិធី​ការងារ​នីមួយៗ​មាន​ស្លាកមួយ និងត្រូវ​បានរក្សាទុក​យ៉ាងមានសុវត្ថិភាព​ដោយស្ថាប័ន​របស់អ្នក។ សូម​ផ្លាស់ទី​កម្មវិធី​ទៅកាន់​អេក្រង់​ដើម​របស់អ្នក​ ដើម្បី​ងាយស្រួល​ចូលប្រើជាងមុន។" + "គ្រប់គ្រងដោយ​ស្ថាប័ន​របស់អ្នក" + "ការជូនដំណឹង​ និងកម្មវិធី​ត្រូវបានបិទ" + "បិទ" + "បានបិទ" + diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index 6b56372160..e3659c99ff 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -81,6 +81,8 @@ "ផ្ទាំង​រូបភាព" "ការកំណត់​ទំព័រដើម" "បានបិទដំណើរការដោយអ្នកគ្រប់គ្រងរបស់អ្នក" + "អនុញ្ញាតការបងិ្វលអេក្រង់ដើម" + "នៅពេលដែលបង្វិលទូរស័ព្ទរបស់អ្នក" "ស្លាកជូនដំណឹង" "បើក" "បិទ" @@ -128,8 +130,8 @@ "បន្ថយកម្ពស់" "ធាតុក្រាហ្វិកដែលបានប្តូរទំហំទៅទទឹងប្រវែង %1$s កម្ពស់ប្រវែង %2$s" "ផ្លូវកាត់" - "%1$d ផ្លូវកាត់សម្រាប់ %2$s" - "ផ្លូវកាត់ចំនួន %1$d និង​ការជូនដំណឹងចំនួន %2$d សម្រាប់ %3$s" + + "បដិសេធ" "បាន​បដិសេធ​ការជូនដំណឹង" "ផ្ទាល់ខ្លួន" diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml new file mode 100644 index 0000000000..56ebe0a9bb --- /dev/null +++ b/res/values-kn-rIN/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "ಕೆಲಸ" + "ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಸ್ಥಾಪಿಸಲಾಗಿಲ್ಲ" + "ಅಪ್ಲಿಕೇಶನ್ ಲಭ್ಯವಿಲ್ಲ" + "ಡೌನ್‌ಲೋಡ್ ಮಾಡಲಾದ ಅಪ್ಲಿಕೇಶನ್ ಅನ್ನು ಸುರಕ್ಷಿತ ಮೋಡ್‌ನಲ್ಲಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" + "ಸುರಕ್ಷಿತ ಮೋಡ್‌ನಲ್ಲಿ ವಿಜೆಟ್‌ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" + "ಶಾರ್ಟ್‌ಕಟ್ ಲಭ್ಯವಿಲ್ಲ" + "ಮುಖಪುಟದ ಪರದೆ" + "ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳು" + "ವಿಜೆಟ್ ಅನ್ನು ಆರಿಸಿಕೊಳ್ಳಲು ಸ್ಪರ್ಶಿಸಿ & ಹಿಡಿದುಕೊಳ್ಳಿ." + "ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ವಿಜೆಟ್ ಆರಿಸಿಕೊಳ್ಳಲು ಹೋಲ್ಡ್ ಮಾಡಿ ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಿ" + "%1$d × %2$d" + "%1$d ಅಗಲ ಮತ್ತು %2$d ಎತ್ತರ" + "ಹಸ್ತಚಾಲಿತವಾಗಿ ಸೇರಿಸಲು ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹೋಲ್ಡ್ ಮಾಡಿ" + "ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸೇರಿಸಿ" + "ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಹುಡುಕಿ" + "ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಲೋಡ್ ಮಾಡಲಾಗುತ್ತಿದೆ..." + "\"%1$s\" ಹೊಂದಿಕೆಯ ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಕಂಡುಬಂದಿಲ್ಲ" + "ಮತ್ತಷ್ಟು ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಹುಡುಕಿ" + "ಅಧಿಸೂಚನೆಗಳು" + "ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್ ಆರಿಸಲು ಹೋಲ್ಡ್ ಮಾಡಿ." + "ಡಬಲ್ ಟ್ಯಾಪ್ ಮಾಡಿ ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್ ಆರಿಸಿಕೊಳ್ಳಲು ಹೋಲ್ಡ್ ಮಾಡಿ ಅಥವಾ ಕಸ್ಟಮ್ ಕ್ರಿಯೆಗಳನ್ನು ಬಳಸಿ." + "ಈ ಮುಖಪುಟದ ಪರದೆಯಲ್ಲಿ ಹೆಚ್ಚು ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ." + "ಮೆಚ್ಚಿನವುಗಳ ಟ್ರೇನಲ್ಲಿ ಹೆಚ್ಚಿನ ಸ್ಥಳಾವಕಾಶವಿಲ್ಲ" + "ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಪಟ್ಟಿ" + "ವೈಯಕ್ತಿಕ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಪಟ್ಟಿ" + "ಕೆಲಸದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಪಟ್ಟಿ" + "ಮುಖಪುಟ" + "ತೆಗೆದುಹಾಕಿ" + "ಅನ್‌ಇನ್‌ಸ್ಟಾಲ್" + "ಅಪ್ಲಿಕೇಶನ್ ಮಾಹಿತಿ" + "ಸ್ಥಾಪಿಸಿ" + "ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಿ" + "ಬಳಕೆದಾರರ ಹಸ್ತಕ್ಷೇಪವಿಲ್ಲದೆ ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ." + "ಮುಖಪುಟದ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಓದಿ" + "ಮುಖಪುಟದಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಓದಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ." + "ಮುಖಪುಟದ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಬರೆಯಿರಿ" + "ಮುಖಪುಟದಲ್ಲಿ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಮತ್ತು ಶಾರ್ಟ್‌ಕಟ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡುತ್ತದೆ." + "ಫೋನ್ ಕರೆಗಳನ್ನು ಮಾಡಲು %1$s ಅಪ್ಲಿಕೇಶನ್‌‌ಗೆ ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ" + "ವಿಜೆಟ್ ಲೋಡ್‌ ಮಾಡುವಲ್ಲಿ ಸಮಸ್ಯೆ" + "ಸೆಟಪ್" + "ಇದೊಂದು ಅಪ್ಲಿಕೇಶನ್ ಆಗಿದೆ ಮತ್ತು ಅಸ್ಥಾಪಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ." + "ಹೆಸರಿಲ್ಲದ ಫೋಲ್ಡರ್" + "%1$s ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ" + + %1$s, %2$d ಅಧಿಸೂಚನೆಗಳನ್ನು ಹೊಂದಿದೆ + %1$s, %2$d ಅಧಿಸೂಚನೆಗಳನ್ನು ಹೊಂದಿದೆ + + "%2$d ರಲ್ಲಿ %1$d ಪುಟ" + "%2$d ರಲ್ಲಿ %1$d ಮುಖಪುಟದ ಪರದೆ" + "ಹೊಸ ಮುಖಪುಟ ಪರದೆ" + "ಫೋಲ್ಡರ್ ತೆರೆಯಲಾಗಿದೆ, %1$d ಬೈ %2$d" + "ಫೋಲ್ಡರ್‌ ಮುಚ್ಚಲು ಟ್ಯಾಪ್ ಮಾಡಿ" + "ಮರುಹೆಸರನ್ನು ಉಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ" + "ಫೋಲ್ಡರ್ ಮುಚ್ಚಿದೆ" + "ಫೋಲ್ಡರ್‌ ಅನ್ನು %1$s ಗೆ ಮರುಹೆಸರಿಸಲಾಗಿದೆ" + "ಫೋಲ್ಡರ್: %1$s" + "ವಿಜೆಟ್‌ಗಳು" + "ವಾಲ್‌ಪೇಪರ್‌ಗಳು" + "ಮುಖಪುಟ ಸೆಟ್ಟಿಂಗ್‌ಗಳು" + "ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ" + "ಮುಖಪುಟ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ" + "ಫೋನ್‌ ತಿರುಗಿಸಿದಾಗ" + "ಅಧಿಸೂಚನೆ ಡಾಟ್‌ಗಳು" + "ಆನ್" + "ಆಫ್" + "ಅಧಿಸೂಚನೆ ಪ್ರವೇಶ ಅಗತ್ಯವಿದೆ" + "ಅಧಿಸೂಚನೆ ಚುಕ್ಕೆಗಳನ್ನು ತೋರಿಸಲು, %1$s ಗೆ ಅಪ್ಲಿಕೇಶನ್‌ ಅಧಿಸೂಚನೆಗಳನ್ನು ಆನ್‌ ಮಾಡಿ" + "ಸೆಟ್ಟಿಂಗ್‌‌ಗಳನ್ನು ಬದಲಾಯಿಸಿ" + "ಅಧಿಸೂಚನೆ ಡಾಟ್‌ಗಳನ್ನು ತೋರಿಸಿ" + "ಮುಖಪುಟದ ಪರದೆಗೆ ಐಕಾನ್ ಸೇರಿಸಿ" + "ಹೊಸ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗೆ" + "ಐಕಾನ್ ಆಕಾರವನ್ನು ಬದಲಿಸಿ" + "ಮುಖಪುಟ ಪರದೆಯಲ್ಲಿ" + "ಸಿಸ್ಟಂ ಡಿಫಾಲ್ಟ್ ಬಳಸಿ" + "ಚೌಕ" + "ಚೌಕವೃತ್ತ" + "ವೃತ್ತ" + "ಕಂಬನಿ" + "ಐಕಾನ್ ಆಕಾರ ಬದಲಾವಣೆಯನ್ನು ಅನ್ವಯಿಸಲಾಗುತ್ತಿದೆ" + "ಅಪರಿಚಿತ" + "ತೆಗೆದುಹಾಕಿ" + "ಹುಡುಕಿ" + "ಈ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪನೆಗೊಂಡಿಲ್ಲ" + "ಈ ಐಕಾನ್ ಅಪ್ಲಿಕೇಶನ್ ಸ್ಥಾಪನೆಗೊಂಡಿಲ್ಲ. ನೀವು ಅದನ್ನು ತೆಗೆದುಹಾಕಬಹುದು ಅಥವಾ ಅಪ್ಲಿಕೇಶನ್ ಹುಡುಕಬಹುದು ಮತ್ತು ಹಸ್ತಚಾಲಿತವಾಗಿ ಅದನ್ನು ಸ್ಥಾಪಿಸಬಹುದು." + "%1$s ಡೌನ್‌ಲೋಡ್‌ ಮಾಡಲಾಗುತ್ತಿದೆ, %2$s ಪೂರ್ಣಗೊಂಡಿದೆ" + "%1$s ಸ್ಥಾಪಿಸಲು ಕಾಯಲಾಗುತ್ತಿದೆ" + "%1$s ವಿಜೆಟ್‌ಗಳು" + "ಮುಖಪುಟಕ್ಕೆ ಸೇರಿಸು" + "ಐಟಂ ಇಲ್ಲಿಗೆ ಸರಿಸಿ" + "ಮುಖಪುಟ ಪರದೆಗೆ ಐಟಂ ಸೇರಿಸಲಾಗಿದೆ" + "ಐಟಂ ತೆಗೆದುಹಾಕಲಾಗಿದೆ" + "ಐಟಂ ಸರಿಸಿ" + "%1$s ಸಾಲು %2$s ಕಾಲಮ್‌ಗೆ ಸರಿಸಿ" + "%1$s ಸ್ಥಾನಕ್ಕೆ ಸರಿಸಿ" + "ಮೆಚ್ಚಿನ %1$s ಸ್ಥಾನಕ್ಕೆ ಸರಿಸಿ" + "ಐಟಂ ಸರಿಸಲಾಗಿದೆ" + "ಫೋಲ್ಡರ್‌ಗೆ ಸೇರಿಸಿ: %1$s" + "%1$s ಮೂಲಕ ಫೋಲ್ಡರ್‌ಗೆ ಸೇರಿಸಿ" + "ಐಟಂ ಅನ್ನು ಫೋಲ್ಡರ್‌ಗೆ ಸೇರಿಸಲಾಗಿದೆ" + "ಇದನ್ನು ಬಳಸಿಕೊಂಡು ಫೋಲ್ಡರ್ ರಚಿಸಿ: %1$s" + "ಫೋಲ್ಡರ್ ರಚಿಸಲಾಗಿದೆ" + "ಮುಖಪುಟಕ್ಕೆ ಸರಿಸಿ" + "ಮರುಗಾತ್ರ" + "ಅಗಲವನ್ನು ಹೆಚ್ಚು ಮಾಡಿ" + "ಎತ್ತರವನ್ನು ಹೆಚ್ಚು ಮಾಡಿ" + "ಅಗಲವನ್ನು ಕಡಿಮೆ ಮಾಡಿ" + "ಎತ್ತರವನ್ನು ಕಡಿಮೆ ಮಾಡಿ" + "ವಿಜೆಟ್ ಅನ್ನು %1$s ಅಗಲ %2$s ಎತ್ತರಕ್ಕೆ ಮರುಗಾತ್ರಗೊಳಿಸಲಾಗಿದೆ" + "ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು" + "%2$s ಗೆ %1$d ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು" + "%3$s ಗಾಗಿ %1$d ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು ಮತ್ತು %2$d ಅಧಿಸೂಚನೆಗಳು" + "ವಜಾಗೊಳಿಸಿ" + "ಅಧಿಸೂಚನೆಯನ್ನು ವಜಾಗೊಳಿಸಲಾಗಿದೆ" + "ವೈಯಕ್ತಿಕ" + "ಕೆಲಸ" + "ಕೆಲಸದ ಪ್ರೊಫೈಲ್" + "ಕೆಲಸದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಇಲ್ಲಿ ಹುಡುಕಿ" + "ಕೆಲಸದ ಪ್ರತಿ ಅಪ್ಲಿಕೇಶನ್ ಬ್ಯಾಡ್ಜ್ ಹೊಂದಿದೆ ಮತ್ತು ನಿಮ್ಮ ಸಂಸ್ಥೆಯಿಂದ ಸುರಕ್ಷಿತವಾಗಿ ಇರಿಸಲಾಗುತ್ತದೆ. ಸುಲಭ ಪ್ರವೇಶಕ್ಕಾಗಿ ನಿಮ್ಮ ಹೋಮ್ ಸ್ಕ್ರೀನ್‌ಗೆ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಸರಿಸಿ." + "ನಿಮ್ಮ ಸಂಸ್ಥೆಯ ಮೂಲಕ ನಿರ್ವಹಿಸಲಾಗಿದೆ" + "ಅಧಿಸೂಚನೆಗಳು ಮತ್ತು ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಆಫ್ ಆಗಿವೆ" + "ಮುಚ್ಚಿ" + "ಮುಚ್ಚಲಾಗಿದೆ" + diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index d4813b5760..7a68378d2a 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -81,6 +81,8 @@ "ವಾಲ್‌ಪೇಪರ್‌ಗಳು" "ಮುಖಪುಟ ಸೆಟ್ಟಿಂಗ್‌ಗಳು" "ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿದ್ದಾರೆ" + "ಮುಖಪುಟ ತಿರುಗುವಿಕೆಯನ್ನು ಅನುಮತಿಸಿ" + "ಫೋನ್‌ ತಿರುಗಿಸಿದಾಗ" "ಅಧಿಸೂಚನೆ ಡಾಟ್‌ಗಳು" "ಆನ್" "ಆಫ್" @@ -128,8 +130,8 @@ "ಎತ್ತರವನ್ನು ಕಡಿಮೆ ಮಾಡಿ" "ವಿಜೆಟ್ ಅನ್ನು %1$s ಅಗಲ %2$s ಎತ್ತರಕ್ಕೆ ಮರುಗಾತ್ರಗೊಳಿಸಲಾಗಿದೆ" "ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು" - "%2$s ಗೆ %1$d ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು" - "%3$s ಗಾಗಿ %1$d ಶಾರ್ಟ್‌ಕಟ್‌ಗಳು ಮತ್ತು %2$d ಅಧಿಸೂಚನೆಗಳು" + + "ವಜಾಗೊಳಿಸಿ" "ಅಧಿಸೂಚನೆಯನ್ನು ವಜಾಗೊಳಿಸಲಾಗಿದೆ" "ವೈಯಕ್ತಿಕ" diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index 9275abfe1f..4a6f3faa10 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -81,6 +81,8 @@ "배경화면" "홈 설정" "관리자가 사용 중지함" + "홈 화면 회전 허용" + "휴대전화 회전 시" "알림 표시 점" "사용" "사용 안함" @@ -128,8 +130,8 @@ "높이 줄이기" "폭 %1$s, 높이 %2$s로 위젯 크기 조정됨" "바로가기" - "%2$s에 사용 가능한 단축키 %1$d개" - "바로가기 %1$d개 및 %3$s 알림 %2$d개" + + "닫기" "알림이 해제되었습니다." "개인" diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml new file mode 100644 index 0000000000..502a08a3e1 --- /dev/null +++ b/res/values-ky-rKG/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "Жумуш" + "Колдонмо орнотулган эмес." + "Колдонмо жеткиликтүү эмес" + "Жүктөп алынган колдонмо Коопсуз режиминде иштен чыгарылды" + "Виджеттер Коопсуз режимде өчүрүлгөн" + "Кыска жол жок" + "Башкы экран" + "Ыңгайлаштырылган аракеттер" + "Виджетти тандаш үчүн, басып туруңуз" + "Виджет тандоо үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз." + "%1$d × %2$d" + "Туурасы: %1$d, бийиктиги: %2$d" + "Кол менен жайгаштыруу үчүн басып туруп, таштаңыз" + "Автоматтык түрдө кошуу" + "Колдонмолорду издөө" + "Колдонмолор жүктөлүүдө…" + "\"%1$s\" сурамына дал келген колдонмолор табылган жок" + "Көбүрөөк колдонмолорду издөө" + "Билдирмелер" + "Кыска жолду тандоо үчүн басып туруңуз." + "Кыска жолду тандоо үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз." + "Бул Үй экранында бош орун жок." + "Тандамалдар тайпасында орун калган жок" + "Колдонмолор тизмеси" + "Жеке колдономолордун тизмеси" + "Жумуш колдонмолорунун тизмеси" + "Үйгө" + "Алып салуу" + "Чыгарып салуу" + "Колдонмо тууралуу" + "Орнотуу" + "тез чакырмаларды орнотуу" + "Колдонмого колдонуучуга кайрылбастан тез чакырма кошууга уруксат берет." + "Үйдүн тууралоолорун жана тез чакырмаларын окуу" + "Колдонмого Үйдүн тууралоолорун жана тез чакырмаларын окууга уруксат берет." + "Үйдүн тууралоолорун жана тез чакырмаларын жазуу" + "Колдонмого Үйдүн тууралоолорун жана тез чакырмаларын өзгөртүүгө уруксат берет." + "%1$s телефон чалууларды аткарууга уруксаты жок" + "Виджетти жүктөөдө маселе бар" + "Орнотуу" + "Бул системдик колдонмо жана аны чечкенге болбойт." + "Аты жок фолдер" + "%1$s өчүрүлгөн" + + %1$s, %2$d эскертме бар + %1$s, %2$d эскертме бар + + "%2$d ичинен %1$d барак" + "Үй экраны %2$d ичинен %1$d" + "Жаңы башкы экран барагы" + "Фолдер ачылды, туурасы %1$d, бийиктиги %2$d" + "Куржунду жабуу үчүн таптаңыз" + "Өзгөртүлгөн аталышын сактоо үчүн таптаңыз" + "Фолдер жабык" + "Фолдердин аты %1$s деп өзгөртүлдү" + "Фолдер: %1$s" + "Виджеттер" + "Тушкагаздар" + "Башкы беттин жөндөөлөрү" + "Администраторуңуз өчүрүп койгон" + "Башкы экранды айлантууга уруксат берүү" + "Телефон айланганда" + "Билдирмелер белгилери" + "Күйүк" + "Өчүк" + "Эскертмелерге уруксат берилиши керек" + "Эскертме белгилерин көрсөтүү максатында, %1$s үчүн колдонмонун эскертмелерин күйгүзүү керек" + "Жөндөөлөрдү өзгөртүү" + "Эскертме белгилерин көрсөтүү" + "Башкы экранга сүрөтчө кошуу" + "Жаңы колдонмолор үчүн" + "Сүрөтчөнүн формасын өзгөртүү" + "Башкы экранда" + "Демейки тутум жөндөөлөрү колдонулат" + "Чарчы" + "Бурчтары жумуру төрт бурчтук" + "Тегерек" + "Тамчы" + "Өзгөртүлгөн сүрөтчөнүн формасы колдонулууда" + "Белгисиз" + "Алып салуу" + "Издөө" + "Бул колдонмо орнотулган эмес" + "Бул сүрөтчөнүн колдонмосу орнотулган эмес. Аны алып салсаңыз же колдонмону издеп, кол менен орнотсоңуз болот." + "%1$s жүктөлүп алынууда, %2$s аяктады" + "%1$s орнотулушу күтүлүүдө" + "%1$s виджеттери" + "Башкы экранга кошуу" + "Бул нерсени бул жерге жылдыруу" + "Башкы экранга кошулду" + "Жоюлду" + "Муну жылдыруу" + "%1$s катарга %2$s тилкеге жылдыруу" + "%1$s орунга жылдыруу" + "Сүйүктүүлөргө %1$s жылдыруу" + "Нерсе жылдырылды" + "Куржунга кошуу: %1$s" + "%1$s куржунуна кошуу" + "Нерсе куржунга кошулду" + "Төмөнкү менен куржун түзүү: %1$s" + "Куржун түзүлдү" + "Башкы экранга жылдыруу" + "Өлчөмүн өзгөртүү" + "Кеңейтүү" + "Бийиктетүү" + "Ичкертүү" + "Жапыздатуу" + "Виджеттин кеңдиги %1$s бийиктиги %2$s болду" + "Кыска жолдор" + "%2$s колдонмосуна %1$d кыска жол бар" + "%3$s колдонмосу үчүн %1$d кыска жол жана %2$d эскертме бар" + "Этибарга албоо" + "Эскертме көз жаздымда калтырылды" + "Жеке колдонмолор" + "Жумуш колдонмолору" + "Жумуш профили" + "Жумуш колдонмолорун бул жерден таап алыңыз" + "Ар бир жумуш колдонмосунун бейджиги бар жана ал уюмуңуз тарабынан коопсуз сакталат. Колдонмолорго тез өтүү үчүн аларды Башкы экранга кошуп алыңыз." + "Уюмуңуз тарабынан башкарылат" + "Билдирүүлөр жана колдонмолор өчүрүлгөн" + "Жабуу" + "Жабык" + diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index e0e740346a..ce0dc3f866 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -39,7 +39,7 @@ "Колдонмолор жүктөлүүдө…" "\"%1$s\" сурамына дал келген колдонмолор табылган жок" "Көбүрөөк колдонмолорду издөө" - "Эскертмелер" + "Билдирмелер" "Кыска жолду тандоо үчүн басып туруңуз." "Кыска жолду тандоо үчүн эки жолу таптап, кармап туруңуз же ыңгайлаштырылган аракеттерди колдонуңуз." "Бул Үй экранында бош орун жок." @@ -81,7 +81,9 @@ "Тушкагаздар" "Башкы беттин жөндөөлөрү" "Администраторуңуз өчүрүп койгон" - "Эскертме белгилери" + "Башкы экранды айлантууга уруксат берүү" + "Телефон айланганда" + "Билдирмелер белгилери" "Күйүк" "Өчүк" "Эскертмелерге уруксат берилиши керек" @@ -92,7 +94,7 @@ "Жаңы колдонмолор үчүн" "Сүрөтчөнүн формасын өзгөртүү" "Башкы экранда" - "Тутум сушунтаган демейкисин колдонуу" + "Демейки тутум жөндөөлөрү колдонулат" "Чарчы" "Бурчтары жумуру төрт бурчтук" "Тегерек" @@ -128,8 +130,8 @@ "Жапыздатуу" "Виджеттин кеңдиги %1$s бийиктиги %2$s болду" "Кыска жолдор" - "%2$s колдонмосуна %1$d кыска жол бар" - "%3$s колдонмосу үчүн %1$d кыска жол жана %2$d эскертме бар" + + "Этибарга албоо" "Эскертме көз жаздымда калтырылды" "Жеке колдонмолор" diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml index 7b5252949a..f0021956a1 100644 --- a/res/values-land/dimens.xml +++ b/res/values-land/dimens.xml @@ -25,7 +25,6 @@ 24dp - 48dp 4dp 0dp diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml new file mode 100644 index 0000000000..cd2c933c15 --- /dev/null +++ b/res/values-lo-rLA/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "ວຽກ" + "ແອັບຯບໍ່ໄດ້ຖືກຕິດຕັ້ງ." + "ແອັບຯ​ໃຊ້​ບໍ່​ໄດ້" + "ແອັບຯ​ທີ່​ດາວ​ໂຫລດ​ແລ້ວ​ຖືກ​ປິດ​ການ​ນຳ​ໃຊ້​ໃນ Safe mode" + "​ວິດ​ເຈັດ​ຖືກ​ປິດ​ໃນ Safe mode" + "ບໍ່ສາມາດໃຊ້ທາງລັດໄດ້" + "ໜ້າຈໍຫຼັກ" + "ຄຳສັ່ງແບບກຳນົດເອງ" + "ສຳພັດຄ້າງໄວ້ ເພື່ອຈັບວິດເຈັດ." + "ແຕະ​ຄ້າງ​ໄວ້ ເພື່ອ​ເລືອກວິດ​ເຈັດ ຫຼື ໃຊ້​ການ​ດຳ​ເນີນ​ການ​ກຳ​ນົດ​ເອງ." + "%1$d × %2$d" + "ກວ້າງ %1$d ຄູນສູງ %2$d" + "ແຕະຄ້າງໄວ້ເພື່ອວາງດ້ວຍຕົນເອງ" + "ເພີ່ມໂດຍອັດຕະໂນມັດ" + "ຊອກຫາແອັບ" + "ກໍາລັງໂຫຼດແອັບ…" + "ບໍ່ພົບແອັບທີ່ກົງກັບ \"%1$s\"" + "ຊອກຫາແອັບເພີ່ມເຕີມ" + "ການແຈ້ງເຕືອນ" + "ແຕະຄ້າງໄວ້ເພື່ອຮັບປຸ່ມລັດ." + "ແຕະສອງເທື່ອຄ້າງໄວ້ເພື່ອຮັບປຸ່ມລັດ ຫຼື ໃຊ້ຄຳສັ່ງແບບກຳນົດເອງ." + "ບໍ່ມີຫ້ອງເຫຼືອໃນໜ້າຈໍຫຼັກນີ້." + "ບໍ່ມີບ່ອນຫວ່າງໃນຖາດສຳລັບເກັບສິ່ງທີ່ໃຊ້ເປັນປະຈຳ" + "ລາຍຊື່ແອັບ" + "ລາຍຊື່ແອັບສ່ວນຕົວ" + "ລາຍຊື່ແອັບເຮັດວຽກ" + "ໜ້າຫຼັກ" + "ເອົາ​ອອກ" + "ຖອນ​ການ​ຕິດ​ຕັ້ງ" + "ຂໍ້ມູນແອັບ" + "ຕິດຕັ້ງ" + "ຕິດຕັ້ງທາງລັດ" + "ອະນຸຍາດໃຫ້ແອັບຯ ເພີ່ມທາງລັດໂດຍບໍ່ຕ້ອງຮັບການຢືນຢັນຈາກຜູ່ໃຊ້." + "ອ່ານການຕັ້ງຄ່າໜ້າຫຼັກ ແລະທາງລັດ" + "ອະນຸຍາດໃຫ້ແອັບຯດັ່ງກ່າວອ່ານການຕັ້ງຄ່າ ແລະທາງລັດໃນໜ້າຫຼັກ." + "ຂຽນການຕັ້ງຄ່າໜ້າຫຼັກ ແລະທາງລັດ" + "ອະນຸຍາດໃຫ້ແອັບຯດັ່ງກ່າວ ປ່ຽນການຕັ້ງຄ່າ ແລະທາງລັດໃນໜ້າຫຼັກ." + "%1$s ບໍ່​ໄດ້​ຮັບ​ອະ​ນຸ​ຍາດ​ໃຫ້​ໂທ" + "ມີບັນຫາໃນການໂຫລດວິດເຈັດ" + "ຕິດຕັ້ງ" + "ນີ້ແມ່ນແອັບຯຂອງລະບົບ ແລະບໍ່ສາມາດຖອນການຕິດຕັ້ງອອກໄດ້." + "ໂຟນເດີຍັງບໍ່ຖືກຕັ້ງຊື່" + "ປິດການນຳໃຊ້ %1$s ແລ້ວ" + + %1$s, ມີ %2$d ການແຈ້ງເຕືອນ + %1$s, ມີ %2$d ການແຈ້ງເຕືອນ + + "ໜ້າ %1$d ຈາກ %2$d" + "ໜ້າຈໍຫຼັກ %1$d ໃນ %2$d" + "ໜ້າ​ຂອງ​ໜ້າ​ຈໍ​ຫຼັກ​ໃໝ່" + "ເປີດໂຟນເດີແລ້ວ, %1$d ຄູນ %2$d" + "ແຕະເພື່ອປິດໂຟນເດີ" + "ແຕະເພື່ອບັນທຶກການປ່ຽນຊື່" + "ປິດໂຟນເດີແລ້ວ" + "ປ່ຽນຊື່ໂຟນເດີເປັນ %1$s ແລ້ວ" + "ໂຟນເດີ: %1$s" + "ວິດເຈັດ" + "ພາບພື້ນຫຼັງ" + "ການຕັ້ງຄ່າ Home" + "ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ" + "ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍທຳອິດໄດ້" + "ເມື່ອໝຸນໂທລະສັບ" + "ຈຸດການແຈ້ງເຕືອນ" + "ເປີດ" + "ປິດ" + "ຕ້ອງໃຊ້ການເຂົ້າເຖິງການແຈ້ງເຕືອນ" + "ເພື່ອສະແດງຈຸດການແຈ້ງເຕືອນ, ໃຫ້ເປີດການແຈ້ງເຕືອນສຳລັບ %1$s" + "ບັນທຶກການຕັ້ງຄ່າ" + "ສະແດງຈຸດການແຈ້ງເຕືອນ" + "ເພີ່ມໄອຄອນໃສ່ໜ້າຈໍຫຼັກ" + "ສຳລັບແອັບໃໝ່" + "ປ່ຽນຮູບຮ່າງໄອຄອນ" + "ຢູ່ໜ້າຈໍຫຼັກ" + "ໃຊ້ຄ່າເລີ່ມຕົ້ນລະບົບ" + "ສີ່ຫຼ່ຽມຈັດຕຸລັດ" + "ສີ່ຫຼ່ຽມຂອບມົນ" + "ວົງມົນ" + "ນ້ຳຢອດ" + "ນຳໃຊ້ການປ່ຽນແປງຮູບຮ່າງໄອຄອນ" + "​ບໍ່​ຮູ້​ຈັກ" + "ລຶບ​" + "ຊອກຫາ" + "ແອັບຯ​ນີ້​ຍັງ​ບໍ່​ໄດ້​ຕິດ​ຕັ້ງ​ເທື່ອ" + "​ແອັບຯ​ສຳ​ລັບ​ໄອ​ຄອນ​ນີ້​ຍັງ​ບໍ່ໄດ້​ຕິດ​ຕັ້ງ​ເທື່ອ. ທ່ານ​ສາ​ມາດ​ລຶບ​ມັນ​ອອກ ຫຼື​ຊອກ​ຫາ​ແອັບຯ ແລ້ວ​ຕິດ​ຕັ້ງ​ມັນ​ໄດ້​ດ້ວຍ​ຕົນ​ເອງ." + "%1$s ກຳ​ລັງ​ດາວ​ໂຫຼດ, %2$s ສຳ​ເລັດ" + "%1$s ກຳ​ລັງ​ລໍ​ຖ້າ​ຕິດ​ຕັ້ງ" + "ວິດເຈັດ %1$s" + "ເພີ່ມໃສ່ໜ້າຈໍຫຼັກ" + "Move item here" + "ເພີ່ມ​ລາຍ​ການ​ໃສ່​ໜ້າ​ຈໍ​ຫຼັກ​ແລ້ວ" + "ເອົາ​ລາຍ​ການ​ອອກ​ໄປ​ແລ້ວ" + "ຍ້າຍ​ລາຍ​ການ" + "ຍ້າຍ​ໄປ​ໃສ່​ແຖວ %1$s ຖັນ %2$s" + "ຍ້າຍ​ໄປ​ໃສ່​ຕຳ​ແໜ່ງ %1$s" + "ຍ້າຍ​ໄປ​ໃສ່​ຕຳ​ແໜ່ງ​ທີ່​ມັກ %1$s" + "ຍ້າຍ​ລາຍ​ການ​ແລ້ວ" + "ເພີ່ມ​ໃສ່​ໂຟ​ລ​ເດີ: %1$s" + "ເພີ່ມ​ໃສ່​ໂຟ​ລ​ເດີ​ດ້ວຍ %1$s" + "ເພີ່ມ​ລາຍ​ການ​ໃສ່​ໂຟ​ລ​ເດີ​ແລ້ວ" + "ສ້າງ​ໂຟ​ລ​ເດີ​ກັບ: %1$s" + "ສ້າງ​ໂຟ​ລ​ເດີ​ແລ້ວ" + "ຍ້າຍ​ໄປ​ໃສ່​ໜ້າ​ຈໍ​ຫຼັກ" + "ປັບຂະໜາດ" + "ເພີ່ມ​ລວງ​ກ້​ວາງ​ຂຶ້ນ" + "ເພີ່ມ​ລວງ​ສູງ​ຂຶ້ນ" + "ຫຼຸດ​ລວງ​ກ້​ວາງ​ລົງ" + "ຫຼຸດ​ລວງ​ສູງ​ລົງ" + "ປ່ຽນ​ຂະ​ໜາດ​ວິດ​ເຈັດ​ເປັນ​ລວງ​ກ້​ວາງ %1$s ລວງ​ສູງ %2$s ແລ້ວ" + "ທາງລັດ" + "%1$d ທາງລັດສຳລັບ %2$s" + "%1$d ທາງລັດ ແລະ %2$d ການແຈ້ງເຕືອນສຳລັບ %3$s" + "ປິດໄວ້" + "ປິດການແຈ້ງເຕືອນແລ້ວ" + "ສ່ວນຕົວ" + "ວຽກ" + "ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ" + "ຊອກຫາແອັບວຽກຢູ່ບ່ອນນີ້" + "ແຕ່ລະແອັບວຽກຈະມີປ້າຍ ແລະ ຖືກຈັດເກັບໄວ້ຢ່າງປອດໄພໂດຍອົງກອນຂອງທ່ານ. ທ່ານສາມາດຍ້າຍແອັບໄປໃສ່ໜ້າຈໍຫຼັກເພື່ອໃຫ້ເຂົ້າໃຊ້ງ່າຍຂຶ້ນໄດ້." + "ຈັດການໂດຍອົງກອນຂອງທ່ານ" + "ການແຈ້ງເຕືອນ ແລະ ແອັບຖືກປິດໄວ້" + "ປິດ" + "ປິດແລ້ວ" + diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index 2b73628978..a195eaf97f 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -81,6 +81,8 @@ "ພາບພື້ນຫຼັງ" "ການຕັ້ງຄ່າ Home" "ຖືກປິດການນຳໃຊ້ໂດຍຜູ້ເບິ່ງແຍງລະບົບຂອງທ່ານ" + "ອະນຸຍາດໃຫ້ໝຸນໜ້າຈໍທຳອິດໄດ້" + "ເມື່ອໝຸນໂທລະສັບ" "ຈຸດການແຈ້ງເຕືອນ" "ເປີດ" "ປິດ" @@ -128,8 +130,8 @@ "ຫຼຸດ​ລວງ​ສູງ​ລົງ" "ປ່ຽນ​ຂະ​ໜາດ​ວິດ​ເຈັດ​ເປັນ​ລວງ​ກ້​ວາງ %1$s ລວງ​ສູງ %2$s ແລ້ວ" "ທາງລັດ" - "%1$d ທາງລັດສຳລັບ %2$s" - "%1$d ທາງລັດ ແລະ %2$d ການແຈ້ງເຕືອນສຳລັບ %3$s" + + "ປິດໄວ້" "ປິດການແຈ້ງເຕືອນແລ້ວ" "ສ່ວນຕົວ" diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index db751dae6a..ac8684c012 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -83,6 +83,8 @@ "Ekrano fonai" "„Home“ nustatymai" "Išjungė administratorius" + "Leisti pasukti pagrindinį ekraną" + "Kai telefonas pasukamas" "Pranešimų taškai" "Įjungta" "Išjungta" @@ -130,8 +132,8 @@ "Sumažinti aukštį" "Valdiklio dydis pakeistas: plotis – %1$s, aukštis – %2$s" "Spartieji klavišai" - "Programos „%2$s“ spartieji klavišai (%1$d)" - "„%3$s“ spartieji klavišai (%1$d) ir pranešimai (%2$d)" + + "Atsisakyti" "Pranešimo atsisakyta" "Asmeninės" diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index a6e16deeef..0ed4093184 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -82,6 +82,8 @@ "Fona tapetes" "Sākumlapas iestatījumi" "Atspējojis administrators" + "Atļaut sākuma ekrāna pagriešanu" + "Pagriežot tālruni" "Paziņojumu punkti" "Ieslēgts" "Izslēgts" @@ -129,8 +131,8 @@ "Samazināt augstumu" "Logrīka lielums mainīts — platums: %1$s, augstums: %2$s." "Saīsnes" - "%1$d saīsnes lietotnei %2$s" - "%1$d saīsnes un %2$d paziņojumi lietotnei %3$s" + + "Nerādīt" "Paziņojums netiek rādīts" "Personīgās lietotnes" diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml new file mode 100644 index 0000000000..54d9c8054a --- /dev/null +++ b/res/values-mk-rMK/strings.xml @@ -0,0 +1,146 @@ + + + + + "Стартер3" + + "Работа" + "Апликацијата не е инсталирана." + "Апликацијата не е достапна" + "Преземената апликација е оневозможена во безбеден режим" + "Додатоците се оневозможени во безбеден режим" + "Кратенката не е достапна" + "Почетен екран" + "Приспособени дејства" + "Допри и задржи за да се избере виџетот." + "Допрете двапати и задржете за да изберете додаток или да користите приспособени дејства." + "%1$d × %2$d" + "%1$d широк на %2$d висок" + "Допрете и задржете за рачно поставување" + "Додај автоматски" + "Пребарувајте апликации" + "Се вчитуваат апликации…" + "Не се најдени апликации што одговараат на „%1$s“" + "Пребарај други апликации" + "Известувања" + "Допрете двапати и задржете за избор на кратенка." + "Допрете двапати и задржете за избор на кратенка или користете приспособени дејства." + "Нема повеќе простор на овој екран на почетната страница." + "Нема повеќе простор на лентата „Омилени“" + "Список со апликации" + "Список со лични апликации" + "Список со апликации за работа" + "Почетна страница" + "Отстрани" + "Деинсталирај" + "Инф. за апликација" + "Инсталирај" + "инсталирај кратенки" + "Овозможува апликацијата да додава кратенки без интервенција на корисникот." + "чита поставки и кратенки на почетна страница" + "Овозможува апликацијата да ги менува подесувањата и кратенките на почетната страница." + "пишува поставки и кратенки на почетна страница" + "Овозможува апликацијата да ги менува подесувањата и кратенките на почетната страница." + "%1$s нема дозвола за телефонски повици" + "Проблем при вчитувањето на виџетот" + "Поставување" + "Ова е системска апликација и не може да се деинсталира." + "Неименувана папка" + "%1$s е оневозможена" + + %1$s има %2$d известување + %1$s има %2$d известувања + + "Страница %1$d од %2$d" + "Екран на почетна страница %1$d од %2$d" + "Нова страница на почетен екран" + "Отворена е папка, %1$d на %2$d" + "Допрете за да ја затворите папката" + "Допрете за да го зачувате преименувањето" + "Папката е затворена" + "Папката е преименувана во %1$s" + "Папка: %1$s" + "Виџети" + "Тапети" + "Поставки за Home" + "Оневозможено од администраторот" + "Дозволете ротација на Почетниот екран" + "Кога телефонот се ротира" + "Точки за известување" + "Вклучено" + "Исклучено" + "Потребен е пристап до известувањата" + "За да се прикажуваат „Точки за известување“, вклучете ги известувањата за апликацијата %1$s" + "Промени ги поставките" + "Прикажи точки за известување" + "Додај икона на почетниот екран" + "За нови апликации" + "Променете ја формата на иконата" + "на „Почетен екран“" + "Користи ја стандардната поставка на системот" + "Квадрат" + "Заоблен квадрат" + "Круг" + "Солза" + "Се применуваат промените на формата на иконата" + "Непознато" + "Отстрани" + "Барај" + "Апликацијата не е инсталирана" + "Апликацијата за оваа икона не е инсталирана. Може да ја отстраните или да се обидете да ја најдете апликацијата и да ја инсталирате рачно." + "Се презема %1$s, %2$s завршено" + "%1$s чека да се инсталира" + "Виџети за %1$s" + "Додај на Почетен екран" + "Премести ја ставката овде" + "Ставката е додадена на почетниот екран" + "Ставката е отстранета" + "Премести ја ставката" + "Премести во ред %1$s колона %2$s" + "Премести на место %1$s" + "Премести на место %1$s во омилени" + "Ставката е преместена" + "Додај во папката: %1$s" + "Додај во папка со %1$s" + "Ставката е додадена во папката" + "Создај папка со: %1$s" + "Папката е создадена" + "Премести на Почетен екран" + "Промени големина" + "Зголеми ширина" + "Зголеми висина" + "Намали ширина" + "Намали висина" + "Големината на виџетот е променета на ширина %1$s висина %2$s" + "Кратенки" + "%1$d кратенки за %2$s" + "%1$d кратенки и %2$d известувања за %3$s" + "Отфрли" + "Известувањето е отфрлено" + "Лично" + "За работа" + "Работен профил" + "Најдете апликации за работа тука" + "Секоја апликација за работа има значка, а организацијата се грижи за нејзината безбедност. За полесен пристап, преместете ги апликациите на почетниот екран." + "Управувано од вашата организација" + "Известувањата и апликациите се исклучени" + "Затвори" + "Затворено" + diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index 29e837b27c..3a033153e4 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -81,6 +81,8 @@ "Тапети" "Поставки за Home" "Оневозможено од администраторот" + "Дозволете ротација на Почетниот екран" + "Кога телефонот се ротира" "Точки за известување" "Вклучено" "Исклучено" @@ -128,8 +130,8 @@ "Намали висина" "Големината на виџетот е променета на ширина %1$s висина %2$s" "Кратенки" - "%1$d кратенки за %2$s" - "%1$d кратенки и %2$d известувања за %3$s" + + "Отфрли" "Известувањето е отфрлено" "Лично" diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml new file mode 100644 index 0000000000..a0609333c9 --- /dev/null +++ b/res/values-ml-rIN/strings.xml @@ -0,0 +1,146 @@ + + + + + "ലോഞ്ചർ3" + + "ഔദ്യോഗികം" + "അപ്ലിക്കേഷൻ ഇൻസ്‌റ്റാളുചെ‌യ്‌തിട്ടില്ല." + "അപ്ലിക്കേഷൻ ലഭ്യമല്ല" + "ഡൗൺലോഡുചെയ്‌ത അപ്ലിക്കേഷൻ സുരക്ഷാ മോഡിൽ പ്രവർത്തനരഹിതമാക്കി" + "സുരക്ഷിത മോഡിൽ വിജറ്റുകൾ പ്രവർത്തനരഹിതമാക്കി" + "കുറുക്കുവഴി ലഭ്യമല്ല" + "ഹോം സ്‌ക്രീൻ" + "ഇഷ്‌ടാനുസൃത പ്രവർത്തനങ്ങൾ" + "ഒരു വിജറ്റ് ചേർക്കുന്നതിന് അത് സ്‌പർശിച്ച് പിടിക്കുക." + "വിജറ്റ് തിരഞ്ഞെടുക്കാനോ ഇഷ്ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കാനോ രണ്ടുതവണ ടാപ്പുചെയ്ത് പിടിക്കുക." + "%1$d × %2$d" + "%1$d വീതിയും %2$d ഉയരവും" + "സ്വമേധയാ സ്ഥാപിക്കുന്നതിന് സ്‌പർശിച്ചുപിടിക്കുക" + "സ്വയമേവ ചേർക്കുക" + "ആപ്പുകൾ തിരയുക" + "ആപ്പുകൾ ലോഡുചെയ്യുന്നു..." + "\"%1$s\" എന്നതുമായി പൊരുത്തപ്പെടുന്ന ആപ്പുകളൊന്നും കണ്ടെത്തിയില്ല" + "കൂടുതൽ ആപ്പുകൾക്ക് തിരയുക" + "അറിയിപ്പുകൾ" + "തിരഞ്ഞെടുക്കുന്നതിന് കുറുക്കുവഴി സ്‌പർശിച്ച് പിടിക്കുക." + "കുറുക്കുവഴി തിരഞ്ഞെടുക്കാനോ ഇഷ്‌ടാനുസൃത പ്രവർത്തനങ്ങൾ ഉപയോഗിക്കാനോ 2 തവണ ടാപ്പ് ചെയ്‌ത് പിടിക്കുക." + "ഈ ഹോം സ്‌ക്രീനിൽ ഒഴിവൊന്നുമില്ല." + "പ്രിയപ്പെട്ടവയുടെ ട്രേയിൽ ഒഴിവൊന്നുമില്ല" + "അപ്ലിക്കേഷനുകളുടെ ലിസ്‌റ്റ്" + "വ്യക്തിഗത ആപ്പുകളുടെ ലിസ്റ്റ്" + "ഔദ്യോഗിക ആപ്പുകളുടെ ലിസ്റ്റ്" + "ഹോം" + "നീക്കംചെയ്യുക" + "അൺഇൻസ്റ്റാളുചെയ്യുക" + "ആപ്പ് വിവരം" + "ഇൻസ്‌റ്റാൾ ചെയ്യുക" + "കുറുക്കുവഴികൾ ഇൻസ്റ്റാളുചെയ്യുക" + "ഉപയോക്തൃ ഇടപെടൽ ഇല്ലാതെ കുറുക്കുവഴികൾ ചേർക്കാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." + "ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യുക" + "ഹോമിലെ ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റീഡുചെയ്യാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." + "ഹോം ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും റൈറ്റുചെയ്യുക" + "ഹോമിലെ ക്രമീകരണങ്ങളും കുറുക്കുവഴികളും മാറ്റാൻ അപ്ലിക്കേഷനെ അനുവദിക്കുന്നു." + "ഫോൺ കോൾ ചെയ്യാൻ %1$s എന്നതിനെ അനുവദിച്ചിട്ടില്ല" + "വിജറ്റ് ലോഡുചെയ്യുന്നതിൽ പ്രശ്നമുണ്ട്" + "സജ്ജീകരിക്കുക" + "ഇതൊരു സിസ്‌റ്റം അപ്ലിക്കേഷനായതിനാൽ അൺഇൻസ്‌റ്റാളുചെയ്യാനാവില്ല." + "പേരുനൽകാത്ത ഫോൾഡർ" + "%1$s പ്രവർത്തനരഹിതമാക്കി" + + %1$s-ന്, %2$d അറിയിപ്പുകൾ ഉണ്ട് + %1$s-ന്, %2$d അറിയിപ്പ് ഉണ്ട് + + "പേജ് %1$d / %2$d" + "ഹോം സ്‌ക്രീൻ %1$d / %2$d" + "പുതിയ ഹോം സ്ക്രീൻ പേജ്" + "ഫോൾഡർ തുറന്നു, %1$d / %2$d" + "ഫോൾഡർ അടയ്ക്കുന്നതിന് ടാപ്പുചെയ്യുക" + "പേരുമാറ്റം സംരക്ഷിക്കുന്നതിന് ടാപ്പുചെയ്യുക" + "ഫോൾഡർ അടച്ചു" + "ഫോൾഡറിന്റെ പേര് %1$s എന്നായി മാറ്റി" + "ഫോൾഡർ: %1$s" + "വിജറ്റുകൾ" + "വാൾപേപ്പർ" + "ഹോം ക്രമീകരണം" + "അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു" + "ഹോം സ്ക്രീൻ തിരിക്കൽ അനുവദിക്കുക" + "ഫോൺ തിരിച്ച നിലയിലായിരിക്കുമ്പോൾ" + "അറിയിപ്പ് ഡോട്ടുകൾ" + "ഓൺ" + "ഓഫ്" + "അറിയിപ്പിനായുള്ള ആക്‌സസ് ആവശ്യമാണ്" + "അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുന്നതിന്, %1$s എന്നയാളിനായുള്ള ആപ്പ് അറിയിപ്പുകൾ ഓണാക്കുക" + "ക്രമീകരണം മാറ്റുക" + "അറിയിപ്പ് ഡോട്ടുകൾ കാണിക്കുക" + "ഹോം സ്ക്രീനിലേക്ക് ഐക്കൺ ചേർക്കുക" + "പുതിയ ആപ്പുകൾക്ക്" + "ഐക്കണിന്റെ ആകാരം മാറ്റുക" + "ഹോം സ്‌ക്രീനിൽ" + "സിസ്‌റ്റം ഡിഫോൾട്ട് ഉപയോഗിക്കുക" + "ചതുരം" + "ചതുരവൃത്തം" + "വൃത്തം" + "കണ്ണുനീര്‍ തുള്ളി" + "ഐക്കൺ ആകാര മാറ്റങ്ങൾ പ്രയോഗിക്കുന്നു" + "അജ്ഞാതം" + "നീക്കംചെയ്യുക" + "തിരയുക" + "ഈ അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്‌തിട്ടില്ല" + "ഈ ഐക്കണുവേണ്ടി അപ്ലിക്കേഷൻ ഇൻസ്റ്റാളുചെയ്‌തിട്ടില്ല. നിങ്ങൾക്കത് നീക്കംചെയ്യാനാകും അല്ലെങ്കിൽ അപ്ലിക്കേഷനുവേണ്ടി തിരഞ്ഞുകൊണ്ട് അത് സ്വമേധയാ ഇൻസ്റ്റാളുചെയ്യുക." + "%1$s ഡൗൺലോഡ് ചെയ്യുന്നു, %2$s പൂർത്തിയായി" + "ഇൻസ്റ്റാൾ ചെയ്യാൻ %1$s കാക്കുന്നു" + "%1$s വിജറ്റുകൾ" + "ഹോം സ്ക്രീനിൽ ചേർക്കുക" + "ഇനം ഇവിടേക്ക് നീക്കുക" + "ഹോം സ്‌ക്രീനിൽ ഇനം ചേർത്തു" + "ഇനം നീക്കംചെയ്‌തു" + "ഇനം നീക്കുക" + "വരി %1$s നിര %2$s-ലേക്ക് നീക്കുക" + "%1$s-ലേക്ക് നീക്കുക" + "ഇഷ്‌ടമുള്ള %1$s സ്ഥാനത്തേക്ക് നീക്കുക" + "ഇനം നീക്കി" + "ഫോൾഡറിൽ ചേർക്കുക: %1$s" + "%1$s ഉള്ള ഫോൾഡറിൽ ചേർക്കുക" + "ഫോൾഡറിൽ ഇനം ചേർത്തു" + "ഇതുപയോഗിച്ച് ഫോൾഡർ സൃഷ്‌ടിക്കുക: %1$s" + "ഫോൾഡർ സൃഷ്‌ടിച്ചു" + "ഹോം സ്‌ക്രീനിലേക്ക് നീക്കുക" + "വലുപ്പംമാറ്റുക" + "വീതി കൂട്ടുക" + "ഉയരം കൂട്ടുക" + "വീതി കുറയ്‌ക്കുക" + "ഉയരം കുറയ്‌ക്കുക" + "വീതി %1$s ഉയരം %2$s-ലേക്ക് വിഡ്‌ജെറ്റിന്റെ വലുപ്പം മാറ്റി" + "കുറുക്കുവഴികൾ" + "%2$s ആപ്പിനുള്ള %1$d കുറുക്കുവഴികൾ" + "%3$s ആപ്പിനായുള്ള %1$d കുറുക്കുവഴികളും %2$d അറിയിപ്പുകളും" + "നിരസിക്കുക" + "അറിയിപ്പ് നിരസിച്ചു" + "വ്യക്തിപരം" + "ജോലി" + "ഔദ്യോഗിക പ്രൊഫൈൽ" + "ഔദ്യോഗിക ആപ്പുകൾ ഇവിടെ കണ്ടെത്തുക" + "എല്ലാ ഔദ്യോഗിക ആപ്പിനും ഒരു ബാഡ്‌ജ് ഉണ്ട്, നിങ്ങളുടെ സ്ഥാപനം അത് സുരക്ഷിതമായി സൂക്ഷിക്കുന്നു. എളുപ്പത്തിൽ ആക്സസ് ചെയ്യാൻ ആപ്പുകളെ ഹോം സ്‌ക്രീനിലേക്ക് നീക്കുക." + "നിങ്ങളുടെ സ്ഥാപനം നിയന്ത്രിക്കുന്നത്" + "അറിയിപ്പുകളും ആപ്പുകളും ഓഫാണ്" + "അടയ്ക്കുക" + "അടച്ചു" + diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index 5ccac13e4a..7ad2803df9 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -81,6 +81,8 @@ "വാൾപേപ്പർ" "ഹോം ക്രമീകരണം" "അഡ്മിൻ പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു" + "ഹോം സ്ക്രീൻ തിരിക്കൽ അനുവദിക്കുക" + "ഫോൺ തിരിച്ച നിലയിലായിരിക്കുമ്പോൾ" "അറിയിപ്പ് ഡോട്ടുകൾ" "ഓൺ" "ഓഫ്" @@ -128,8 +130,8 @@ "ഉയരം കുറയ്‌ക്കുക" "വീതി %1$s ഉയരം %2$s-ലേക്ക് വിഡ്‌ജെറ്റിന്റെ വലുപ്പം മാറ്റി" "കുറുക്കുവഴികൾ" - "%2$s ആപ്പിനുള്ള %1$d കുറുക്കുവഴികൾ" - "%3$s ആപ്പിനായുള്ള %1$d കുറുക്കുവഴികളും %2$d അറിയിപ്പുകളും" + + "നിരസിക്കുക" "അറിയിപ്പ് നിരസിച്ചു" "വ്യക്തിപരം" diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml new file mode 100644 index 0000000000..a3507c5bb8 --- /dev/null +++ b/res/values-mn-rMN/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "Ажил" + "Апп суугаагүй байна." + "Апп-г ашиглах боломжгүй" + "Татаж авсан апп-г Аюулгүй горим дотроос идэвхгүйжүүлсэн" + "Safe горимд виджетүүдийг идэвхгүйжүүлсэн" + "Товчлол алга" + "Үндсэн нүүр" + "Захиалгат үйлдэл" + "Виджетийг авах бол хүрээд барина уу." + "Жижиг хэрэгсэл авах болон тохируулсан үйлдлийг ашиглахын тулд 2 удаа товшоод барина уу." + "%1$d × %2$d" + "%1$d өргөн %2$d өндөр" + "Гараар байршуулахын тулд дараад хүлээнэ үү" + "Автоматаар нэмэх" + "Апп хайх" + "Аппыг ачааллаж байна..." + "\"%1$s\"-д тохирох апп олдсонгүй" + "Бусад апп-г хайх" + "Мэдэгдэл" + "Товчлол авах бол удаан дарна уу." + "Товчлол авах эсвэл тохируулсан үйлдлийг ашиглахын тулд давхар товшоод хүлээнэ үү." + "Энэ Нүүр дэлгэц зайгүй." + "\"Дуртай\" трей дээр өөр зай байхгүй байна" + "Апп-н жагсаалт" + "Хувийн аппын жагсаалт" + "Ажлын аппын жагсаалт" + "Нүүр" + "Арилгах" + "Устгах" + "Апп-н мэдээлэл" + "Суулгах" + "товчлол суулгах" + "Апп нь хэрэглэгчийн оролцоогүйгээр товчлолыг нэмэж чадна" + "Нүүрний тохиргоо болон товчлолыг унших" + "Апп нь Нүүрэндэх товчлол болон тохиргоог уншиж чадна." + "Нүүрний тохиргоо болон товчлолыг бичих" + "Апп нь Нүүрэндэх товчлол болон тохиргоог өөрчилж чадна." + "%1$s утасны дуудлага хийх боломжгүй" + "Виджет ачаалахад асуудал гарав" + "Тохируулга" + "Энэ апп нь системийн апп ба устгах боломжгүй." + "Нэргүй фолдер" + "%1$s-г идэвхгүй болгосон" + + %1$s, %2$d мэдэгдэл байна + %1$s, %2$d мэдэгдэл байна + + "%2$d-н %1$d хуудас" + "%2$d-н Нүүр дэлгэц %1$d" + "Шинэ үндсэн нүүр хуудас" + "%1$d %2$d фолдер нээгдэв" + "Фолдерийг хаахын тулд дарна уу" + "Шинэ нэрийг хадгалахын тулд дарна уу." + "Фолдер хаагдав" + "Фолдерын нэр %1$s болов" + "Фолдер: %1$s" + "Виджет" + "Ханын зураг" + "Нүүр хуудасны тохиргоо" + "Таны админ идэвхгүй болгосон" + "Нүүр дэлгэцийг эргүүлэхийг зөвшөөрөх" + "Утсыг эргүүлсэн үед" + "Мэдэгдлийн цэг" + "Асаалттай" + "Унтраалттай" + "Мэдэгдлийн хандалт шаардлагатай" + "Мэдэгдлийн цэгийг харуулахын тулд %1$s-д аппын мэдэгдлийг асаана уу" + "Тохиргоог өөрчлөх" + "Мэдэгдлийн цэгийг харуулах" + "Нүүр хуудаст дүрс тэмдэг нэмэх" + "Шинэ аппад зориулсан" + "Дүрс тэмдгийн хэлбэрийг өөрчлөх" + "Үндсэн нүүр хэсэгт" + "Системийн өгөгдмөл тохиргоог ашиглах" + "Дөрвөлжин" + "Мохоо өнцөгтэй дөрвөлжин" + "Дугуй" + "Дусал" + "Дүрс тэмдгийн хэлбэрийг өөрчилж байна" + "Тодорхойгүй" + "Устгах" + "Хайх" + "Энэ апп-г суулгаагүй байна" + "Энэ дүрсний апп-г суулгаагүй байна. Та үүнийг устгах буюу апп-г хайж суулгах боломжтой." + "%1$s-г татаж байна, %2$s татсан" + "%1$s нь суулгахыг хүлээж байна" + "%1$s жижиг хэрэгсэл" + "Нүүр дэлгэц нэмэх" + "Энд байршуулах" + "Нүүр дэлгэцэнд нэмсэн зүйл" + "Арилгасан зүйл" + "Зөөх" + "%1$s мөр %2$s баганад зөөх" + "Байршил %1$s-д зөөх" + "Дуртай байршил болох %1$s-д зөөх" + "Зөөвөрлөсөн зүйл" + "Хавтас: %1$s руу нэм" + "%1$s-тай хавтас нэмэх" + "Хавтсанд нэмэгдсэн зүйл" + "Хавтсыг: %1$s нэрээр үүсгэ" + "Үүсгэсэн хавтас" + "Нүүр дэлгэц рүү зөөх" + "Хэмжээг өөрчлөх" + "Өргөсгөх" + "Өндөрсгөх" + "Нарийсгах" + "Намсгах" + "Виджэтийн өргөн %1$s, өндөр %2$s болсон" + "Товчлол" + "%2$s%1$d товчлол" + "%1$d товчлол болон %3$s%2$d мэдэгдэл" + "Хаах" + "Мэдэгдлийг хаасан" + "Хувийн" + "Ажил" + "Ажлын профайл" + "Ажлын аппыг эндээс олно уу" + "Ажлын апп тус бүр тэмдэгтэй ба эдгээрийг танай байгууллагаас аюулгүй байлгадаг. Аппуудад хялбар хандахын тулд тэдгээрийг Үндсэн нүүр хэсэгт зөөнө үү." + "Танай байгууллагаас удирддаг" + "Мэдэгдэл, апп унтраалттай байна" + "Хаах" + "Хаасан" + diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index 7c0b00ec7b..3dcc49542b 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -81,6 +81,8 @@ "Ханын зураг" "Нүүр хуудасны тохиргоо" "Таны админ идэвхгүй болгосон" + "Нүүр дэлгэцийг эргүүлэхийг зөвшөөрөх" + "Утсыг эргүүлсэн үед" "Мэдэгдлийн цэг" "Асаалттай" "Унтраалттай" @@ -128,8 +130,8 @@ "Намсгах" "Виджэтийн өргөн %1$s, өндөр %2$s болсон" "Товчлол" - "%2$s%1$d товчлол" - "%1$d товчлол болон %3$s%2$d мэдэгдэл" + + "Хаах" "Мэдэгдлийг хаасан" "Хувийн" diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml new file mode 100644 index 0000000000..bf1e188058 --- /dev/null +++ b/res/values-mr-rIN/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "कार्य" + "अॅप इंस्टॉल केलेला नाही." + "अॅप उपलब्ध नाही" + "डाउनलोड केलेला अ‍ॅप सुरक्षित मोड मध्‍ये अक्षम केला" + "विजेट सुरक्षित मोडमध्ये अक्षम झाले" + "शॉर्टकट उपलब्ध नाही" + "होम स्क्रीन" + "कस्टम क्रिया" + "विजेट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा." + "एक विजेट निवडण्यासाठी दोनदा टॅप करा आणि धरून ठेवा किंवा कस्टम क्रिया वापरा." + "%1$d × %2$d" + "%1$d रूंद बाय %2$d उंच" + "स्वतः ठेवण्यासाठी स्पर्श करा आणि धरून ठेवा" + "अापोआप जोडा" + "अॅप्स शोधा" + "अॅप्स लोड करत आहे…" + "\"%1$s\" शी जुळणारे कोणतेही अॅप्स आढळले नाहीत" + "अधिक अॅप्स शोधा" + "सूचना" + "शॉर्टकट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा." + "शॉर्टकट निवडण्यासाठी किंवा कस्टम क्रिया वापरण्यासाठी दोनदा टॅप करा आणि धरून ठेवा." + "या मुख्य स्क्रीनवर आणखी जागा नाही." + "आवडीच्या ट्रे मध्ये आणखी जागा नाही" + "अॅप्स सूची" + "वैयक्तिक अॅप्स सूची" + "कामाच्या ठिकाणी वापरली जाणाऱ्या अॅप्सची सूची" + "होम" + "काढा" + "अनइंस्टॉल करा" + "अॅप माहिती" + "इंस्टॉल करा" + "शॉर्टकट स्‍थापित करा" + "वापरकर्ता हस्तक्षेपाशिवाय शॉर्टकट जोडण्यास अॅप ला अनुमती देते." + "होम सेटिंग्ज आणि शॉर्टकट वाचा" + "मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट वाचण्यास अॅप ला अनुमती देते." + "होम सेटिंग्ज आणि शॉर्टकट लिहा" + "मुख्यपृष्ठातील सेटिंग्ज आणि शॉर्टकट बदलण्यास अॅप ला अनुमती देते." + "%1$s ला फोन कॉल करण्याची अनुमती नाही" + "विजेट लोड करण्यात समस्या" + "सेटअप" + "हा सिस्टम अॅप आहे आणि अनइंस्टॉल केला जाऊ शकत नाही." + "अनामित फोल्डर" + "%1$s अक्षम केला आहे" + + %1$s, कडे %2$d सूचना आहे + %1$s, कडे %2$d सूचना आहेत + + "%2$d पैकी %1$d पृष्ठ" + "%2$d पैकी %1$d मुख्य स्क्रीन" + "नवीन मुख्य स्क्रीन पृष्ठ" + "फोल्डर उघडले, %1$d बाय %2$d" + "फोल्डर बंद करण्यासाठी टॅप करा" + "पुनर्नामित करणे सेव्ह करण्यासाठी टॅप करा" + "फोल्डर बंद" + "फोल्डरचे नाव बदलून %1$s असे ठेवले" + "फोल्डर: %1$s" + "विजेट" + "वॉलपेपर" + "होम सेटिंग्‍ज" + "आपल्या प्रशासकाने अक्षम केले" + "मुख्यस्क्रीन फिरविण्‍यास अनुमती द्या" + "फोन फिरविला जातो तेव्हा" + "सूचना बिंदू" + "चालू" + "बंद" + "सूचनांच्या अ‍ॅक्सेसची आवश्यकता आहे" + "सूचना बिंदू दाखवण्यासाठी, %1$s साठी अ‍ॅप सूचना चालू करा" + "सेटिंग्ज बदला" + "सूचना बिंदू दाखवा" + "होम स्क्रीनवर आयकन जोडा" + "नवीन अॅप्ससाठी" + "चिन्हाचा आकार बदला" + "होम स्क्रीनवर" + "सिस्‍टमचे डीफॉल्‍ट वापरा" + "चौरस" + "गोलाकार चौरस" + "वर्तुळ" + "अश्रू" + "चिन्हाचा आकार बदल लागू करत आहे" + "अज्ञात" + "काढा" + "शोधा" + "हा अॅप इंस्टॉल केलेला नाही" + "या चिन्हासाठी अॅप इंस्टॉल केलेला नाही. तुम्ही ते काढू शकता किंवा अॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे इंस्टॉल करू शकता." + "%1$s डाउनलोड होत आहे , %2$s पूर्ण झाले" + "%1$s इंस्टॉल करण्याची प्रतिक्षा करत आहे" + "%1$s विजेट" + "होम स्क्रीनवर जोडा" + "आयटम येथे हलवा" + "आयटम मुख्य स्क्रीनवर जोडला" + "आयटम काढला" + "आयटम हलवा" + "पंक्ति %1$s स्तंभ %2$s मध्ये हलवा" + "%1$s स्थानावर हलवा" + "आवडत्या %1$s स्थानावर हलवा" + "आयटम हलविला" + "फोल्‍डरवर जोडा: %1$s" + "%1$s सह फोल्डरमध्ये जोडा" + "फोल्‍डरमध्‍ये आयटम जोडले" + "यासह फोल्‍डर तयार करा: %1$s" + "फोल्‍डर तयार केले" + "मुख्य स्क्रीनवर हलवा" + "आकार बदला" + "रूंदी वाढवा" + "उंची वाढवा" + "रुंदी कमी करा" + "उंची कमी करा" + "विजेटचा आकार रुंदी %1$s उंची %2$s मध्ये बदलला" + "शॉर्टकट" + "%2$s साठी %1$d शॉर्टकट" + "%3$sसाठी %1$d शॉर्टकट आणि %2$d सूचना" + "डिसमिस करा" + "सूचना डिसमिस केली" + "वैयक्तिक" + "कार्यालय" + "कार्य प्रोफाइल" + "कामाची अ‍ॅप्स येथे मिळवा" + "प्रत्येक कार्य अ‍ॅपला एक बॅज असतो आणि तो तुमच्या संस्थेकडून सुरक्षित ठेवला जातो. अधिक सहज अ‍ॅक्सेससाठी अ‍ॅप्स तुमच्या होम स्क्रीनवर हलवा." + "तुमच्या संस्थेकडून व्यवस्थापित" + "सूचना आणि अॅप्स बंद आहेत" + "बंद करा" + "बंद केले" + diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 0e2f9c808c..7b9aebd8a8 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -28,9 +28,9 @@ "विजेट सुरक्षित मोडमध्ये अक्षम झाले" "शॉर्टकट उपलब्ध नाही" "होम स्क्रीन" - "सानुकूल क्रिया" + "कस्टम क्रिया" "विजेट निवडण्यासाठी स्पर्श करा आणि धरून ठेवा." - "एक विजेट निवडण्यासाठी दोनदा टॅप करा आणि धरून ठेवा किंवा सानुकूल क्रिया वापरा." + "एक विजेट निवडण्यासाठी दोनदा टॅप करा आणि धरून ठेवा किंवा कस्टम क्रिया वापरा." "%1$d × %2$d" "%1$d रूंद बाय %2$d उंच" "स्वतः ठेवण्यासाठी स्पर्श करा आणि धरून ठेवा" @@ -73,7 +73,7 @@ "नवीन मुख्य स्क्रीन पृष्ठ" "फोल्डर उघडले, %1$d बाय %2$d" "फोल्डर बंद करण्यासाठी टॅप करा" - "पुनर्नामित करणे जतन करण्यासाठी टॅप करा" + "पुनर्नामित करणे सेव्ह करण्यासाठी टॅप करा" "फोल्डर बंद" "फोल्डरचे नाव बदलून %1$s असे ठेवले" "फोल्डर: %1$s" @@ -81,6 +81,8 @@ "वॉलपेपर" "होम सेटिंग्‍ज" "आपल्या प्रशासकाने अक्षम केले" + "मुख्यस्क्रीन फिरविण्‍यास अनुमती द्या" + "फोन फिरविला जातो तेव्हा" "सूचना बिंदू" "चालू" "बंद" @@ -102,7 +104,7 @@ "काढा" "शोधा" "हा अॅप इंस्टॉल केलेला नाही" - "या चिन्हासाठी अॅप इंस्टॉल केलेला नाही. आपण ते काढू शकता किंवा अॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे इंस्टॉल करू शकता." + "या चिन्हासाठी अॅप इंस्टॉल केलेला नाही. तुम्ही ते काढू शकता किंवा अॅपचा शोध घेऊ शकता आणि त्यास व्यक्तिचलितपणे इंस्टॉल करू शकता." "%1$s डाउनलोड होत आहे , %2$s पूर्ण झाले" "%1$s इंस्टॉल करण्याची प्रतिक्षा करत आहे" "%1$s विजेट" @@ -128,8 +130,8 @@ "उंची कमी करा" "विजेटचा आकार रुंदी %1$s उंची %2$s मध्ये बदलला" "शॉर्टकट" - "%2$s साठी %1$d शॉर्टकट" - "%3$sसाठी %1$d शॉर्टकट आणि %2$d सूचना" + + "डिसमिस करा" "सूचना डिसमिस केली" "वैयक्तिक" diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml new file mode 100644 index 0000000000..3c223b6334 --- /dev/null +++ b/res/values-ms-rMY/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "Kerja" + "Apl tidak dipasang." + "Apl tidak tersedia" + "Apl yang dimuat turun dilumpuhkan dalam mod Selamat" + "Widget dilumpuhkan dalam mod Selamat" + "Pintasan tidak tersedia" + "Skrin utama" + "Tindakan tersuai" + "Sentuh & tahan untuk mengambil widget." + "Ketik dua kali & tahan untuk mengambil widget atau menggunakan tindakan tersuai" + "%1$d × %2$d" + "Lebar %1$d kali tinggi %2$d" + "Sentuh & tahan untuk meletakkan widget/ikon secara manual" + "Tambahkan secara automatik" + "Cari apl" + "Memuatkan apl…" + "Tiada apl yang ditemui sepadan dengan \"%1$s\"" + "Cari lagi apl" + "Pemberitahuan" + "Sentuh & tahan untuk mengambil pintasan." + "Ketik dua kali & tahan untuk mengambil pintasan atau menggunakan tindakan tersuai." + "Tiada lagi ruang pada skrin Laman Utama ini." + "Tiada ruang dalam dulang Kegemaran lagi" + "Senarai apl" + "Senarai apl peribadi" + "Senarai apl kerja" + "Laman Utama" + "Alih keluar" + "Nyahpasang" + "Maklumat apl" + "Pasang" + "pasang pintasan" + "Membenarkan apl menambah pintasan tanpa campur tangan pengguna." + "baca tetapan dan pintasan Laman Utama" + "Membenarkan apl membaca tetapan dan pintasan di Laman Utama." + "tulis tetapan dan pintasan Laman Utama" + "Membenarkan apl menukar tetapan dan pintasan di Laman Utama." + "%1$s tidak dibenarkan membuat panggilan telefon" + "Masalah memuatkan widget" + "Persediaan" + "Ini ialah apl sistem dan tidak boleh dinyahpasang." + "Folder Tanpa Nama" + "%1$s dilumpuhkan" + + %1$s, mempunyai %2$d pemberitahuan + %1$s, mempunyai %2$d pemberitahuan + + "Halaman %1$d daripada %2$d" + "Skrin Laman Utama %1$d daripada %2$d" + "Halaman skrin utama baharu" + "Folder dibuka, %1$d kali %2$d" + "Ketik untuk menutup folder" + "Ketik untuk menyimpan penamaan semula" + "Folder ditutup" + "Folder dinamakan semula kepada %1$s" + "Folder: %1$s" + "Widget" + "Kertas dinding" + "Tetapan laman utama" + "Dilumpuhkan oleh pentadbir anda" + "Benarkan putaran Skrin Utama" + "Apabila telefon diputar" + "Titik pemberitahuan" + "Hidup" + "Mati" + "Akses pemberitahuan diperlukan" + "Untuk menunjukkan Titik Pemberitahuan, hidupkan pemberitahuan apl untuk %1$s" + "Tukar tetapan" + "Tunjukkan titik pemberitahuan" + "Tambahkan ikon pada Skrin Utama" + "Untuk apl baharu" + "Tukar bentuk ikon" + "pada Skrin Utama" + "Gunakan lalai sistem" + "Segi empat sama" + "Segi empat berbucu bulat" + "Bulatan" + "Titisan air mata" + "Menggunakan perubahan bentuk ikon" + "Tidak diketahui" + "Alih keluar" + "Carian" + "Apl ini tidak dipasang" + "Apl untuk ikon ini tidak dipasang. Anda boleh mengalih keluar atau mencari dan memasang apl itu secara manual." + "%1$s memuat turun, %2$s selesai" + "%1$s menunggu untuk dipasang" + "Widget %1$s" + "Tambahkan pada Skrin Utama" + "Alihkan item ke sini" + "Item ditambahkan pada skrin utama" + "Item dialih keluar" + "Alihkan Item" + "Alihkan ke baris %1$s lajur %2$s" + "Alihkan ke kedudukan %1$s" + "Alihkan ke kedudukan kegemaran %1$s" + "Item dialihkan" + "Tambahkan pada folder: %1$s" + "Tambahkan pada folder dengan %1$s" + "Item ditambahkan pada folder" + "Buat folder dengan: %1$s" + "Folder dibuat" + "Alihkan ke Skrin Utama" + "Ubah saiz" + "Tambahkan kelebaran" + "Tambahkan ketinggian" + "Kurangkan kelebaran" + "Kurangkan ketinggian" + "Saiz widget diubah menjadi %1$s lebar %2$s tinggi" + "Pintasan" + "%1$d pintasan untuk %2$s" + "%1$d pintasan dan %2$d pemberitahuan untuk %3$s" + "Ketepikan" + "Pemberitahuan diketepikan" + "Peribadi" + "Kerja" + "Profil kerja" + "Temui apl kerja di sini" + "Setiap apl kerja terdapat lencana dan dilindungi oleh organisasi anda. Alihkan apl ke Skrin Utama untuk akses yang lebih mudah." + "Diurus oleh organisasi anda" + "Pemberitahuan dan apl dimatikan" + "Tutup" + "Ditutup" + diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index 130e008389..ea178b89d7 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -81,6 +81,8 @@ "Kertas dinding" "Tetapan laman utama" "Dilumpuhkan oleh pentadbir anda" + "Benarkan putaran Skrin Utama" + "Apabila telefon diputar" "Titik pemberitahuan" "Hidup" "Mati" @@ -128,8 +130,8 @@ "Kurangkan ketinggian" "Saiz widget diubah menjadi %1$s lebar %2$s tinggi" "Pintasan" - "%1$d pintasan untuk %2$s" - "%1$d pintasan dan %2$d pemberitahuan untuk %3$s" + + "Ketepikan" "Pemberitahuan diketepikan" "Peribadi" diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml new file mode 100644 index 0000000000..59ac4cad35 --- /dev/null +++ b/res/values-my-rMM/strings.xml @@ -0,0 +1,146 @@ + + + + + "ဖွင့်တင်စက်၃" + + "အလုပ်" + "အက်ပ်မထည့်သွင်းထားပါ" + "အက်ပ်လက်လှမ်း မမှီပါ" + "ဒေါင်းလုဒ် အက်ပ်ကို လုံခြုံရေး မုဒ်ထဲမှာ ပိတ်ထား" + "လုံခြုံရေး မုဒ်ထဲမှာ ဝီဂျက်များကို ပိတ်ထား" + "ဖြတ်လမ်း မရနိုင်ပါ" + "ပင်မစာမျက်နှာ" + "စိတ်ကြိုက် လုပ်ဆောင်ချက်များ" + "ဝဒ်ဂျက်တစ်ခုကို ကောက်ယူရန် ဖိနှိပ်ထားပါ" + "ဝစ်ဂျက်တစ်ခုကိုရယူရန် သို့မဟုတ် စိတ်ကြိုက်လုပ်ဆောင်မှုများကို အသုံးပြုရန် နှစ်ချက်တို့ပြီး ကိုင်ထားပါ။" + "%1$d × %2$d" + "အလျား %1$d နှင့် အမြင့် %2$d" + "ကိုယ်တိုင်ထည့်ရန် ထိထားပါ" + "အလိုအလျောက် ထည့်ရန်" + "ရှာဖွေမှု အက်ပ်များ" + "အက်ပ်များကို ဖွင့်နေသည်…" + "\"%1$s\" နှင့်ကိုက်ညီသည့် အပ်ပ်များကို မတွေ့ပါ" + "နောက်ထပ် အက်ပ်များကို ရှာပါ" + "အကြောင်းကြားချက်များ" + "ဖြတ်လမ်းလင့်ခ်တစ်ခုကို ရွေးရန် ထိပြီး ဖိထားပါ။" + "ဖြတ်လမ်းလင့်ခ်ကို ရွေးရန် (သို့) စိတ်ကြိုက်လုပ်ဆောင်ချက်များကို သုံးရန် နှစ်ချက်တို့ပြီး ဖိထားပါ။" + "ဤပင်မမျက်နှာစာတွင် နေရာလွတ် မကျန်တော့ပါ" + "အနှစ်သက်ဆုံးများ ထားရာတွင် နေရာလွတ် မကျန်တော့ပါ" + "အက်ပ်စာရင်း" + "တစ်ကိုယ်ရေသုံး အက်ပ်စာရင်း" + "အလုပ်သုံး အက်ပ်စာရင်း" + "ပင်မစာမျက်နှာ" + "ဖယ်ရှားမည်" + "ဖယ်ထုတ်မည်" + "အက်ပ်အချက်အလက်များ" + "ထည့်သွင်းရန်" + "အတိုကောက်မှတ်သားမှုများအား ထည့်သွင်းခြင်း" + "အသုံးပြုသူ လုပ်ဆောင်မှုမရှိပဲ အပ်ပလီကေးရှင်းကို အတိုကောက်မှတ်သားမှုများ ပြုလုပ်ခွင့် ပေးခြင်း" + "ပင်မမျက်နှာစာ အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများအား ဖတ်ခြင်း" + "ပင်မမျက်နှာစာတွင်ရှိသော အပြင်အဆင်နှင့် အတိုကောက်မှတ်သားမှုများကို အပ်ပလီကေးရှင်းအား ဖတ်ခွင့်ပြုခြင်း" + "ပင်မမျက်နှာစာ အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများအား ရေးသားခြင်း" + "ပင်မမျက်နှာစာတွင် ရှိသော အပြင်အဆင် နှင့် အတိုကောက်မှတ်သားမှုများ ကို အပ်ပလီကေးရှင်းအား ပြောင်းခွင့်ပြုခြင်း" + "%1$sသည် ဖုန်းခေါ်ဆိုခွင့် မရှိပါ" + "ဝဒ်ဂျက် တင်ရာတွင် ပြသနာ ရှိပါသည်" + "စဖွင့်သတ်မှတ်ရန်" + "ဤအပ်ပလီကေးရှင်းမှာ စစ်စတန်ပိုင်းဆိုင်ရာ အပ်ပလီကေးရှင်းဖြစ်ပါသည်။ ထုတ်ပစ်၍ မရပါ" + "အမည်မရှိအကန့်" + "%1$s ကို ပိတ်ထားသည်" + + %1$s တွင် အကြောင်းကြားချက် %2$d ခု ရှိသည် + %1$s တွင် အကြောင်းကြားချက် %2$d ခု ရှိသည် + + "စာမျက်နှာ %1$d မှ %2$d" + "ပင်မစာမျက်နှာ %1$d မှ %2$d" + "ပင်မမျက်နှာပြင် စာမျက်နှာသစ်" + "ဖွင့်ထားသောအကန့်, %1$d နှင့် %2$d" + "ဖိုင်တွဲကို ပိတ်ရန် တို့ပါ" + "အမည်ပြောင်းခြင်းကို သိမ်းဆည်းရန် တို့ပါ" + "ပိတ်ထားသောအကန့်" + "ပြောင်းလဲလိုက်သော အကန့်အမည် %1$s" + "အကန့်အမည်: %1$s" + "ဝိဂျက်များ" + "နောက်ခံများ" + "ပင်မဆက်တင်များ" + "သင့်စီမံခန့်ခွဲသူက ပိတ်လိုက်ပါသည်" + "ပင်မစာမျက်နှာလှည့်ခြင်းကို ခွင့်ပြုပါ" + "ဖုန်းကိုလှည့်ထားစဉ်" + "အကြောင်းကြားချက်အမှတ်အသားများ" + "ဖွင့်ထားသည်" + "ပိတ်ထားသည်" + "အကြောင်းကြားချက် အသုံးပြုခွင့် လိုအပ်သည်" + "အကြောင်းကြားချက် အစက်များကို ပြသရန် %1$s အတွက် အက်ပ်အကြောင်းကြားချက်များကို ဖွင့်ပါ" + "ဆက်တင်များ ပြောင်းရန်" + "အကြောင်းကြားချက် အမှတ်အသားများကို ပြရန်" + "ပင်မစာမျက်နှာသို့ သင်္ကေတပုံ ထည့်ရန်" + "အက်ပ်အသစ်များအတွက်" + "သင်္ကေတပုံစံကို ပြောင်းရန်" + "\'ပင်မမျက်နှာပြင်\' ပေါ်တွင်" + "စနစ်၏ မူရင်းပုံကို အသုံးပြုရန်" + "လေးထောင့်" + "စတုရန်းမကျ စက်ဝိုင်းမကျပုံ" + "စက်ဝိုင်း" + "မျက်ရည်စက်ပုံ" + "သင်္ကေတပုံစံကို ပြောင်းလဲနေသည်" + "မသိရ" + "ဖယ်ရှားရန်" + "ရှာဖွေရန်" + "အက်ပ်မတပ်ဆင်ရသေးပါ" + "ဤအိုင်ကွန်အတွက် အက်ပ်အားမထည့်သွင်းထားပါ။ You can remove it, or search for the အက်ပ်and install it manually." + "%1$s ဒေါင်းလုဒ်လုပ်နေသည်၊ %2$s ပြီးပါပြီ" + "%1$s ကိုထည့်သွင်းရန်စောင့်နေသည်" + "%1$s ဝိဂျက်များ" + "ပင်မမျက်နှာစာသို့ ထည့်ပါ" + "၎င်းအား ဤသို့ ရွှေ့ပါ" + "ပင်မ ဖန်မျက်နှာပြင်သို့ ထည့်ပြီး၏" + "၎င်းအား ဖယ်ရှားပြီး၏" + "၎င်းအား ရွှေ့ပါ" + "အတန်း %1$s အတိုင် %2$s သို့ ရွှေ့ပါ" + "%1$s သို့ နေရာရွှေ့ပါ" + "စိတ်ကြိုက်နေရာ %1$s သို့ ရွှေ့ပါ" + "၎င်းအားရွှေ့ပြီး" + "ဖိုလ်ဒါသို့ ထည့်ရန်- %1$s" + "%1$s အမည်ရှိ ဖိုလ်ဒါသို့ ထည့်ပြီး၏" + "ဖိုလ်ဒါသို့ ထည့်ပြီး" + "ဖိုလ်ဒါ ပြုလုပ်ရန်- %1$s" + "ဖိုလ်ဒါ ပြုလုပ်ပြီး" + "ပင်မမျက်နှာပြင်သို့ ရွှေ့ပါ" + "အရွယ်အစားပြောင်းပါ" + "အကျယ်အား တိုးပါ" + "အမြင့်အား တိုးပါ" + "အကျယ်အား လျှော့ပါ" + "အမြင့်အား လျှော့ပါ" + "Widget အား အကျယ် %1$s အမြင့် %2$s အရွယ်အစားပြန်လည်ချိန်ညှိပြီး၏" + "ဖြတ်လမ်းများ" + "%2$s အတွက် အမြန်နည်း %1$d ခု" + "%3$s အတွက် ဖြတ်လမ်းလင့်ခ် %1$d နှင့် အကြောင်းကြားချက် %2$d ခု" + "ပယ်ရန်" + "အသိပေးချက်ကို ဖယ်ထုတ်ပြီးပါပြီ" + "ကိုယ်ပိုင်" + "အလုပ်" + "အလုပ်ပရိုဖိုင်" + "အလုပ်အက်ပ်များကို ဤနေရာတွင်ရှာဖွေပါ" + "အလုပ်အက်ပ်တိုင်းတွင် တံဆိပ် တစ်ခုစီရှိပြီး သင်၏ အဖွဲ့အစည်းက လုံခြုံအောင် ထားရှိပါသည်။ အသုံးပြုရ ပိုမိုလွယ်ကူစေရန် အက်ပ်များကို သင်၏ ပင်မမျက်နှာပြင်သို့ ရွှေ့ပါ။" + "သင်၏ အဖွဲ့အစည်းက စီမံခန့်ခွဲထားပါသည်" + "အကြောင်းကြားချက်များနှင့် အက်ပ်များကို ပိတ်ထားသည်" + "ပိတ်ရန်" + "ပိတ်ထားသည်" + diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index 778402ac27..315ebf5700 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -81,6 +81,8 @@ "နောက်ခံများ" "ပင်မဆက်တင်များ" "သင့်စီမံခန့်ခွဲသူက ပိတ်လိုက်ပါသည်" + "ပင်မစာမျက်နှာလှည့်ခြင်းကို ခွင့်ပြုပါ" + "ဖုန်းကိုလှည့်ထားစဉ်" "အကြောင်းကြားချက်အမှတ်အသားများ" "ဖွင့်ထားသည်" "ပိတ်ထားသည်" @@ -128,8 +130,8 @@ "အမြင့်အား လျှော့ပါ" "Widget အား အကျယ် %1$s အမြင့် %2$s အရွယ်အစားပြန်လည်ချိန်ညှိပြီး၏" "ဖြတ်လမ်းများ" - "%2$s အတွက် အမြန်နည်း %1$d ခု" - "%3$s အတွက် ဖြတ်လမ်းလင့်ခ် %1$d နှင့် အကြောင်းကြားချက် %2$d ခု" + + "ပယ်ရန်" "အသိပေးချက်ကို ဖယ်ထုတ်ပြီးပါပြီ" "ကိုယ်ပိုင်" diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 5542079640..d5beead867 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -81,6 +81,8 @@ "Bakgrunner" "Startsideinnstillinger" "Administratoren har slått av funksjonen" + "Tillat rotasjon av startskjermen" + "Når telefonen roteres" "Varselsprikker" "På" "Av" @@ -128,8 +130,8 @@ "Reduser høyden" "Størrelsen på modulen er endret til bredde %1$s og høyde %2$s" "Snarveier" - "%1$d snarveier for %2$s" - "%1$d snarveier og %2$d varsler for %3$s" + + "Avvis" "Varselet ble avvist" "Personlig" diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml new file mode 100644 index 0000000000..a8a64f1bbc --- /dev/null +++ b/res/values-ne-rNP/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "कार्य" + "अनुप्रयोग स्थापित छैन।" + "अनुप्रयोग उपलब्ध छैन" + "सुरक्षित मोडमा डाउनलोड गरेको अनुप्रयोग अक्षम गरिएको छ" + "सुरक्षित मोडमा विगेटहरू अक्षम गरियो" + "सर्टकट उपलब्ध छैन" + "गृह स्क्रिन" + "आफू अनुकूलका कारबाहीहरू" + "एउटा विजेटलाई टिप्नको लागि टच गरेर होल्ड गर्नुहोस्।" + "विजेटलाई छान्न वा आफू अनुकूल कार्यहरू प्रयोग गर्न डबल ट्याप गरी होल्ड गर्नुहोस्।" + "%1$d × %2$d" + "%1$d चौडाइ गुणा %2$d उचाइ" + "म्यानुअल तरिकाले थप्न छुनुहोस् र थिची राख्नुहोस्‌" + "स्वतः थप्नुहोस्" + "खोजसम्बन्धी अनुप्रयोगहरू" + "अनुप्रयोगहरू लोड गर्दै…" + "\"%1$s\" सँग मिल्दो कुनै अनुप्रयोग भेटिएन" + "थप अनुप्रयोगहरू खोज्नुहोस्" + "सूचनाहरू" + "कुनै सर्टकट छनौट गर्न छोइराख्नुहोस्।" + "कुनै सर्टकट छनौट गर्न वा रोजेका कारबाहीहरू प्रयोग गर्न डबल ट्याप गरेर छोइराख्नुहोस्।" + "यो गृह स्क्रिनमा कुनै थप ठाउँ छैन।" + "मनपर्ने ट्रे अब कुनै ठाँउ छैन" + "अनुप्रयोगको सूची" + "व्यक्तिगत अनुप्रयोगहरूको सूची" + "कार्यसम्बन्धी अनुप्रयोगहरूको सूची" + "गृह" + "हटाउनुहोस्" + "विस्थापित गर्नुहोस्" + "अनुप्रयोग जानकारी" + "स्थापना गर्नुहोस्" + "सर्टकट स्थापना गर्नेहोस्" + "प्रयोगकर्ताको हस्तक्षेप बिना एउटा अनुप्रयोगलाई सर्टकटमा थप्नको लागि अनुमति दिनुहोस्।" + "गृह सेटिङहरू र सर्टकटहरू पढ्नुहोस्" + "गृहमा एउटा अनुप्रयोगलाई सेटिङहरू र सर्टकटहरू पढ्न अनुमति दिनुहोस्।" + "गृह सेटिङहरू र सर्टकटहरू लेख्नुहोस्" + "गृहमा एउटा अनुप्रयोगलाई सेटिङ र सर्टकट बदल्न अनुमति दिनुहोस्।" + "%1$s ले फोन कलहरू गर्न अनुमति छैन" + "समस्या लोडिङ गर्ने विजेट" + "सेटअप" + "यो प्रणाली अनुप्रयोग हो र यसलाई स्थापना रद्द गर्न सकिँदैन।" + "बेनाम फोल्डर" + "असक्षम पारिएको %1$s" + + %1$s, यसमा %2$d सूचनाहरू छन्‌ + %1$s, यसमा %2$d सूचना छ + + "पृष्ठ %2$d को %1$d" + "गृह स्क्रिन %1$d को %2$d" + "नयाँ गृह स्क्रिन पृष्ठ" + "फोल्डर खुल्यो %1$d बाट %2$d" + "फोल्डरलाई बन्द गर्न ट्याप गर्नुहोस्" + "पुनःनामाकरणलाई सुरक्षित गर्न ट्याप गर्नुहोस्" + "फोल्डर बन्द भयो" + "फोल्डर %1$s मा पुनःनामाकरण गरियो।" + "फोल्डर: %1$s" + "विजेटहरू" + "वालपेपरहरु" + "गृहपृष्ठका सेटिङहरू" + "तपाईँको प्रशासकद्वारा असक्षम गरिएको" + "गृह स्क्रिनलाई घुम्ने अनुमति दिनुहोस्" + "फोनलाई घुमाइँदा" + "सूचनाको प्रतीक जनाउने थोप्लोहरू" + "सक्रिय छ" + "निष्क्रिय छ" + "सूचनासम्बन्धी पहुँच आवश्यक हुन्छ" + "सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउन %1$s को अनुप्रयोगसम्बन्धी सूचनाहरूलाई सक्रिय गर्नुहोस्" + "सेटिङहरू बदल्नुहोस्" + "सूचनाको प्रतीक जनाउने थोप्लाहरू देखाउनुहोस्" + "गृह स्क्रिनमा आइकन थप्नुहोस्" + "नयाँ अनुप्रयोगका लागि" + "आइकनको आकार परिवर्तन गर्नुहोस्" + "गृह स्क्रिनमा" + "प्रणालीको पूर्वनिर्धारित सेटिङ प्रयोग गर्नुहोस्" + "वर्ग" + "वर्गाकार वृत्त" + "वृत्त" + "आँसुको थोपा" + "आइकनको आकारमा गरिएका परिवर्तनहरू लागू गरिँदैछन्" + "अज्ञात" + "हटाउनुहोस्" + "खोजी गर्नुहोस्" + "यो अनुप्रयोग स्थापित छैन" + "यो प्रतिमाका लागि अनुप्रयोगलाई स्थापना गरिएको छैन। तपाईं यसलाई हटाउन, वा अनुप्रयोग खोजी र स्वयं यो स्थापित गर्न सक्नुहुन्छ।" + "%1$s डाउनलोड गर्दै, %2$s सम्पन्‍न" + "%1$s स्थापना गर्न प्रतीक्षा गर्दै" + "%1$s विजेटहरू" + "गृह स्क्रिनमा थप्नुहोस्" + "वस्तु यहाँ सार्नुहोस्" + "वस्तु गृह स्क्रिनमा थपियो" + "वस्तु हटाइयो" + "वस्तु सार्नुहोस्" + "पङ्क्ति %1$s स्तम्भ %2$s मा सार्नुहोस्" + "स्थिति %1$s मा सार्नुहोस्" + "मनपर्ने स्थिति %1$s मा सार्नुहोस्" + "वस्तु सारियो" + "फोल्डर: %1$s मा थप्नुहोस्" + "फोल्डरमा %1$s सँग थप्नुहोस्" + "वस्तु फोल्डरमा थपियो" + "%1$s: मार्फत फोल्डर सिर्जना गर्नुहोस्" + "फोल्डर सिर्जना गरियो" + "गृह स्क्रिनमा सार्नुहोस्" + "पुनःआकार मिलाउनुहोस्" + "चौडाइ बढाउनुहोस्" + "उँचाइ बढाउनुहोस्" + "चौडाइ घटाउनुहोस्" + "उँचाइ घटाउनुहोस्" + "विजेट चौडाइ %1$s उचाइ %2$s मा पुनः आकार मिलाइयो" + "सर्टकटहरू" + "%2$s का %1$d सर्टकटहरू" + "%3$s का %1$d सर्टकट र %2$d सूचनाहरू" + "खारेज गर्नुहोस्" + "सूचना खारेज गरियो" + "व्यक्तिगत" + "कार्यसम्बन्धी" + "कार्य प्रोफाइल" + "कार्यसम्बन्धी अनुप्रयोगहरू यहाँ प्राप्त गर्नुहोस्" + "कार्यसम्बन्धी प्रत्येक अनुप्रयोगमा एउटा ब्याज छ र तपाईंको संगठनले यसलाई सुरक्षित राखेको छ । अझ सजिलो गरी पहुँच राख्नका लागि अनुप्रयोगहरूलाई आफ्नो गृहस्क्रिनमा सार्नुहोस्‌।" + "तपाईंको सङ्गठनले व्यवस्थापन गरेको" + "सूचना र अनुप्रयोगहरू निष्क्रिय छन्‌" + "बन्द गर्नुहोस्" + "बन्द गरियो" + diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index fa2f9cf0b8..f44c47bd90 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -81,6 +81,8 @@ "वालपेपरहरु" "गृहपृष्ठका सेटिङहरू" "तपाईँको प्रशासकद्वारा असक्षम गरिएको" + "गृह स्क्रिनलाई घुम्ने अनुमति दिनुहोस्" + "फोनलाई घुमाइँदा" "सूचनाको प्रतीक जनाउने थोप्लोहरू" "सक्रिय छ" "निष्क्रिय छ" @@ -128,8 +130,8 @@ "उँचाइ घटाउनुहोस्" "विजेट चौडाइ %1$s उचाइ %2$s मा पुनः आकार मिलाइयो" "सर्टकटहरू" - "%2$s का %1$d सर्टकटहरू" - "%3$s का %1$d सर्टकट र %2$d सूचनाहरू" + + "खारेज गर्नुहोस्" "सूचना खारेज गरियो" "व्यक्तिगत" diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index 458b6dd993..e1c059ad48 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -54,9 +54,9 @@ "Installeren" "Snelle links instellen" "Een app toestaan snelkoppelingen toe te voegen zonder tussenkomst van de gebruiker." - "instellingen en snelkoppelingen op de homepage lezen" + "instellingen en snelkoppelingen op startscherm lezen" "De app toestaan de instellingen en snelkoppelingen op de homepage te lezen." - "instellingen en snelkoppelingen op de homepage schrijven" + "instellingen en snelkoppelingen op startscherm zetten" "De app toestaan de instellingen en snelkoppelingen op de homepage te wijzigen." "%1$s mag niet bellen" "Probleem bij het laden van widget" @@ -79,8 +79,10 @@ "Map: %1$s" "Widgets" "Achtergrond" - "Instellingen voor homepage" + "Instellingen startscherm" "Uitgeschakeld door je beheerder" + "Draaien van startscherm toestaan" + "Wanneer de telefoon gedraaid is" "Meldingsstipjes" "Aan" "Uit" @@ -128,8 +130,8 @@ "Hoogte verkleinen" "Formaat van widget gewijzigd in breedte %1$s en hoogte %2$s" "Snelkoppelingen" - "%1$d snelkoppelingen voor %2$s" - "%1$d snelkoppelingen en %2$d meldingen voor %3$s" + + "Sluiten" "Melding gesloten" "Privé" diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml new file mode 100644 index 0000000000..9152b43c45 --- /dev/null +++ b/res/values-or/strings.xml @@ -0,0 +1,146 @@ + + + + + "ଲଞ୍ଚର୍3" + + "କାମ" + "ଆପ୍‌ ଇନଷ୍ଟଲ୍‌ ହୋଇନାହିଁ" + "ଆପ୍‌ ଉପଲବ୍ଧ ନାହିଁ" + "ନିରାପଦ ମୋଡରେ ଡାଉନଲୋଡ୍‌ ହେଇଥିବା ଆପ୍‌ ଅକ୍ଷମ କରାଗଲା" + "ନିରାପଦ ମୋଡରେ ୱିଜେଟ୍‌ ଅକ୍ଷମ କରାଗଲା" + "ଶର୍ଟକଟ୍‌ ଉପଲବ୍ଧ ନାହିଁ" + "ହୋମ୍‌ ସ୍କ୍ରୀନ୍‌" + "କାର୍ଯ୍ୟ କଷ୍ଟମ୍ କରନ୍ତୁ" + "ୱିଜେଟ୍‌ ନେବାକୁ ସ୍ପର୍ଶ କରନ୍ତୁ ଏବଂ ଧରି ରଖନ୍ତୁ।" + "ଡବଲ୍‌-ଟାପ୍‌ କରନ୍ତୁ ଏବଂ ଏକ ୱିଜେଟ୍‌ ନେବାକୁ ଧରି ରଖନ୍ତୁ କିମ୍ୱା କଷ୍ଟମ୍ କାର୍ଯ୍ୟପ୍ରକ୍ରିୟା ବ୍ୟବହାର କରନ୍ତୁ।" + "%1$d × %2$d" + "%1$d ଓସାର ଓ %2$d ଉଚ୍ଚ" + "ମାନୁଆଲ୍‌ ଭାବରେ ରଖିବାକୁ ସ୍ପର୍ଶ କରନ୍ତୁ ଏବଂ ଧରି ରଖନ୍ତୁ" + "ସ୍ୱଚାଳିତ ଭାବେ ଯୋଡ଼ନ୍ତୁ" + "ଆପ୍‌ ଖୋଜନ୍ତୁ" + "ଆପ୍‌ ଲୋଡ୍‌ ହେଉଛି..." + "\"%1$s\" ସହିତ ମେଳ ହେଉଥିବା କୌଣସି ଆପ୍‌ ମିଳିଲା ନାହିଁ" + "ଅଧିକ ଆପ୍‌ ଖୋଜନ୍ତୁ" + "ବିଜ୍ଞପ୍ତି" + "ଏକ ଶର୍ଟକଟ୍ ଚୟନ କରିବାକୁ ସ୍ପର୍ଶ କରି ଧରି ରଖନ୍ତୁ।" + "ଡବଲ୍‌-ଟାପ୍‌ କରନ୍ତୁ ଏବଂ ଏକ ଶର୍ଟକଟ୍ ଚୟନ କରିବାକୁ ଧରି ରଖନ୍ତୁ କିମ୍ୱା କଷ୍ଟମ୍ ପ୍ରକ୍ରିୟା ବ୍ୟବହାର କରନ୍ତୁ।" + "ହୋମ୍‌ ସ୍କ୍ରୀନ ପାଇଁ ଆଉ କୋଠରୀ ନାହିଁ" + "ମନପସନ୍ଦ ଟ୍ରେରେ ଆଉ କୋଠରୀ ନାହିଁ" + "ଆପ୍‌ ତାଲିକା" + "ବ୍ୟକ୍ତିଗତ ଆପ୍ ତାଲିକା" + "କାର୍ଯ୍ୟକାରୀ ଆପ୍‌ ତାଲିକା" + "ହୋମ୍" + "ବାହାର କରନ୍ତୁ" + "ଅନଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ" + "ଆପ୍‌ ସୂଚନା" + "ଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ" + "ଶର୍ଟକଟ୍‍ ଇନଷ୍ଟଲ୍‌ କରନ୍ତୁ" + "ୟୁଜରଙ୍କ ବିନା ହସ୍ତକ୍ଷେପରେ ଶର୍ଟକଟ୍‌ ଯୋଡ଼ିବାକୁ ଆପକୁ ଅନୁମତି ଦିଏ।" + "ହୋମ୍‌ ସେଟିଙ୍ଗ ଏବଂ ଶର୍ଟକଟ୍‌ ପଢ଼ନ୍ତୁ" + "ହୋମରେ ସେଟିଙ୍ଗ ପଢ଼ିବାକୁ ଆପ ଏବଂ ଶର୍ଟକଟକୁ ଅନୁମତି ଦିଏ।" + "ହୋମ୍‌ ସେଟିଙ୍ଗ ଏବଂ ଶର୍ଟକଟ୍‌ ଲେଖନ୍ତୁ" + "ହୋମରେ ସେଟିଙ୍ଗ ଏବଂ ଶର୍ଟକଟ୍‌ ପରିବର୍ତ୍ତନ କରିବାକୁ ଆପକୁ ଅନୁମତି ଦିଏ।" + "ଫୋନ୍‌ କଲ୍‌ କରିବାକୁ %1$sକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ" + "ୱିଜେଟ୍‌ ଲୋଡ୍‌ ହେବାରେ ସମସ୍ୟା ଅଛି" + "ସେଟ୍ ଅପ୍ କରନ୍ତୁ" + "ଏହା ଏକ ସିଷ୍ଟମ୍‌ ଆପ୍‌ ଅଟେ ଏବଂ ଏହା ଅନଇନଷ୍ଟଲ୍‌ କରାଯାଇ ପାରିବ ନାହିଁ।" + "ବେନାମୀ ଫୋଲ୍ଡର୍‌" + "%1$s ଅକ୍ଷମ କରାଗଲା" + + %1$s, ରେ %2$d ବିଜ୍ଞପ୍ତିଗୁଡ଼ିକ ଅଛି + %1$s, ରେ %2$d ବିଜ୍ଞପ୍ତି ଅଛି + + "ମୋଟ %2$dରୁ %1$d ନମ୍ବର ପୃଷ୍ଠା" + "%2$dରୁ %1$d ହୋମ୍‌ ସ୍କ୍ରୀନ୍" + "ନୂଆ ହୋମ୍‌ ସ୍କ୍ରୀନ୍‌ ପୃଷ୍ଠା" + "%2$d / %1$dର ଫୋଲ୍ଡର ଖୋଲାଗଲା" + "ଫୋଲ୍ଡର୍‌ ବନ୍ଦ କରିବାକୁ ଟାପ୍‌ କରନ୍ତୁ" + "ନାମ ବଦଳାଇବା ସେଭ୍ କରିବାକୁ ଟାପ୍‌ କରନ୍ତୁ" + "ଫୋଲ୍ଡର ବନ୍ଦ କରାଗଲା" + "ଫୋଲ୍ଡରର ନାମ %1$sକୁ ବଦଳାଗଲା" + "ଫୋଲ୍ଡର: %1$s" + "ୱିଜେଟ୍‌" + "ୱାଲପେପର୍‌" + "ହୋମ୍‌ ସେଟିଙ୍ଗ" + "ଆପଣଙ୍କ ଆଡମିନଙ୍କ ଦ୍ୱାରା ଅକ୍ଷମ କରାଯାଇଛି" + "ହୋମ୍‌ ସ୍କ୍ରୀନ୍ ବୁଲାଇବା ଅନୁମତି ଦିଅନ୍ତୁ" + "ଯେତେବେଳେ ଫୋନକୁ ବୁଲାଯାଇଥାଏ" + "ବିଜ୍ଞପ୍ତି ବିନ୍ଦୁଗୁଡ଼ିକ" + "ଅନ୍" + "ଅଫ୍‌" + "ବିଜ୍ଞପ୍ତି ଆକ୍ସେସ୍‌ ଆବଶ୍ୟକ ଅଟେ" + "ବିଜ୍ଞପ୍ତି ବିନ୍ଦୁ ଦେଖାଇବାକୁ, %1$s ପାଇଁ ଆପ୍‌ ବିଜ୍ଞପ୍ତି ଅନ୍‌ କରନ୍ତୁ" + "ସେଟିଙ୍ଗ ପରିବର୍ତ୍ତନ କରନ୍ତୁ" + "ବିଜ୍ଞପ୍ତି ଡଟ୍‌ଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ" + "ହୋମ୍‌ ସ୍କ୍ରୀନରେ ଆଇକନ୍‌କୁ ଯୋଡ଼ନ୍ତୁ" + "ନୂଆ ଆପ୍‌ ପାଇଁ" + "ଆଇକନ୍‌ର ଆକାର ପରିବର୍ତ୍ତନ କରନ୍ତୁ" + "ହୋମ୍ ସ୍କ୍ରୀନ୍ ଉପରେ" + "ସିଷ୍ଟମ ଡିଫଲ୍ଟ ବ୍ୟବହାର କରନ୍ତୁ" + "ବର୍ଗାକାର" + "ବର୍ଗାକାରର ବୃତ୍ତ" + "ବୃତ୍ତ" + "ଟିଅରଡ୍ରପ୍‌" + "ଆଇକନ୍‌ ଆକାର ପରିବର୍ତ୍ତନ ଲାଗୁ କରୁଛି" + "ଅଜଣା" + "ବାହାର କରନ୍ତୁ" + "ସର୍ଚ୍ଚ କରନ୍ତୁ" + "ଏହି ଆପ୍‌ ଇନଷ୍ଟଲ୍‌ ହୋଇନାହିଁ" + "ଏହି ଆଇକନ୍‌ ପାଇଁ ଆପ୍‌ ଇନଷ୍ଟଲ୍‌ ହୋଇନାହିଁ। ଏହାକୁ ଆପଣ ଆପ୍‌ ପାଇଁ ବାହାର କରିପାରିବେ କିମ୍ୱା ସର୍ଚ୍ଚ କରି ପାରିବେ ଏବଂ ଏହାକୁ ମାନୁଆଲ୍‌ ଭାବରେ ଇନଷ୍ଟଲ୍‌ କରିପାରିବେ।" + "%1$s ଡାଉନଲୋଡ୍‌ ହେଉଛି, %2$s ସମ୍ପୂର୍ଣ୍ଣ" + "%1$s ଇନଷ୍ଟଲ୍‌ ହେବାକୁ ଅପେକ୍ଷା କରିଛି" + "%1$s ୱିଜେଟ୍‌" + "ହୋମ୍‌ ସ୍କ୍ରୀନରେ ଯୋଡ଼ନ୍ତୁ" + "ଆଇଟମ୍‌କୁ ଏଠାକୁ ଘୁଞ୍ଚାନ୍ତୁ" + "ହୋମ୍‌ ସ୍କ୍ରୀନରେ ଆଇଟମ୍‌ ଯୋଡ଼ାଗଲା" + "ଆଇଟମ୍‌ ବାହାର କରାଗଲା" + "ଆଇଟମ୍‌ ଘୁଞ୍ଚାନ୍ତୁ" + "ଧାଡ଼ି %1$s ସ୍ତମ୍ଭ %2$sକୁ ନିଅନ୍ତୁ" + "%1$s ସ୍ଥିତିକୁ ନିଅନ୍ତୁ" + "ପସନ୍ଦର ସ୍ଥିତି %1$sକୁ ନିଅନ୍ତୁ" + "ଆଇଟମ୍‌ ଘୁଞ୍ଚେଇ ଦିଆଗଲା" + "ଏହି ଫୋଲ୍ଡରରେ ଯୋଡ଼ନ୍ତୁ: %1$s" + "%1$s ସହିତ ଫୋଲ୍ଡରରେ ଯୋଡ଼ନ୍ତୁ" + "ଫୋଲ୍ଡରରେ ଆଇଟମ୍‌ ଯୋଡ଼ାଗଲା" + "ଏହି ନାମରେ ଫୋଲ୍ଡର ତିଆରି କରନ୍ତୁ: %1$s" + "ଫୋଲ୍ଡର ତିଆରି କରାଗଲା" + "ହାମ୍‌ ସ୍କ୍ରୀନକୁ ଘୁଞ୍ଚାନ୍ତୁ" + "ଆକାର ବଦଳାନ୍ତୁ" + "ଚଉଡ଼ା ବଢ଼ାନ୍ତୁ" + "ଉଚ୍ଚତା ବଢ଼ାନ୍ତୁ" + "ଚଉଡ଼ା କମ୍‌ କରନ୍ତୁ" + "ଉଚ୍ଚତା କମ୍‌ କରନ୍ତୁ" + "ୱିଜେଟକୁ %1$s ଓସାର ଓ %2$s ଉଚ୍ଚରେ ପୁନଃଆକାର ଦିଆଗଲା" + "ଶର୍ଟକଟ୍‍" + + + "ଖାରଜ କରନ୍ତୁ" + "ବିଜ୍ଞପ୍ତି ଖାରଜ କରାଗଲା" + "ବ୍ୟକ୍ତିଗତ" + "କାମ" + "ୱର୍କ ପ୍ରୋଫାଇଲ୍‌" + "ଏଠାରେ କାମ ଆପ୍‌ ଖୋଜନ୍ତୁ" + "ପ୍ରତ୍ୟେକ କାଯ୍ୟକାରୀ ଆପ୍‌ର ଗୋଟିଏ ବ୍ୟାଜ୍ (ଚିହ୍ନ) ଅଛି, ଯାହାକୁ ଆପଣଙ୍କ ସଂସ୍ଥା ସୁରକ୍ଷିତ ରଖିଥାଏ। ସହଜରେ ଆକ୍ସେସ୍ କରିବା ପାଇଁ ଆପ୍‌କୁ ହୋମ୍ ସ୍କ୍ରୀନ୍ ଉପରକୁ ଆଣନ୍ତୁ।" + "ଆପଣଙ୍କ ସଂସ୍ଥା ଦ୍ୱାରା ପରିଚାଳିତ" + "ବିଜ୍ଞପ୍ତି ଓ ଆପ୍‌ଗୁଡ଼ିକ ବନ୍ଦ ଅଛି" + "ବନ୍ଦ କରନ୍ତୁ" + "ବନ୍ଦ ହୋଇଯାଇଛି" + diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml new file mode 100644 index 0000000000..c0778690ad --- /dev/null +++ b/res/values-pa-rIN/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "ਦਫ਼ਤਰ" + "ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ।" + "ਐਪ ਉਪਲਬਧ ਨਹੀਂ ਹੈ" + "ਡਾਊਨਲੋਡ ਕੀਤਾ ਐਪ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਅਸਮਰਥਿਤ" + "ਵਿਜੇਟ ਸੁਰੱਖਿਅਤ ਮੋਡ ਵਿੱਚ ਅਸਮਰਥਿਤ" + "ਸ਼ਾਰਟਕੱਟ ਉਪਲਬਧ ਨਹੀਂ ਹੈ" + "ਹੋਮ ਸਕ੍ਰੀਨ" + "ਵਿਉਂਂਤੀ ਕਾਰਵਾਈਆਂ" + "ਇੱਕ ਵਿਜੇਟ ਚੁਣਨ ਲਈ ਛੋਹਵੋT & ਹੋਲਡ ਕਰੋ।" + "ਇੱਕ ਵਿਜੇਟ ਚੁਣਨ ਲਈ ਜਾਂ ਵਿਉਂਂਤੀ ਕਾਰਵਾਈਆਂ ਵਰਤਣ ਲਈ ਦੋ ਵਾਰ ਟੈਪ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।" + "%1$d × %2$d" + "%1$d ਚੌੜਾਈ ਅਤੇ %2$d ਲੰਬਾਈ" + "ਹੱਥੀਂ ਰੱਖਣ ਲਈ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾਈ ਰੱਖੋ" + "ਸਵੈਚਲਿਤ ਤਰੀਕੇ ਨਾਲ ਸ਼ਾਮਲ ਕਰੋ" + "ਐਪਾਂ ਖੋਜੋ" + "ਐਪਾਂ ਨੂੰ ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ..." + "\"%1$s\" ਨਾਲ ਮੇਲ ਖਾਂਦੀਆਂ ਕੋਈ ਐਪਾਂ ਨਹੀਂ ਮਿਲੀਆਂ" + "ਹੋਰ ਐਪਾਂ ਖੋਜੋ" + "ਸੂਚਨਾਵਾਂ" + "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਸਪੱਰਸ਼ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ।" + "ਕੋਈ ਸ਼ਾਰਟਕੱਟ ਚੁਣਨ ਲਈ ਡਬਲ ਟੈਪ ਕਰਕੇ ਦਬਾਈ ਰੱਖੋ ਜਾਂ ਵਿਉਂਤੀਆਂ ਕਾਰਵਾਈਆਂ ਵਰਤੋ।" + "ਇਸ ਹੋਮ ਸਕ੍ਰੀਨ ਲਈ ਹੋਰ ਖਾਲੀ ਸਥਾਨ ਨਹੀਂ ਹੈ।" + "ਮਨਪਸੰਦ ਟ੍ਰੇ ਵਿੱਚ ਹੋਰ ਖਾਲੀ ਸਥਾਨ ਨਹੀਂ।" + "ਐਪ ਸੂਚੀ" + "ਨਿੱਜੀ ਐਪਾਂ ਦੀ ਸੂਚੀ" + "ਕਾਰਜ-ਸਥਾਨ ਸੰਬੰਧੀ ਐਪਾਂ ਦੀ ਸੂਚੀ" + "ਹੋਮ" + "ਹਟਾਓ" + "ਅਣਸਥਾਪਤ ਕਰੋ" + "ਐਪ ਜਾਣਕਾਰੀ" + "ਸਥਾਪਤ ਕਰੋ" + "ਸ਼ਾਰਟਕੱਟ ਸਥਾਪਤ ਕਰੋ" + "ਇੱਕ ਐਪ ਨੂੰ ਵਰਤੋਂਕਾਰ ਦੇ ਦਖ਼ਲ ਤੋਂ ਬਿਨਾਂ ਸ਼ਾਰਟਕੱਟ ਸ਼ਾਮਲ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" + "ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਪੜ੍ਹੋ" + "ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਪੜ੍ਹਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" + "ਹੋਮ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਲਿਖੋ" + "ਐਪ ਨੂੰ ਹੋਮ ਵਿੱਚ ਸੈਟਿੰਗਾਂ ਅਤੇ ਸ਼ਾਰਟਕੱਟ ਬਦਲਣ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ।" + "%1$s ਨੂੰ ਫ਼ੋਨ ਕਾਲਾਂ ਕਰਨ ਦੀ ਆਗਿਆ ਨਹੀਂ ਹੈ" + "ਵਿਜੇਟ ਲੋਡ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ" + "ਸਥਾਪਤ ਕਰੋ" + "ਇਹ ਇੱਕ ਸਿਸਟਮ ਐਪ ਹੈ ਅਤੇ ਇਸਨੂੰ ਅਣਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।" + "ਬਿਨਾਂ ਨਾਮ ਦਿੱਤਾ ਫੋਲਡਰ" + "%1$s ਨੂੰ ਅਯੋਗ ਬਣਾਇਆ ਗਿਆ" + + %1$s, ਦੀ %2$d ਸੂਚਨਾ + %1$s, ਦੀਆਂ %2$d ਸੂਚਨਾਵਾਂ + + "ਸਫ਼ਾ %2$d ਦਾ %1$d" + "ਹੋਮ ਸਕ੍ਰੀਨ %2$d ਦੀ %1$d" + "ਨਵਾਂ ਹੋਮ ਸਕ੍ਰੀਨ ਸਫ਼ਾ" + "ਫੋਲਡਰ ਖੋਲ੍ਹਿਆ, %1$d ਬਾਇ %2$d" + "ਫੋਲਡਰ ਬੰਦ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ" + "ਬਦਲੇ ਗਏ ਨਾਮ ਨੂੰ ਰੱਖਿਅਤ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ" + "ਫੋਲਡਰ ਬੰਦ ਕੀਤਾ" + "ਫੋਲਡਰ ਨੂੰ %1$s ਮੁੜ ਨਾਮ ਦਿੱਤਾ ਗਿਆ" + "ਫੋਲਡਰ: %1$s" + "ਵਿਜੇਟ" + "ਵਾਲਪੇਪਰ" + "ਹੋਮ ਸੈਟਿੰਗਾਂ" + "ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਈ ਗਈ" + "ਹੋਮ ਸਕ੍ਰੀਨ ਨੂੰ ਘੁੰਮਾਉਣ ਦੀ ਆਗਿਆ ਦਿਓ" + "ਜਦੋਂ ਫ਼ੋਨ ਘੁੰਮਾਇਆ ਜਾਂਦਾ ਹੈ" + "ਸੂਚਨਾ ਬਿੰਦੂ" + "ਚਾਲੂ" + "ਬੰਦ" + "ਸੂਚਨਾ ਪਹੁੰਚ ਲੋੜੀਂਦੀ ਹੈ" + "ਸੂਚਨਾ ਬਿੰਦੂਆਂ ਦਿਖਾਉਣ ਲਈ, %1$s ਲਈ ਐਪ ਸੂਚਨਾਵਾਂ ਚਾਲੂ ਕਰੋ" + "ਸੈਟਿੰਗਾਂ ਬਦਲੋ" + "ਸੂਚਨਾ ਬਿੰਦੂ ਦਿਖਾਓ" + "ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਪ੍ਰਤੀਕ ਸ਼ਾਮਲ ਕਰੋ" + "ਨਵੀਆਂ ਐਪਾਂ ਲਈ" + "ਪ੍ਰਤੀਕ ਦੀ ਆਕ੍ਰਿਤੀ ਬਦਲੋ" + "ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ" + "ਸਿਸਟਮ ਦੀ ਪੂਰਵ-ਨਿਰਧਾਰਤ ਸੈਟਿੰਗ ਵਰਤੋ" + "ਵਰਗ" + "ਵਰਗਾਕਾਰ-ਚੱਕਰ" + "ਚੱਕਰ" + "ਹੰਝੂ ਦੀ ਬੂੰਦ" + "ਪ੍ਰਤੀਕ ਦੀ ਆਕ੍ਰਿਤੀ ਵਿੱਚ ਤਬਦੀਲੀਆਂ ਨੂੰ ਲਾਗੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" + "ਅਗਿਆਤ" + "ਹਟਾਓ" + "ਖੋਜੋ" + "ਇਹ ਐਪ ਇੰਸਟੌਲ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ।" + "ਇਸ ਪ੍ਰਤੀਕ ਲਈ ਐਪ ਸਥਾਪਤ ਨਹੀਂ ਕੀਤਾ ਹੋਇਆ ਹੈ। ਤੁਸੀਂ ਇਸਨੂੰ ਹਟਾ ਸਕਦੇ ਹੋ ਜਾਂ ਐਪ ਖੋਜ ਸਕਦੇ ਹੋ ਅਤੇ ਇਸਨੂੰ ਮੈਨੂਅਲੀ ਸਥਾਪਤ ਕਰ ਸਕਦੇ ਹੋ।" + "%1$s ਡਾਉਨਲੋਡ ਹੋਰ ਰਿਹਾ ਹੈ, %2$s ਸੰਪੂਰਣ" + "%1$s ਸਥਾਪਤ ਕਰਨ ਦੀ ਉਡੀਕ ਕਰ ਰਿਹਾ ਹੈ" + "%1$s ਵਿਜੇਟ" + "ਹੋਮ ਸਕ੍ਰੀਨ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ" + "ਆਈਟਮ ਨੂੰ ਇੱਥੇ ਮੂਵ ਕਰੋ" + "ਆਈਟਮ ਨੂੰ ਹੋਮ ਸਕ੍ਰੀਨ ਵਿੱਚ ਜੋੜਿਆ ਗਿਆ" + "ਅਈਟਮ ਹਟਾਈ ਗਈ" + "ਆਈਟਮ ਨੂੰ ਮੂਵ ਕਰੋ" + "ਕਤਾਰ %1$s ਕਾਲਮ %2$s ਵਿੱਚ ਮੂਵ ਕਰੋ" + "ਸਥਿਤੀ %1$s ਵਿੱਚ ਮੂਵ ਕਰੋ" + "ਮਨਪਸੰਦ ਸਥਿਤੀ %1$s ਵਿੱਚ ਮੂਵ ਕਰੋ" + "ਆਈਟਮ ਮੂਵ ਕੀਤੀ ਗਈ" + "ਇਸ ਫੋਲਡਰ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ: %1$s" + "%1$s ਦੇ ਨਾਲ ਫੋਲਡਰ ਵਿੱਚ ਸ਼ਾਮਲ ਕਰੋ" + "ਆਈਟਮ ਨੂੰ ਫੋਲਡਰ ਵਿੱਚ ਜੋੜਿਆ ਗਿਆ" + "ਇਸਦੇ ਨਾਲ ਫੋਲਡਰ ਬਣਾਓ: %1$s" + "ਫੋਲਡਰ ਬਣਾਇਆ ਗਿਆ" + "ਹੋਮ ਸਕ੍ਰੀਨ ਵਿੱਚ ਮੂਵ ਕਰੋ" + "ਮੁੜ ਆਕਾਰ ਦਿਓ" + "ਚੌੜਾਈ ਵਧਾਓ" + "ਉਂਚਾਈ ਵਧਾਓ" + "ਚੌੜਾਈ ਘਟਾਓ" + "ਉਂਚਾਈ ਘਟਾਓ" + "ਵਿਜੈਟ ਨੂੰ ਚੌੜਾਈ %1$s ਉਂਚਾਈ %2$s ਨੂੰ ਮੁੜ ਆਕਾਰ ਦਿੱਤਾ" + "ਸ਼ਾਰਟਕੱਟ" + "%2$s ਲਈ %1$d ਸ਼ਾਰਟਕੱਟ" + "%3$s ਲਈ %1$d ਸ਼ਾਰਟਕੱਟ ਅਤੇ %2$d ਸੂਚਨਾਵਾਂ" + "ਖਾਰਜ ਕਰੋ" + "ਸੂਚਨਾ ਖਾਰਜ ਕੀਤੀ ਗਈ" + "ਨਿੱਜੀ" + "ਕਾਰਜ-ਸਥਾਨ" + "ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ" + "ਕਾਰਜ-ਸਥਾਨ ਐਪਾਂ ਇੱਥੇ ਲੱਭੋ" + "ਹਰੇਕ ਕਾਰਜ-ਸਥਾਨ ਐਪ ਦਾ ਇੱਕ ਬੈਜ ਹੁੰਦਾ ਹੈ ਅਤੇ ਉਸਨੂੰ ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਸੁਰੱਖਿਅਤ ਰੱਖਿਆ ਜਾਂਦਾ ਹੈ। ਵਧੇਰੇ ਆਸਾਨ ਪਹੁੰਚ ਲਈ ਐਪਾਂ ਨੂੰ ਹੋਮ ਸਕ੍ਰੀਨ \'ਤੇ ਲਿਜਾਓ।" + "ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਪ੍ਰਬੰਧਿਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ" + "ਸੂਚਨਾਵਾਂ ਅਤੇ ਐਪਾਂ ਬੰਦ ਹਨ" + "ਬੰਦ ਕਰੋ" + "ਬੰਦ ਕੀਤਾ ਗਿਆ" + diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index 02424031bf..237e5190af 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -81,6 +81,8 @@ "ਵਾਲਪੇਪਰ" "ਹੋਮ ਸੈਟਿੰਗਾਂ" "ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਦੁਆਰਾ ਅਯੋਗ ਬਣਾਈ ਗਈ" + "ਹੋਮ ਸਕ੍ਰੀਨ ਨੂੰ ਘੁੰਮਾਉਣ ਦੀ ਆਗਿਆ ਦਿਓ" + "ਜਦੋਂ ਫ਼ੋਨ ਘੁੰਮਾਇਆ ਜਾਂਦਾ ਹੈ" "ਸੂਚਨਾ ਬਿੰਦੂ" "ਚਾਲੂ" "ਬੰਦ" @@ -128,8 +130,8 @@ "ਉਂਚਾਈ ਘਟਾਓ" "ਵਿਜੈਟ ਨੂੰ ਚੌੜਾਈ %1$s ਉਂਚਾਈ %2$s ਨੂੰ ਮੁੜ ਆਕਾਰ ਦਿੱਤਾ" "ਸ਼ਾਰਟਕੱਟ" - "%2$s ਲਈ %1$d ਸ਼ਾਰਟਕੱਟ" - "%3$s ਲਈ %1$d ਸ਼ਾਰਟਕੱਟ ਅਤੇ %2$d ਸੂਚਨਾਵਾਂ" + + "ਖਾਰਜ ਕਰੋ" "ਸੂਚਨਾ ਖਾਰਜ ਕੀਤੀ ਗਈ" "ਨਿੱਜੀ" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 558fab2590..65de77703c 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -83,6 +83,8 @@ "Tapety" "Ustawienia strony głównej" "Funkcja wyłączona przez administratora" + "Zezwalaj na obrót ekranu głównego" + "Po obróceniu telefonu" "Plakietki z powiadomieniami" "Włączono" "Wyłączono" @@ -130,8 +132,8 @@ "Zmniejsz wysokość" "Szerokość i wysokość widżetu zmieniła się na %1$s x %2$s" "Skróty" - "Skróty aplikacji %2$s: %1$d" - "Skróty (%1$d) i powiadomienia (%2$d) aplikacji %3$s" + + "Odrzuć" "Powiadomienie odrzucone" "Osobiste" diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 0d3224d39d..48dcebb425 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -50,7 +50,7 @@ "Ecrã principal" "Remover" "Desinstalar" - "Inf. da aplicação" + "Info. da aplicação" "Instalar" "instalar atalhos" "Permite a uma aplicação adicionar atalhos sem a intervenção do utilizador." @@ -81,6 +81,8 @@ "Imagens de fundo" "Definições da página inicial" "Desativada pelo gestor" + "Permitir rotação do ecrã principal" + "Quando o telemóvel é rodado" "Pontos de notificação" "Ativada" "Desativada" @@ -128,8 +130,8 @@ "Diminuir altura" "Widget redimensionado para a largura %1$s, altura %2$s" "Atalhos" - "%1$d atalhos para a aplicação %2$s" - "%1$d atalhos e %2$d notificações para a aplicação %3$s" + + "Ignorar" "Notificação ignorada" "Pessoal" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index 73dad35bbb..25bde0add8 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -79,8 +79,10 @@ "Pasta: %1$s" "Widgets" "Planos de fundo" - "Configurações da página inicial" + "Configurações da tela inicial" "Desativado pelo administrador" + "Permitir rotação da tela inicial" + "Quando o smartphone for girado" "Pontos de notificação" "Ativado" "Desativado" @@ -128,8 +130,8 @@ "Diminuir altura" "Widget redimensionado para a largura %1$s, altura %2$s" "Atalhos" - "%1$d atalhos para %2$s" - "%1$d atalhos e %2$d notificações para o app %3$s" + + "Dispensar" "Notificação dispensada" "Pessoais" diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index 500512ac31..1af37eb709 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -82,6 +82,8 @@ "Imagini de fundal" "Setări pentru ecranul de pornire" "Dezactivată de administrator" + "Permiteți rotirea ecranului de pornire" + "Când telefonul este rotit" "Puncte de notificare" "Activat" "Dezactivat" diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index d04ca5c04a..74809dde43 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -83,15 +83,17 @@ "Обои" "Настройки главного экрана" "Функция отключена администратором" + "Разрешить поворачивать главный экран" + "Когда телефон повернут" "Значки уведомлений" - "ВКЛ" - "ВЫКЛ" + "Вкл." + "Выкл." "Нет доступа к уведомлениям" "Чтобы показывать значки уведомлений, включите уведомления в приложении \"%1$s\"" "Изменить настройки" "Показывать значки уведомлений" "Добавлять значки" - "Добавлять значки установленных приложений на главный экран." + "Добавлять значки установленных приложений на главный экран" "Изменить форму значков" "на главном экране" "Использовать системные настройки по умолчанию" @@ -130,8 +132,8 @@ "Уменьшить высоту" "Изменен размер виджета: до %1$s в ширину и %2$s в высоту" "Ярлыки" - "Количество ярлыков для приложения \"%2$s\": %1$d" - "Количество ярлыков для приложения \"%3$s\": %1$d. Количество уведомлений: %2$d." + + "Закрыть" "Уведомление закрыто" "Личные" diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml new file mode 100644 index 0000000000..10835dc5ce --- /dev/null +++ b/res/values-si-rLK/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "කාර්යාලය" + "යෙදුම ස්ථාපනය කර නැත." + "යෙදුම නොතිබේ" + "ආරක්ෂිත ආකාරය තුළ බාගන්න ලද යෙදුම් අබල කරන්න" + "සුරක්ෂිත ආකාරය තුළ විජටය අබල කරන ලදි" + "කෙටි මග ලබා ගත නොහැකිය" + "මුල් පිටු තිරය" + "අභිරුචි ක්‍රියා" + "විජට් එක ස්පර්ශ කර අහුලා ගැනීමට අල්ලාගෙන සිටින්න." + "විජට් එකක් අහුලා ගැනීමට හෝ අභිරුචි ක්‍රියා කිරීමට ඩබල් ටැප් කර අල්ලා ගෙන සිටින්න." + "%1$d × %2$d" + "පළල %1$d උස %2$d" + "අතින් ස්ථානගත කිරීමට ස්පර්ශ කර අල්ලාගෙන සිටින්න" + "ස්වයංක්‍රියව එක් කරන්න" + "යෙදුම් සොයන්න" + "යෙදුම් පූරණය වෙමින්…" + "\"%1$s\" සමග ගැළපෙන යෙදුම් හමු නොවිණි" + "තව යෙදුම් සඳහා සොයන්න" + "දැනුම්දීම්" + "කෙටි මගක් තෝරා ගැනීමට ස්පර්ශ කර අල්ලාගෙන සිටින්න." + "විජට් එකක් තෝරා ගැනීමට හෝ අභිරුචි භාවිත කිරීමට දෙවරක් තට්ටු කර අල්ලා ගෙන සිටින්න." + "මෙම මුල් පිටු තිරය මත තවත් අවසර නැත." + "ප්‍රියතම දෑ ඇති තැටියේ තවත් ඉඩ නොමැත" + "යෙදුම් ලැයිස්තුව" + "පෞද්ගලික යෙදුම් ලැයිස්තුව" + "වැඩ යෙදුම් ලැයිස්තුව" + "මුල් පිටුව" + "ඉවත් කරන්න" + "අස්ථාපනය කරන්න" + "යෙදුම් තොරතුරු" + "ස්ථාපනය කරන්න" + "කෙටිමං ස්ථාපනය කරන්න" + "පරිශීලක මැදිහත්වීමෙන් තොරව කෙටිමං එක් කිරීමට යෙදුමකට අවසර දෙයි." + "මුල් පිටු සැකසීම් සහ කෙටිමං කියවන්න" + "මුල් පිටුවේ ඇති සැකසීම් සහ කෙටිමං කියවීමට යෙදුමකට අවසර දෙයි." + "මුල් පිටු සැකසීම් සහ කෙටිමං ලියන්න" + "මුල් පිටුවේ සැකසීම් සහ කෙටිමං ඉවත් කිරීමට යෙදුමට අවසර දෙයි." + "%1$s හට දුරකථන ඇමතුම් සිදු කිරීමට ඉඩ නොදේ" + "ගැටලු පූරණ විජට් එක" + "ස්ථාපනය කරන්න" + "මෙය පද්ධති යෙදුමක් වන අතර අස්ථාපනය කළ නොහැක." + "නම් නොකළ ෆෝල්ඩරය" + "%1$s අබල කෙරිණි" + + %1$s, දැනුම්දීම් %2$dක් ඇත + %1$s, දැනුම්දීම් %2$dක් ඇත + + "%2$d හි %1$d පිටුව" + "මුල් පිටු තිරය %2$d හි %1$d" + "නව මුල් පිටුව" + "ෆෝල්ඩරය විවෘත විය, %1$d හි %2$d" + "ෆෝල්ඩරය වැසීමට තට්ටු කරන්න" + "යළි නම් කිරීම සුරැකීමට තට්ටු කරන්න" + "ෆෝල්ඩරය වසා ඇත" + "%1$s වෙත ෆෝල්ඩරය නැවත නම් කෙරිණි" + "ෆෝල්ඩරය: %1$s" + "විජට්" + "වෝල්පේපර" + "Home සැකසීම්" + "ඔබගේ පරිපාලක විසින් අබල කරන ලදී" + "මුල් පිටු තිරය කරකැවීමට ඉඩ දෙන්න" + "දුරකථනය කරකවන විට" + "දැනුම්දීම් තිත්" + "ක්‍රියාත්මකයි" + "ක්‍රියාවිරහිතයි" + "දැනුම්දීම් ප්‍රවේශය අවශ්‍යයි" + "දැනුම්දීම් තිත් පෙන්වීමට, %1$s සඳහා යෙදුම් දැනුම්දීම් සබල කරන්න" + "සැකසීම් වෙනස් කරන්න" + "දැනුම් දීමේ තිත් පෙන්වන්න" + "මුල් පිටු තිරය වෙත අයිකනය එක් කරන්න" + "නව යෙදුම් සඳහා" + "නිරූපක හැඩය වෙනස් කරන්න" + "මුල් පිටු තිරය මත" + "පද්ධති පෙරනිමි භාවිත කරන්න" + "සමචතුරස්‍රය" + "හතරැස් කවය" + "කවය" + "කඳුළු බිංදුව" + "නිරූපක හැඩය වෙනස් කිරීම් යොදමින්" + "නොදනී" + "ඉවත් කරන්න" + "සොයන්න" + "මෙම යෙදුම ස්ථාපනය කර නොමැත" + "මෙම නිරුපකයට යෙදුම ස්ථාපනය කර නොමැත. ඔබට එය ඉවත් කළ හැක, හෝ යෙදුම් සඳහා සොයන්න සහ අතින් ස්ථාපනය කරන්න." + "%1$s බාගත කරමින්, %2$s සම්පූර්ණයි" + "%1$s ස්ථාපනය කිරීමට බලා සිටිමින්" + "%1$s විජට්" + "මුල් තිරය වෙත එක් කරන්න" + "මෙතනට අයිතමය ගෙන එන්න" + "අයිතමය මුල් තිරය වෙත එකතු කරන ලදි" + "අයිතමය ඉවත් කරන ලදි" + "අයිතමය ගෙනයන්න" + "පේළිය %1$s තීරුව %2$s වෙත ගෙන යන්න" + "%1$s ස්ථානය වෙත ගෙන යන්න" + "ප්‍රියතම ස්ථානය %1$s වෙත ගෙන යන්න" + "අයිතමය ගෙන යන ලදි" + "ෆෝල්ඩරය එක් කරන්න: %1$s" + "%1$s සමඟ ෆෝල්ඩරය වෙත එක් කරන්න" + "අයිතමය ෆෝඩරය වෙතට එක් කරන ලදි" + "මේ සමග ෆෝල්ඩරය සාදන්න: %1$s" + "ෆෝල්ඩරය සාදන ලදි" + "මුල් තිරය වෙත ගෙන යන්න" + "නැවත ප්‍රමාණගත කිරීම" + "පළල වැඩි කරන්න" + "උස වැඩි කරන්න" + "පළල අඩු කරන්න" + "උස අඩු කරන්න" + "විජට් පළල %1$s උස %2$s වෙත ප්‍රමාණකරණය කරන ලදි" + "කෙටිමං" + "%2$s සඳහා කෙටි මං %1$d" + "%3$s සඳහා කෙටි මං %1$dක් සහ දැනුම්දීම් %2$dක්" + "ඉවතලන්න" + "දැනුම්දීම ඉවතලන ලදී" + "පුද්ගලික" + "කාර්යාලය" + "කාර්යාල පැතිකඩ" + "මෙහි කාර්යාල යෙදුම් සොයා ගන්න" + "සෑම කාර්යාල යෙදුමකම ලාංඡනයක් ඇත ඇති අතර එය ඔබේ සංවිධානය මගින් සුරක්ෂිතව තබා ගනී. වඩාත් පහසු ප්‍රවේශයකට යෙදුම් ඔබේ මුල් පිටු තිරය වෙත ගෙන යන්න." + "ඔබේ සංවිධානය විසින් කළමනාකරණය කරනු ලැබේ" + "දැනුම්දීම් සහ යෙදුම් ක්‍රියාවිරහිතයි" + "වසන්න" + "වසා ඇත" + diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index 7a4771e611..10835dc5ce 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -81,6 +81,8 @@ "වෝල්පේපර" "Home සැකසීම්" "ඔබගේ පරිපාලක විසින් අබල කරන ලදී" + "මුල් පිටු තිරය කරකැවීමට ඉඩ දෙන්න" + "දුරකථනය කරකවන විට" "දැනුම්දීම් තිත්" "ක්‍රියාත්මකයි" "ක්‍රියාවිරහිතයි" diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 4d90dee09f..cbffd1b25b 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -81,8 +81,10 @@ "Priečinok: %1$s" "Miniaplikácie" "Tapety" - "Nastavenia služby Home" + "Nastavenia Home" "Zakázané vaším správcom" + "Povoliť otáčanie plochy" + "Pri otočení telefónu" "Bodky upozornení" "Zapnuté" "Vypnuté" @@ -130,8 +132,8 @@ "Znížiť výšku" "Veľkosť miniaplikácie bola zmenená na %1$s x %2$s (šírka x výška)" "Skratky" - "Počet skratiek aplikácie %2$s: %1$d" - "Odkazy (%1$d) a upozornenia (%2$d) pre aplikáciu %3$s" + + "Zavrieť" "Upozornenie bolo zavreté" "Osobné" diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 82b79125b4..df934cd2fd 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -83,6 +83,8 @@ "Ozadja" "Nastavitve začetnega zaslona" "Onemogočil skrbnik." + "Omogočanje sukanja začetnega zaslona" + "Ko se telefon zasuka" "Obvestilne pike" "Vklopljeno" "Izklopljeno" @@ -130,8 +132,8 @@ "Zmanjšanje višine" "Velikost pripomočka je bila spremenjena na %1$s širine in %2$s višine" "Bližnjice" - "Št. bližnjic za aplikacijo %2$s: %1$d" - "Bližnjice (%1$d) in obvestila (%2$d) aplikacije %3$s" + + "Opusti" "Obvestilo je bilo opuščeno" "Osebno" diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml new file mode 100644 index 0000000000..82cc42a169 --- /dev/null +++ b/res/values-sq-rAL/strings.xml @@ -0,0 +1,146 @@ + + + + + "Nisësi3" + + "Puna" + "Aplikacioni nuk është i instaluar." + "Aplikacioni nuk mundësohet" + "Aplikacioni i shkarkuar është i çaktivizuar në modalitetin e sigurt" + "Miniaplikacionet janë të çaktivizuara në modalitetin e sigurt" + "Shkurtorja nuk është e disponueshme" + "Ekrani bazë" + "Veprimet e personalizuara" + "Prek dhe mbaj shtypur për të zgjedhur një miniaplikacion." + "Prek dy herë dhe mbaj shtypur për të zgjedhur një miniaplikacion ose për të përdorur veprimet e personalizuara." + "%1$d × %2$d" + "%1$d i gjerë me %2$d i lartë" + "Prek dhe mbaj të shtypur për të vendosur në mënyrë manuale" + "Shto automatikisht" + "Kërko për aplikacione" + "Po ngarkon aplikacionet..." + "Nuk u gjet asnjë aplikacion që përputhet me \"%1$s\"" + "Kërko për më shumë aplikacione" + "Njoftimet" + "Prek dhe mbaj prekur për të zgjedhur një shkurtore." + "Prek dy herë dhe mbaj prekur për të zgjedhur një shkurtore ose për të përdorur veprimet e personalizuara." + "Nuk ka më hapësirë në këtë ekran bazë." + "Nuk ka më hapësirë në tabakanë \"Të preferuarat\"" + "Lista e aplikacioneve" + "Lista e aplikacioneve personale" + "Lista e aplikacioneve të punës" + "Faqja kryesore" + "Hiqe" + "Çinstalo" + "Informacion mbi aplikacionin" + "Instalo" + "instalo shkurtore" + "Lejon një aplikacion të shtojë shkurtore pa ndërhyrjen e përdoruesit." + "lexo cilësimet dhe shkurtoret e ekranit bazë" + "Lejon aplikacionin të lexojë cilësimet dhe shkurtoret në ekranin bazë." + "shkruaj cilësimet dhe shkurtoret e ekranit bazë" + "Lejon aplikacionin të ndryshojë cilësimet dhe shkurtoret në ekranin bazë." + "%1$s nuk lejohet të kryejë telefonata" + "Problem në ngarkimin e miniaplikacionit" + "Konfiguro" + "Ky është aplikacion sistemi dhe nuk mund të çinstalohet." + "Dosje e paemërtuar" + "%1$s u çaktivizua" + + %1$s, ka %2$d njoftime + %1$s, ka %2$d njoftime + + "Faqja: %1$d nga gjithsej %2$d" + "Ekrani bazë: %1$d nga gjithsej %2$d" + "Faqja e ekranit të ri kryesor" + "Dosja u hap, %1$d me %2$d" + "Trokit për të mbyllur dosjen" + "Trokit për të ruajtur riemërtimin" + "Dosja u mbyll" + "Dosja u riemërtua në %1$s" + "Dosja: %1$s" + "Miniaplikacionet" + "Imazhet e sfondit" + "Cilësimet e Home" + "Çaktivizuar nga administratori" + "Lejo rrotullimin e ekranit kryesor" + "Kur telefoni rrotullohet" + "Pikat e njoftimeve" + "Aktiv" + "Joaktiv" + "Nevojitet qasja në njoftime" + "Për të shfaqur \"Pikat e njoftimeve\", aktivizo njoftimet e aplikacionit për %1$s" + "Ndrysho cilësimet" + "Shfaq pikat e njoftimeve" + "Shto ikonë në ekranin bazë" + "Për aplikacionet e reja" + "Ndrysho formën e ikonës" + "në ekranin bazë" + "Përdor parazgjedhjen e sistemit" + "Katror" + "Katror me kënde të rrumbullakëta" + "Rreth" + "Pikë loti" + "Po zbatohen ndryshimet e formës së ikonës" + "I panjohur" + "Hiq" + "Kërko" + "Aplikacioni nuk është i instaluar" + "Aplikacioni për këtë ikonë nuk është i instaluar. Mund ta heqësh ose të kërkosh aplikacionin dhe ta instalosh atë në mënyrë manuale." + "%1$s po shkarkohet, %2$s të përfunduara" + "%1$s po pret të instalohet" + "Miniaplikacionet e %1$s" + "Shto në Ekranin bazë" + "Zhvendose artikullin këtu" + "Artikulli u shtua tek ekrani bazë" + "Artikulli u hoq" + "Zhvendose artikullin" + "Zhvendos te rreshti %1$s, kolona %2$s" + "Zhvendos te pozicioni %1$s" + "Zhvendos te pozicioni %1$s i preferencave" + "Artikulli u zhvendos" + "Shto te dosja: %1$s" + "Shto te dosja me %1$s" + "Artikulli u shtua te dosja" + "Krijo një dosje me: %1$s" + "Dosja u krijua" + "Zhvendose në Ekranin bazë" + "Ndrysho madhësinë" + "Rrit gjerësinë" + "Rrit lartësinë" + "Zvogëlo gjerësinë" + "Zvogëlo lartësinë" + "Madhësia e miniaplikacionit u ndryshua me gjerësinë %1$s dhe lartësinë %2$s" + "Shkurtoret" + "%1$d shkurtesa për %2$s" + "%1$d shkurtore dhe %2$d njoftime për %3$s" + "Hiqe" + "Njoftimi u hoq" + "Personale" + "Punë" + "Profili i punës" + "Gjej këtu aplikacionet e punës" + "Secili aplikacion pune ka një distinktiv dhe mbahet i sigurt nga organizata jote. Zhvendosi aplikacionet e punës në ekranin tënd kryesor për qasje më të lehtë." + "Menaxhohet nga organizata jote" + "Njoftimet dhe aplikacionet janë joaktive" + "Mbyll" + "Mbyllur" + diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index a4ad7a0543..ef7cde70e5 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -81,6 +81,8 @@ "Imazhet e sfondit" "Cilësimet e Home" "Çaktivizuar nga administratori" + "Lejo rrotullimin e ekranit kryesor" + "Kur telefoni rrotullohet" "Pikat e njoftimeve" "Aktiv" "Joaktiv" @@ -92,7 +94,7 @@ "Për aplikacionet e reja" "Ndrysho formën e ikonës" "në ekranin bazë" - "Përdor parazgjedhjen e sisteit" + "Përdor parazgjedhjen e sistemit" "Katror" "Katror me kënde të rrumbullakëta" "Rreth" @@ -128,8 +130,8 @@ "Zvogëlo lartësinë" "Madhësia e miniaplikacionit u ndryshua me gjerësinë %1$s dhe lartësinë %2$s" "Shkurtoret" - "%1$d shkurtesa për %2$s" - "%1$d shkurtore dhe %2$d njoftime për %3$s" + + "Hiqe" "Njoftimi u hoq" "Personale" diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 3ae87f9e55..d4223a8a1e 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -82,6 +82,8 @@ "Позадине" "Подешавања почетног екрана" "Администратор је онемогућио" + "Дозволи ротацију почетног екрана" + "Када се телефон ротира" "Тачке за обавештења" "Укључено" "Искључено" @@ -129,8 +131,8 @@ "Смањи висину" "Величина виџета је промењена на ширину %1$s и висину %2$s" "Пречице" - "%1$d пречице(а) за %2$s" - "Пречице (%1$d) и обавештења (%2$d) за %3$s" + + "Одбаци" "Обавештење је одбачено" "Личне" diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 3c91c30b66..2fda5e24a6 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -79,8 +79,10 @@ "Mapp: %1$s" "Widgetar" "Bakgrunder" - "Inställningar för startsidan" + "Startinställningar" "Inaktiverat av administratören" + "Tillåt rotering av startskärmen" + "När mobilen vrids" "Aviseringsprickar" "På" "Av" @@ -128,8 +130,8 @@ "Minska höjden" "Widgetens storlek har ändrats till: bredd %1$s, höjd %2$s" "Genvägar" - "%1$d genvägar för %2$s" - "%3$s har %1$d genvägar och %2$d aviseringar" + + "Ignorera" "Aviseringen togs bort" "Privat" diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index 61d7f8bed3..5981b8684f 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -81,8 +81,10 @@ "Folda: %1$s" "Wijeti" "Mandhari" - "Mipangilio ya ukurasa wa mwanzo" + "Mipangilio ya mwanzo" "Imezimwa na msimamizi wako" + "Ruhusu kuzungusha skrini ya Kwanza" + "Simu inapozungushwa" "Vitone vya arifa" "Imewashwa" "Imezimwa" @@ -94,7 +96,7 @@ "Kwa ajili ya programu mpya" "Badilisha umbo la aikoni" "kwenye Skrini ya mwanzo" - "Tumia umbo chaguo-msingi la mfumo" + "Tumia umbo chaguomsingi la mfumo" "Mraba" "Mstatili wenye pembe duara" "Mduara" @@ -130,8 +132,8 @@ "Punguza urefu" "Wijeti imepunguzwa hadi upana %1$s urefu %2$s" "Njia za mkato" - "Njia %1$d za mkato za %2$s" - "Njia %1$d za mkato na arifa %2$d za %3$s" + + "Ondoa" "Arifa imeondolewa" "Binafsi" diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml index 1497b5a694..b211207587 100644 --- a/res/values-sw720dp/dimens.xml +++ b/res/values-sw720dp/dimens.xml @@ -15,9 +15,6 @@ --> - - 24dp - 8dp 64dp diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml new file mode 100644 index 0000000000..a51247c2de --- /dev/null +++ b/res/values-ta-rIN/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "பணியிடம்" + "பயன்பாடு நிறுவப்படவில்லை." + "பயன்பாடு இல்லை" + "இறக்கிய பயன்பாடு பாதுகாப்பு முறையில் முடக்கப்பட்டது" + "பாதுகாப்புப் பயன்முறையில் விட்ஜெட்கள் முடக்கப்பட்டுள்ளன" + "குறுக்குவழி இல்லை" + "முகப்புத் திரை" + "தனிப்பயன் செயல்கள்" + "விட்ஜெட்டைத் தேர்வுசெய்ய தொட்டுப் பிடிக்கவும்." + "விட்ஜெட்டைத் தேர்ந்தெடுக்க இருமுறை தட்டிப் பிடிக்கவும் அல்லது தனிப்பயன் செயல்களைப் பயன்படுத்தவும்." + "%1$d × %2$d" + "%1$d அகலத்திற்கு %2$d உயரம்" + "நீங்களே சேர்க்க, தொட்டுப் பிடித்திருக்கவும்" + "தானாகவே சேர்" + "பயன்பாடுகளில் தேடுக" + "பயன்பாடுகளை ஏற்றுகிறது…" + "\"%1$s\" உடன் பொருந்தும் பயன்பாடுகள் இல்லை" + "கூடுதல் பயன்பாடுகளைத் தேடு" + "அறிவிப்புகள்" + "ஷார்ட்கட்டைச் சேர்க்க, தொட்டு பிடித்திருக்கவும்." + "ஷார்ட்கட்டைச் சேர்க்க, இருமுறை தட்டிப் பிடித்திருக்கவும் (அ) தனிப்பயன் செயல்களைப் பயன்படுத்தவும்." + "முகப்புத் திரையில் இடமில்லை." + "பிடித்தவை ட்ரேயில் இடமில்லை" + "பயன்பாடுகளின் பட்டியல்" + "தனிப்பட்ட ஆப்ஸ் பட்டியல்" + "பணி ஆப்ஸ் பட்டியல்" + "முகப்பு" + "அகற்று" + "நிறுவல் நீக்கு" + "பயன்பாட்டுத் தகவல்" + "நிறுவு" + "குறுக்குவழிகளை நிறுவுதல்" + "பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளைச் சேர்க்கப் பயன்பாட்டை அனுமதிக்கிறது." + "முகப்பின் அமைப்பு மற்றும் குறுக்குவழிகளைப் படித்தல்" + "முகப்பில் உள்ள அமைப்பு மற்றும் குறுக்குவழிகளைப் படிக்க பயன்பாட்டை அனுமதிக்கிறது." + "முகப்பின் அமைப்பு மற்றும் குறுக்குவழிகளை எழுதுதல்" + "முகப்பில் உள்ள அமைப்பு மற்றும் குறுக்குவழிகளை மாற்ற பயன்பாட்டை அனுமதிக்கிறது." + "ஃபோன் அழைப்புகள் செய்ய, %1$s அனுமதிக்கப்படவில்லை" + "விட்ஜெட்டை ஏற்றுவதில் சிக்கல்" + "அமைவு" + "இது அமைப்பு பயன்பாடு என்பதால் நிறுவல் நீக்கம் செய்ய முடியாது." + "பெயரிடப்படாத கோப்புறை" + "%1$s முடக்கப்பட்டது" + + %1$s பயன்பாட்டில், %2$d அறிவிப்புகள் வந்துள்ளன + %1$s பயன்பாட்டில், %2$d அறிவிப்பு வந்துள்ளது + + "பக்கம் %1$d / %2$d" + "முகப்புத் திரை %1$d of %2$d" + "புதிய முகப்புத் திரை பக்கம்" + "திறக்கப்பட்டக் கோப்புறை, %1$d x %2$d" + "கோப்புறையை மூட, தட்டவும்" + "மாற்றிய பெயரைச் சேமிக்க, தட்டவும்" + "கோப்புறை மூடப்பட்டது" + "கோப்புறை %1$s என மறுபெயரிடப்பட்டது" + "கோப்புறை: %1$s" + "ஷார்ட்கட்ஸ்" + "வால்பேப்பர்கள்" + "முகப்பு அமைப்புகள்" + "உங்கள் நிர்வாகி முடக்கியுள்ளார்" + "முகப்புத் திரை சுழற்சியை அனுமதி" + "மொபைலைச் சுழற்றும் போது" + "அறிவிப்புப் புள்ளிகள்" + "ஆன்" + "முடக்கப்பட்டுள்ளது" + "அறிவிப்பிற்கான அணுகல் தேவை" + "அறிவிப்புப் புள்ளிகளைக் காட்ட, %1$s இன் பயன்பாட்டு அறிவிப்புகளை இயக்கவும்" + "அமைப்புகளை மாற்று" + "அறிவிப்புப் புள்ளிகளைக் காட்டு" + "முகப்புத் திரையில் ஐகானைச் சேர்" + "புதிய பயன்பாடுகளுக்கு" + "ஐகான் வடிவத்தை மாற்று" + "முகப்புத் திரையில்" + "அமைப்பின் இயல்புநிலையைப் பயன்படுத்து" + "சதுரம்" + "சதுரவட்டம்" + "வட்டம்" + "கண்ணீர்துளி" + "ஐகான் வடிவத்தை மாற்றுகிறது" + "தெரியாதது" + "அகற்று" + "தேடு" + "பயன்பாடு நிறுவப்படவில்லை" + "ஐகானுக்கான பயன்பாடு நிறுவப்படவில்லை. இதை அகற்றலாம் அல்லது பயன்பாட்டைத் தேடி கைமுறையாக நிறுவலாம்." + "%1$sஐப் பதிவிறக்குகிறது, %2$s முடிந்தது" + "%1$sஐ நிறுவுவதற்காகக் காத்திருக்கிறது" + "%1$s விட்ஜெட்டுகள்" + "முகப்புத் திரையில் சேர்" + "இங்கு நகர்த்து" + "முகப்புத் திரையில் சேர்க்கப்பட்டது" + "அகற்றப்பட்டது" + "நகர்த்து" + "%1$s வரிசை, %2$s நெடுவரிசைக்கு நகர்த்து" + "நிலை %1$sக்கு நகர்த்து" + "விரும்பும் நிலை %1$sக்கு நகர்த்து" + "உருப்படி நகர்த்தப்பட்டது" + "இந்தக் கோப்புறையில் சேர்க்கும்: %1$s" + "%1$s உள்ள கோப்புறையில் சேர்க்கும்" + "கோப்புறையில் உருப்படி சேர்க்கப்பட்டது" + "இதனுடன் கோப்புறையை உருவாக்கும்: %1$s" + "கோப்புறை உருவாக்கப்பட்டது" + "முகப்புத் திரைக்கு நகர்த்து" + "அளவு மாற்று" + "அகலத்தை அதிகரி" + "உயரத்தை அதிகரி" + "அகலத்தைக் குறை" + "உயரத்தைக் குறை" + "அகலம் %1$s மற்றும் உயரம் %2$sக்கு விட்ஜெட் அளவு மாற்றப்பட்டது" + "குறுக்குவழிகள்" + "%2$sக்கான %1$d குறுக்குவழிகள்" + "%3$s பயன்பாட்டிற்கான %1$d குறுக்குவழிகளும் %2$d அறிவிப்புகளும் உள்ளன" + "நிராகரி" + "அறிவிப்பு நிராகரிக்கப்பட்டது" + "தனிப்பட்டவை" + "பணி" + "பணி விவரம்" + "பணி ஆப்ஸை இங்கு காணலாம்" + "ஒவ்வொரு பணிப் பயன்பாடும் ஒரு பேட்ஜைக் கொண்டிருக்கும். இவை, ஆப்ஸ் உங்கள் நிறுவனத்தால் பாதுகாப்பாக வைக்கப்பட்டுள்ளன என்பதைக் குறிக்கின்றன. இந்த ஆப்ஸை எளிதாக அணுக, முகப்புத் திரைக்கு நகர்த்திக்கொள்ளவும்." + "உங்கள் நிறுவனம் நிர்வகிக்கிறது" + "ஆப்ஸும் அறிவிப்புகளும் ஆஃப் செய்யப்பட்டுள்ளன" + "மூடுக" + "மூடப்பட்டது" + diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index 13358c09ce..5ff5ecc44b 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -40,10 +40,8 @@ "\"%1$s\" உடன் பொருந்தும் பயன்பாடுகள் இல்லை" "கூடுதல் பயன்பாடுகளைத் தேடு" "அறிவிப்புகள்" - - - - + "ஷார்ட்கட்டைச் சேர்க்க, தொட்டு பிடித்திருக்கவும்." + "ஷார்ட்கட்டைச் சேர்க்க, இருமுறை தட்டிப் பிடித்திருக்கவும் (அ) தனிப்பயன் செயல்களைப் பயன்படுத்தவும்." "முகப்புத் திரையில் இடமில்லை." "பிடித்தவை ட்ரேயில் இடமில்லை" "பயன்பாடுகளின் பட்டியல்" @@ -52,7 +50,7 @@ "முகப்பு" "அகற்று" "நிறுவல் நீக்கு" - "ஆப்ஸ் தகவல்" + "பயன்பாட்டுத் தகவல்" "நிறுவு" "குறுக்குவழிகளை நிறுவுதல்" "பயனரின் அனுமதி இல்லாமல் குறுக்குவழிகளைச் சேர்க்கப் பயன்பாட்டை அனுமதிக்கிறது." @@ -83,6 +81,8 @@ "வால்பேப்பர்கள்" "முகப்பு அமைப்புகள்" "உங்கள் நிர்வாகி முடக்கியுள்ளார்" + "முகப்புத் திரை சுழற்சியை அனுமதி" + "மொபைலைச் சுழற்றும் போது" "அறிவிப்புப் புள்ளிகள்" "ஆன்" "முடக்கப்பட்டுள்ளது" @@ -130,8 +130,8 @@ "உயரத்தைக் குறை" "அகலம் %1$s மற்றும் உயரம் %2$sக்கு விட்ஜெட் அளவு மாற்றப்பட்டது" "குறுக்குவழிகள்" - "%2$sக்கான %1$d குறுக்குவழிகள்" - "%3$s பயன்பாட்டிற்கான %1$d குறுக்குவழிகளும் %2$d அறிவிப்புகளும் உள்ளன" + + "நிராகரி" "அறிவிப்பு நிராகரிக்கப்பட்டது" "தனிப்பட்டவை" diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml new file mode 100644 index 0000000000..bffb1a8700 --- /dev/null +++ b/res/values-te-rIN/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "కార్యాలయం" + "యాప్ ఇన్‌స్టాల్ చేయబడలేదు." + "యాప్ అందుబాటులో లేదు" + "డౌన్‌లోడ్ చేసిన యాప్ సురక్షిత మోడ్‌లో నిలిపివేయబడింది" + "సురక్షిత మోడ్‌లో విడ్జెట్‌లు నిలిపివేయబడ్డాయి" + "షార్ట్‌కట్ అందుబాటులో లేదు" + "హోమ్ స్క్రీన్" + "అనుకూల చర్యలు" + "విడ్జెట్‌ను ఎంచుకోవడానికి తాకి & నొక్కి పెట్టండి." + "విడ్జెట్‌ను ఎంచుకోవడానికి లేదా అనుకూల చర్యలను ఉపయోగించడానికి రెండుసార్లు నొక్కి, ఉంచండి." + "%1$d × %2$d" + "%1$d వెడల్పు X %2$d ఎత్తు" + "మాన్యువల్‌గా ఉంచడానికి నొక్కి &amp పట్టుకోండి" + "స్వయంచాలకంగా జోడించు" + "అప్లికేషన్‌లను శోధించండి" + "అప్లికేషన్‌లను లోడ్ చేస్తోంది…" + "\"%1$s\"కి సరిపోలే అప్లికేషన్‌లేవీ కనుగొనబడలేదు" + "మరిన్ని యాప్‌ల కోసం వెతుకు" + "నోటిఫికేషన్‌లు" + "షార్ట్‌కట్‌ని ఎంచుకోవడం కోసం నొక్కి, పట్టుకోండి." + "రెండుసార్లు నొక్కి, పట్టుకోవడం ద్వారా షార్ట్‌కట్‌ని ఎంచుకోండి లేదా అనుకూల చర్యలను ఉపయోగించండి." + "ఈ హోమ్ స్క్రీన్‌లో ఖాళీ లేదు." + "ఇష్టమైనవి ట్రేలో ఖాళీ లేదు" + "అనువర్తనాల జాబితా" + "వ్యక్తిగత యాప్‌ల జాబితా" + "కార్యాలయ యాప్‌ల జాబితా" + "హోమ్" + "తీసివేయి" + "అన్ఇన్‌స్టాల్ చేయి" + "యాప్ సమాచారం" + "ఇన్‌స్టాల్ చేయండి" + "సత్వరమార్గాలను ఇన్‌స్టాల్ చేయడం" + "వినియోగదారు ప్రమేయం లేకుండా సత్వరమార్గాలను జోడించడానికి అనువర్తనాన్ని అనుమతిస్తుంది." + "హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడం" + "హోమ్‌లో సెట్టింగ్‌లు మరియు సత్వరమార్గాలను చదవడానికి అనువర్తనాన్ని అనుమతిస్తుంది." + "హోమ్ సెట్టింగ్‌లు మరియు సత్వరమార్గాలను వ్రాయడం" + "హోమ్‌లో సెట్టింగ్‌లు మరియు సత్వరమార్గాలను మార్చడానికి అనువర్తనాన్ని అనుమతిస్తుంది." + "ఫోన్ కాల్‌లను చేసేందుకు %1$sకి అనుమతి లేదు" + "విడ్జెట్‌ను లోడ్ చేయడంలో సమస్య" + "సెటప్ చేయి" + "ఇది సిస్టమ్ యాప్ మరియు దీన్ని అన్‌ఇన్‌స్టాల్ చేయడం సాధ్యపడదు." + "పేరు లేని ఫోల్డర్" + "%1$s నిలిపివేయబడింది" + + %1$s %2$d నోటిఫికేషన్‌‌లను కలిగి ఉన్నారు + %1$s %2$d నోటిఫికేషన్‌ను కలిగి ఉన్నారు + + "%2$dలో %1$dవ పేజీ" + "%2$dలో %1$dవ హోమ్ స్క్రీన్" + "కొత్త హోమ్ స్క్రీన్ పేజీ" + "ఫోల్డర్ తెరవబడింది, %1$d X %2$d" + "ఫోల్డర్‌ను మూసివేయడానికి నొక్కండి" + "పేరు మార్పును సేవ్ చేయడానికి నొక్కండి" + "ఫోల్డర్ మూసివేయబడింది" + "ఫోల్డర్ పేరు %1$sగా మార్చబడింది" + "ఫోల్డర్: %1$s" + "విడ్జెట్‌లు" + "వాల్‌పేపర్‌లు" + "హోమ్ సెట్టింగ్‌లు" + "మీ నిర్వాహకులు నిలిపివేసారు" + "హోమ్ స్క్రీన్ భ్రమణాన్ని అనుమతించండి" + "ఫోన్‌‌ను తిప్పినప్పుడు" + "నోటిఫికేషన్ డాట్‌లు" + "ఆన్" + "ఆఫ్" + "నోటిఫికేషన్ యాక్సెస్ అవసరం" + "నోటిఫికేషన్ డాట్‌లను చూపించడానికి %1$sకు యాప్ నోటిఫికేషన్‌లను ఆన్ చేయండి" + "సెట్టింగ్‌లను మార్చు" + "నోటిఫికేషన్ డాట్‌లను చూపుతుంది" + "హోమ్ స్క్రీన్‌కి చిహ్నాన్ని జోడించు" + "కొత్త యాప్‌ల కోసం" + "చిహ్న ఆకారాన్ని మార్చు" + "హోమ్ స్క్రీన్‌పై" + "సిస్టమ్ డిఫాల్ట్‌ను ఉపయోగించండి" + "చతురస్రం" + "చతురస్రాకార వృత్తం" + "వృత్తం" + "కన్నీటి చుక్క" + "చిహ్న ఆకార మార్పులను వర్తింపజేస్తోంది" + "తెలియదు" + "తీసివేయి" + "వెతుకు" + "ఈ యాప్ ఇన్‌స్టాల్ చేయబడలేదు" + "ఈ చిహ్నం యొక్క యాప్ ఇన్‌స్టాల్ చేయబడలేదు. మీరు దీన్ని తీసివేయవచ్చు లేదా ఆ యాప్ కోసం శోధించి దాన్ని మాన్యువల్‌గా ఇన్‌స్టాల్ చేయవచ్చు." + "%1$s డౌన్‌లోడ్ అవుతోంది, %2$s పూర్తయింది" + "%1$s ఇన్‌స్టాల్ కావడానికి వేచి ఉంది" + "%1$s విడ్జెట్‌లు" + "హోమ్ స్క్రీన్‌కు జోడించు" + "అంశాన్ని ఇక్కడికి తరలించు" + "అంశం హోమ్‌స్క్రీన్‌కి జోడించబడింది" + "అంశం తీసివేయబడింది" + "అంశాన్ని తరలించు" + "అడ్డు వరుస %1$s నిలువు వరుస %2$sకి తరలించు" + "%1$sవ స్థానానికి తరలించు" + "ఇష్టమైనవిలో %1$sవ స్థానానికి తరలించు" + "అంశం తరలించబడింది" + "ఈ ఫోల్డర్‌కి జోడించండి: %1$s" + "%1$s గల ఫోల్డర్‌కు జోడించు" + "అంశం ఫోల్డర్‌కు జోడించబడింది" + "ఈ పేరుతో ఫోల్డర్‌ను సృష్టించండి: %1$s" + "ఫోల్డర్ సృష్టించబడింది" + "హోమ్‌స్క్రీన్‌కు తరలించు" + "పరిమాణం మార్చు" + "వెడల్పును పెంచు" + "ఎత్తును పెంచు" + "వెడల్పును తగ్గించు" + "ఎత్తును తగ్గించు" + "విడ్జెట్ పరిమాణం వెడల్పు %1$sకి, ఎత్తు %2$sకి మార్చబడింది" + "సత్వరమార్గాలు" + "%2$s కోసం %1$d సత్వరమార్గాలు" + "%3$s కోసం %1$d సత్వరమార్గాలు మరియు %2$d నోటిఫికేషన్‌లు" + "తీసివేయి" + "నోటిఫికేషన్ తీసివేయబడింది" + "వ్యక్తిగతం" + "కార్యాలయం" + "కార్యాలయ ప్రొఫైల్" + "కార్యాలయ యాప్‌లను ఇక్కడ కనుగొనండి" + "ప్రతి కార్యాలయ యాప్‌కు బ్యాడ్జ్‌ ఉంది మరియు మీ సంస్థ ద్వారా సురక్షితంగా ఉంచబడుతుంది. సులభ యాక్సెస్ కోసం యాప్‌లను మీ హోమ్ స్క్రీన్‌కి తరలించండి." + "మీ సంస్థ ద్వారా నిర్వహించబడతాయి" + "నోటిఫికేషన్‌లు మరియు యాప్‌లు ఆఫ్ చేయబడ్డాయి" + "మూసివేయి" + "మూసివేయబడింది" + diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 3f1762d00d..0967119eae 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -81,6 +81,8 @@ "వాల్‌పేపర్‌లు" "హోమ్ సెట్టింగ్‌లు" "మీ నిర్వాహకులు నిలిపివేసారు" + "హోమ్ స్క్రీన్ భ్రమణాన్ని అనుమతించండి" + "ఫోన్‌‌ను తిప్పినప్పుడు" "నోటిఫికేషన్ డాట్‌లు" "ఆన్" "ఆఫ్" @@ -128,8 +130,8 @@ "ఎత్తును తగ్గించు" "విడ్జెట్ పరిమాణం వెడల్పు %1$sకి, ఎత్తు %2$sకి మార్చబడింది" "సత్వరమార్గాలు" - "%2$s కోసం %1$d సత్వరమార్గాలు" - "%3$s కోసం %1$d సత్వరమార్గాలు మరియు %2$d నోటిఫికేషన్‌లు" + + "తీసివేయి" "నోటిఫికేషన్ తీసివేయబడింది" "వ్యక్తిగతం" diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index cac2333509..52ea7521ed 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -81,6 +81,8 @@ "วอลเปเปอร์" "การตั้งค่าหน้าแรก" "ปิดใช้โดยผู้ดูแลระบบ" + "อนุญาตให้หมุนหน้าจอหลัก" + "เมื่อหมุนโทรศัพท์" "จุดแจ้งเตือน" "เปิด" "ปิด" @@ -128,8 +130,8 @@ "ลดความสูง" "ปรับขนาดของวิดเจ็ตเป็นกว้าง %1$s สูง %2$s แล้ว" "ทางลัด" - "%1$d ทางลัดสำหรับ %2$s" - "ทางลัด %1$d รายการและการแจ้งเตือน %2$d รายการสำหรับ %3$s" + + "ปิด" "ปิดการแจ้งเตือนแล้ว" "ส่วนตัว" diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index 0b90214225..0047aaeb30 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -81,6 +81,8 @@ "Mga Wallpaper" "Mga setting ng Home" "Na-disable ng iyong admin" + "Payagan ang pag-rotate ng Home screen" + "Kailan maro-rotate ang telepono" "Mga notification dot" "Naka-on" "Naka-off" @@ -128,8 +130,8 @@ "Bawasan ang taas" "Na-resize ang widget sa lapad %1$s taas %2$s" "Mga Shortcut" - "%1$d (na) shortcut para sa %2$s" - "%1$d (na) shortcut at %2$d (na) notification para sa %3$s" + + "I-dismiss" "Na-dismiss ang notification" "Personal" diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index 972554424c..cfa9f9eaf3 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -81,6 +81,8 @@ "Duvar Kağıtları" "Ana ekran ayarları" "Yöneticiniz tarafından devre dışı bırakıldı" + "Ana ekranı döndürmeye izin ver" + "Telefon döndürüldüğünde" "Bildirim noktaları" "Açık" "Kapalı" @@ -128,8 +130,8 @@ "Yüksekliği azalt" "Widget, %1$s genişlik ve %2$s yükseklik değerine yeniden boyutlandırıldı" "Kısayollar" - "%2$s için %1$d kısayol" - "%3$s için %1$d kısayol ve %2$d bildirim" + + "Kapat" "Bildirim kapatıldı" "Kişisel" diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 47ddc7c944..aa5c676b1a 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -83,6 +83,8 @@ "Фонові малюнки" "Налаштування Home" "Вимкнув адміністратор" + "Дозволити обертання головного екрана" + "Коли телефон обертається" "Значки сповіщень" "Увімкнено" "Вимкнено" @@ -130,8 +132,8 @@ "Зменшити висоту" "Розміри віджета змінено на %1$s завширшки та %2$s заввишки" "Ярлики" - "Ярликів для додатка %2$s: %1$d" - "Ярлики (%1$d) і сповіщення (%2$d) додатка %3$s" + + "Закрити" "Сповіщення закрито" "Особисті додатки" diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml new file mode 100644 index 0000000000..77aa0a1eb5 --- /dev/null +++ b/res/values-ur-rPK/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "دفتری" + "ایپ انسٹال نہیں ہے۔" + "ایپ دستیاب نہیں ہے" + "ڈاؤن لوڈ کردہ ایپ کو محفوظ وضع میں غیر فعال کر دیا گیا" + "ویجیٹس کو محفوظ وضع میں غیر فعال کر دیا گیا" + "شارٹ کٹ دستیاب نہیں ہے" + "ہوم اسکرین" + "حسب ضرورت کارروائیاں" + "کوئی ویجیٹ منتخب کرنے کیلئے ٹچ کریں اور پکڑے رہیں۔" + "کوئی ویجٹ منتخب کرنے یا حسب ضرورت کاروائیاں استعمال کرنے کیلئے دو بار تھپتھپائیں اور پکڑے رکھیں۔" + "%1$d × %2$d" + "‏%1$d چوڑا اور ‎%2$d اونچا" + "‏دستی طور پر رکھنے کیلئے ‎& ٹچ کرکے ہولڈ کریں" + "خود کار طور پر شامل کریں" + "ایپس تلاش کریں" + "ایپس لوڈ کی جا رہی ہیں…" + "\"%1$s\" سے مماثل کوئی ایپس نہیں ملیں" + "مزید ایپس تلاش کریں" + "اطلاعات" + "ایک شارٹ کٹ منتخب کرنے کیلئے ٹچ کر کے دبائے رکھیں۔" + "ایک شارٹ کٹ منتخب کرنے یا حسب ضرورت کارروائیاں استعمال کرنے کیلئے دو بار تھپتھپائیں اور دبائے رکھیں۔" + "اس ہوم اسکرین پر مزید کوئی گنجائش نہیں ہے۔" + "پسندیدہ ٹرے میں مزید کوئی گنجائش نہیں ہے" + "ایپس کی فہرست" + "ذاتی ایپس کی فہرست" + "دفتری ایپس کی فہرست" + "ہوم" + "ہٹائیں" + "اَن انسٹال کریں" + "ایپ کی معلومات" + "انسٹال کریں" + "شارٹ کٹس انسٹال کریں" + "کسی ایپ کو صارف کی مداخلت کے بغیر شارٹ کٹس شامل کرنے کی اجازت دیتا ہے۔" + "ہوم ترتیبات اور شارٹ کٹس کو پڑھیں" + "ایپ کو ہوم میں ترتیبات اور شارٹ کٹس کو پڑھنے کی اجازت دیتا ہے۔" + "ہوم ترتیبات اور شارٹ کٹس کو لکھیں" + "ایپ کو ہوم میں ترتیبات اور شارٹ کٹس کو تبدیل کرنے کی اجازت دیتا ہے۔" + "%1$s کو فون کالیں کرنے کی اجازت نہیں ہے" + "ویجیٹ کو لوڈ کرنے میں مسئلہ" + "ترتیب دیں" + "یہ ایک سسٹم ایپ ہے اور اسے اَن انسٹال نہیں کیا جا سکتا ہے۔" + "بلا نام فولڈر" + "%1$s غیر فعال ہے" + + %1$s میں %2$d اطلاعات ہیں + %1$s میں %2$d اطلاع ہے + + "‏صفحہ ‎%1$d از ‎%2$d" + "‏ہوم اسکرین ‎%1$d از ‎%2$d" + "نیا ہوم اسکرین صفحہ" + "فولڈر کھولا گیا، %1$d × %2$d" + "فولڈر کو بند کرنے کیلئے تھپتھپائیں" + "نام کی تبدیلی محفوظ کرنے کیلئے تھپتھپائیں" + "فولڈر بند ہو گیا" + "فولڈر کا نام تبدیل کر کے %1$s کر دیا گیا" + "فولڈر: %1$s" + "ویجیٹس" + "وال پیپرز" + "ہوم ترتیبات" + "آپ کے منتظم کی طرف سے غیر فعال کر دیا گیا" + "ہوم اسکرین گھمانے کی اجازت دیں" + "جب فون گھمایا جاتا ہے" + "اطلاعاتی ڈاٹس" + "آن" + "آف" + "اطلاعاتی رسائی درکار ہے" + "اطلاعاتی ڈاٹس دکھانے کی خاطر %1$s کیلئے ایپ کی اطلاعات آن کریں" + "ترتیبات تبدیل کریں" + "اطلاعاتی ڈاٹس دکھائیں" + "آئیکن کو ہوم اسکرین میں شامل کریں" + "نئی ایپس کیلئے" + "آئیکن کی شکل تبدیل کریں" + "ہوم اسکرین پر" + "سسٹم ڈیفالٹ کا استعمال کریں" + "مربع" + "اسکورکل" + "حلقہ" + "آنسو کا قطرہ" + "آئيکن کی شکل کی تبدیلیاں لاگو ہو رہی ہیں" + "نامعلوم" + "ہٹائیں" + "تلاش کریں" + "یہ ایپ انسٹال کردہ نہیں ہے" + "اس آئیکن کیلئے ایپ انسٹال کردہ نہیں ہے۔ آپ اسے ہٹا سکتے ہیں یا ایپ کو تلاش کر سکتے اور دستی طور پر اسے انسٹال کر سکتے ہیں۔" + "%1$s ڈاؤن لوڈ ہو رہا ہے، %2$s مکمل ہو گیا" + "%1$s انسٹال ہونے کا انتظار کر رہی ہے" + "%1$s ویجیٹس" + "ہوم اسکرین میں شامل کریں" + "آئٹم یہاں منتقل کریں" + "آئٹم کو ہوم اسکرین میں شامل کر دیا گیا" + "آئٹم ہٹا دیا گیا" + "آئٹم منتقل کریں" + "قطار %1$s کالم %2$s میں منتقل کریں" + "پوزیشن %1$s میں منتقل کریں" + "پسندیدہ پوزیشن %1$s میں منتقل کریں" + "آئٹم منتقل کر دیا گیا" + "فولڈر میں شامل کریں: %1$s" + "%1$s کے فولڈر میں شامل کریں" + "آئٹم فولڈر میں شامل کر دیا گیا" + "اس کے ساتھ فولڈر بنائیں: %1$s" + "فولڈر بنا دیا گیا" + "ہوم اسکرین میں منتقل کریں" + "سائز تبدیل کریں" + "چوڑائی بڑھائیں" + "اونچائی بڑھائیں" + "چوڑائی کم کریں" + "اونچائی کم کریں" + "ویجیٹ کے سائز کو چوڑائی %1$s اونچائی %2$s میں تبدیل کر دیا گیا" + "شارٹ کٹس" + "%2$s کیلئے %1$d شارٹ کٹس" + "%3$s کے %1$d شارٹ کٹس اور %2$d اطلاعات" + "برخاست کریں" + "اطلاع مسترد ہو گئی" + "ذاتی" + "دفتری" + "دفتری پروفائل" + "یہاں دفتری ایپس تلاش کریں" + "ہر دفتری ایپ میں ایک بَیج ہوتا ہے اور اسے آپ کی تنظیم محفوظ رکھتی ہے۔ زیادہ آسان رسائی کیلئے ایپس کو اپنی ہوم اسکرین پر منتقل کریں۔" + "آپ کی تنظیم کے زیر انتظام" + "اطلاعات اور ایپس آف ہیں" + "بند کریں" + "بند" + diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index 2558076469..d8e339df07 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -81,6 +81,8 @@ "وال پیپرز" "ہوم ترتیبات" "آپ کے منتظم کی طرف سے غیر فعال کر دیا گیا" + "ہوم اسکرین گھمانے کی اجازت دیں" + "جب فون گھمایا جاتا ہے" "اطلاعاتی ڈاٹس" "آن" "آف" @@ -128,8 +130,8 @@ "اونچائی کم کریں" "ویجیٹ کے سائز کو چوڑائی %1$s اونچائی %2$s میں تبدیل کر دیا گیا" "شارٹ کٹس" - "%2$s کیلئے %1$d شارٹ کٹس" - "%3$s کے %1$d شارٹ کٹس اور %2$d اطلاعات" + + "برخاست کریں" "اطلاع مسترد ہو گئی" "ذاتی" diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml new file mode 100644 index 0000000000..0360a7132a --- /dev/null +++ b/res/values-uz-rUZ/strings.xml @@ -0,0 +1,146 @@ + + + + + "Launcher3" + + "Ishga oid" + "Ilova o‘rnatilmadi." + "Ilova mavjud emas" + "Yuklab olingan ilova xavfsiz rejimda o‘chirib qo‘yildi" + "Xavfsiz rejimda vidjetlar o‘chirib qo‘yilgan" + "Tezkor tugmadan foydalanib bo‘lmaydi" + "Bosh ekran" + "Maxsus amallar" + "Vidjetni tanlash uchun bosib turing." + "Ikki marta bosib va bosib turgan holatda vidjetni tanlang yoki maxsus amaldan foydalaning." + "%1$d × %2$d" + "Eni %1$d, bo‘yi %2$d" + "Qo‘lda joylashtirish uchun bosib turing" + "Avtomatik chiqarish" + "Ilovalarni qidirish" + "Ilovalar yuklanmoqda…" + "“%1$s” bilan mos hech qanday ilova topilmadi" + "Boshqa ilovalarni qidirish" + "Bildirishnomalar" + "Yorliqni tanlab olish uchun bosib turing." + "Ikki marta bosib va bosib turgan holatda yorliqni tanlang yoki maxsus amaldan foydalaning." + "Uy ekranida bitta ham xona yo‘q." + "Ajratilganlarda birorta ham xona yo‘q" + "Ilovalar ro‘yxati" + "Shaxsiy ilovalar ro‘yxati" + "Ishchi ilovalar ro‘yxati" + "Bosh sahifa" + "Olib tashlash" + "O‘chirib tashlash" + "Ilova haqida" + "O‘rnatish" + "yorliqlar yaratish" + "Ilovalarga foydalanuvchidan so‘ramasdan yorliqlar qo‘shishga ruxsat beradi." + "Uy sozlamalari va yorliqlarini o‘qish" + "Ilovaga \"Uy\" ekranidagi yorliqlar va sozlamalarni o‘qish uchun ruxsat beradi." + "Uy sozlamalari va yorliqlarini yozish" + "Ilovaga \"Uy\" ekranidagi yorliqlar va sozlamalrni o‘zgartirish uchun ruxsat beradi." + "%1$s ilovasiga qo‘ng‘iroqlarni amalga oshirishga ruxsat berilmagan" + "Vidjetni yuklashda muammo" + "Sozlash" + "Bu tizim ilovasi, shuning uchun o‘chirib bo‘lmaydi." + "Nomsiz jild" + "%1$s ilovasi o‘chirib qo‘yildi" + + %1$s, %2$d ta bildirishnoma bor + %1$s, %2$d ta bildirishnoma bor + + "%2$ddan %1$d ta sahifa" + "Uy ekrani %2$ddan %1$d" + "Yangi bosh ekran sahifasi" + "Jild ochildi, %1$d ga %2$d" + "Jildni yopish uchun ustiga bosing" + "O‘zgarishni saqlash uchun ustiga bosing" + "Jild yopildi" + "Jild nomi %1$sga o‘zgartirildi" + "Jild: %1$s" + "Vidjetlar" + "Fon rasmlari" + "Bosh ekran sozlamalari" + "Administrator tomonidan o‘chirilgan" + "Asosiy ekranni aylantirishga ruxsat berish" + "Telefon burilganda" + "Bildirishnoma belgilari" + "Yoniq" + "O‘chiq" + "Bildirishnomalarga ruxsat berilmagan" + "Bildirishnoma belgilarini ko‘rsatish uchun %1$s ilovasida bildirishnomalarni yoqing" + "Sozlamalarni o‘zgartirish" + "Bildirishnoma belgilarini ko‘rsatish" + "Bosh ekranga ikonka chiqarish" + "Yangi o‘rnatilgan ilovalar ikonkasini bosh ekranga chiqarish" + "Ikonka shaklini o‘zgartirish" + "Bosh ekranda" + "Standart tizim parametrlaridan foydalanish" + "Kvadrat" + "Qirralari aylana kvadrat" + "Aylana" + "Tomchi" + "Ikonka shakli o‘zgartirilmoqda" + "Noma’lum" + "O‘chirish" + "Qidirish" + "Ushbu ilova o‘rnatilmagan" + "Ilova o‘rnatilmagan. Belgini o‘chirib tashlashingiz yoki ilovani topib, uni qo‘lda o‘rnatishingiz mumkin." + "%1$s yuklab olinmoqda, %2$s bajarildi" + "%1$s ilovasi o‘rnatilishi kutilmoqda" + "%1$s vidjetlari" + "Bosh ekranga qo‘shish" + "Obyektni bu yerga ko‘chirish" + "Obyekt bosh ekranga qo‘shildi" + "Obyekt o‘chirib tashlandi" + "Obyektni ko‘chirib o‘tkazish" + "%1$s %2$s katakka ko‘chirib o‘tkazish" + "%1$s-joyga ko‘chirib o‘tkazish" + "Sevimlilarga (%1$s) ko‘chirib o‘tkazish" + "Element ko‘chirib o‘tkazildi" + "%1$s jildiga qo‘shish" + "%1$s ilovasi bor jildga qo‘shish" + "Element jildga qo‘shildi" + "%1$s bilan jild yaratish" + "Jild yaratildi" + "Bosh ekranga ko‘chirish" + "O‘lchamini o‘zgartirish" + "Enini uzaytirish" + "Bo‘yini uzaytirish" + "Enini kichraytirish" + "Bo‘yini kichraytirish" + "Vidjetning eni %1$s, bo‘yi %2$s qilib o‘zgartirildi" + "Tezkor tugmalar" + "%2$s ilovasi uchun %1$d ta tezkor tugma" + "%3$s ilovasi uchun %1$d ta yorliq va %2$d ta bildirishnoma" + "Yopish" + "Bildirishnoma yopildi" + "Shaxsiy" + "Ishchi" + "Ishchi profil" + "Ishga oid ilovalarni shu yerdan topish mumkin" + "Nishonga ega har bir ishga oid ilova tashkilotingiz tomonidan himoyalanadi. Ishga oid ilovalarga osonroq kirish uchun ularni bosh ekranga chiqaring." + "Tashkilotingiz tomonidan boshqariladi" + "Bildirishnomalar va ilovalar faol emas" + "Yopish" + "Yopiq" + diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index e9f36a842a..6b53e9657f 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -79,8 +79,10 @@ "Jild: %1$s" "Vidjetlar" "Fon rasmlari" - "Home sozlamalari" + "Bosh ekran sozlamalari" "Administrator tomonidan o‘chirilgan" + "Asosiy ekranni aylantirishga ruxsat berish" + "Telefon burilganda" "Bildirishnoma belgilari" "Yoniq" "O‘chiq" @@ -88,7 +90,7 @@ "Bildirishnoma belgilarini ko‘rsatish uchun %1$s ilovasida bildirishnomalarni yoqing" "Sozlamalarni o‘zgartirish" "Bildirishnoma belgilarini ko‘rsatish" - "Bosh ekranga ikonka qo‘shish" + "Bosh ekranga ikonka chiqarish" "Yangi o‘rnatilgan ilovalar ikonkasini bosh ekranga chiqarish" "Ikonka shaklini o‘zgartirish" "Bosh ekranda" @@ -128,8 +130,8 @@ "Bo‘yini kichraytirish" "Vidjetning eni %1$s, bo‘yi %2$s qilib o‘zgartirildi" "Tezkor tugmalar" - "%2$s ilovasi uchun %1$d ta tezkor tugma" - "%3$s ilovasi uchun %1$d ta yorliq va %2$d ta bildirishnoma" + + "Yopish" "Bildirishnoma yopildi" "Shaxsiy" diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 65a5eccf82..ab88cfec6e 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -79,8 +79,10 @@ "Thư mục: %1$s" "Tiện ích con" "Hình nền" - "Cài đặt trang chủ" + "Cài đặt màn hình chính" "Bị tắt bởi quản trị viên của bạn" + "Cho phép xoay Màn hình chính" + "Khi xoay điện thoại" "Dấu chấm thông báo" "Đang bật" "Đã tắt" @@ -128,8 +130,8 @@ "Giảm chiều cao" "Đã đổi kích thước tiện ích thành chiều rộng %1$s chiều cao %2$s" "Lối tắt" - "%1$d phím tắt cho %2$s" - "%1$d phím tắt và %2$d thông báo cho %3$s" + + "Loại bỏ" "Đã loại bỏ thông báo" "Cá nhân" diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index f8dd3cd05f..a92208c83d 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -81,6 +81,8 @@ "壁纸" "主屏幕设置" "已被您的管理员停用" + "允许旋转主屏幕" + "手机旋转时" "通知圆点" "开启" "关闭" @@ -128,8 +130,8 @@ "减小高度" "微件尺寸已调整为:宽度 %1$s,高度 %2$s" "快捷方式" - "%2$s%1$d 个快捷方式" - "%3$s%1$d 个快捷方式和 %2$d 条通知" + + "关闭" "已关闭通知" "个人" diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index 4828006cbb..0f253003b5 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -79,8 +79,10 @@ "資料夾:%1$s" "小工具" "桌布" - "Home 設定" + "主螢幕設定" "已由您的管理員停用" + "允許主畫面旋轉" + "當手機旋轉時" "通知圓點" "開啟" "關閉" @@ -128,8 +130,8 @@ "減少高度" "已調整小工具的大小至闊 %1$s%2$s" "捷徑" - "「%2$s」嘅 %1$d 個捷徑" - "「%3$s」嘅 %1$d 個捷徑同 %2$d 個通知" + + "關閉" "關閉咗通知" "個人" diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index 1a8d515348..c187b968b7 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -81,6 +81,8 @@ "桌布" "Home 設定" "已由你的管理員停用" + "允許旋轉主螢幕" + "當手機旋轉時" "通知圓點" "已啟用" "已停用" @@ -128,8 +130,8 @@ "減少高度" "已將小工具的寬度和高度分別調整為 %1$s%2$s" "捷徑" - "「%2$s」有 %1$d 個捷徑" - "%1$d 個捷徑和 %2$d 則「%3$s」通知" + + "關閉" "已關閉通知" "個人" diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index 126145eac5..6f92847c1c 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -81,6 +81,8 @@ "Izithombe zangemuva" "Izilungiselelo zasekhaya" "Kukhutshazwe umlawuli wakho" + "Vumela ukuphendukiswa kwesikrini sasekhaya" + "Uma ifoni iphendukiswa" "Amachashazi esaziso" "Kuvuliwe" "Kuvaliwe" @@ -128,8 +130,8 @@ "Nciphisa ubude" "Iwijethi inikezwe usayizi omusha ngobubanzi obungu-%1$s ubude obungu-%2$s" "Izinqamuleli" - "%1$d izinqamuleli ze-%2$s" - "%1$d izinqamuleli nezaziso ezingu-%2$d ze-%3$s" + + "Cashisa" "Isaziso sicashisiwe" "Okomuntu siqu" diff --git a/res/values/config.xml b/res/values/config.xml index a40afe1138..d5bb131eff 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -41,9 +41,6 @@ - - 76 - 90 @@ -139,6 +136,7 @@ + @@ -147,6 +145,7 @@ + 6 12 diff --git a/res/values/dimens.xml b/res/values/dimens.xml index b1ad11ef05..07e0b04ddd 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -20,7 +20,6 @@ 8dp - 24dp 1dp 8dp 8dp @@ -42,6 +41,7 @@ 8dp 8dp 4dp + 24dp 48dp diff --git a/res/values/strings.xml b/res/values/strings.xml index bcb90e3fdf..7bc11c3be1 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -179,6 +179,10 @@ Disabled by your admin + + Allow Home screen rotation + + When phone is rotated Notification dots @@ -240,6 +244,11 @@ %1$s widgets + + Widgets list + + Widgets list closed + Add to Home screen @@ -306,11 +315,9 @@ Shortcuts - - - %1$d shortcuts for %2$s - - %1$d shortcuts and %2$d notifications for %3$s + + Shortcuts and notifications + Dismiss diff --git a/res/values/styles.xml b/res/values/styles.xml index 38b5daedbf..631626f441 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -28,7 +28,7 @@