what - هل يمكن أن يحتوي مجلد Android Layout على مجلدات فرعية؟




xml layout code (11)

في الوقت الحالي ، أنا أقوم بتخزين كل ملف تخطيط بتنسيق xml داخل المجلد res/layout ، لذا من السهل إدارة المشاريع الصغيرة ، ولكن عندما تكون هناك مشاريع كبيرة وثقيلة ، يجب أن يكون هناك تسلسل هرمي المجلدات المطلوبة داخل مجلد التخطيط.

على سبيل المثال

layout
-- layout_personal
   -- personal_detail.xml
   -- personal_other.xml
--layout_address
  -- address1.xml
  -- address2.xml

على غرار نفس الطريقة ، نود أن يكون لدينا مجلدات فرعية للتطبيق الكبير ، لذا هل هناك أي طريقة للقيام بذلك داخل مشروع android؟

أتمكن من إنشاء مجلدات فرعية للتخطيط-شخصية و layout_address داخل مجلد التخطيط ، ولكن عندما يحين الوقت للوصول إلى ملف تنسيق xml باستخدام R.layout ._______ ، في ذلك الوقت لا يوجد أي نافذة منبثقة بتنسيق xml داخل قائمة طعام.


مشكلة صغيرة

يمكنني تحقيق المجلدات الفرعية باتباع أعلى إجابة على هذا السؤال.

ومع ذلك ، مع نمو المشروع ، سيكون لديك العديد من المجلدات الفرعية:

sourceSets {
    main {
        res.srcDirs =
            [
                    'src/main/res/layouts/somethingA',
                    'src/main/res/layouts/somethingB',
                    'src/main/res/layouts/somethingC',
                    'src/main/res/layouts/somethingD',
                    'src/main/res/layouts/somethingE',
                    'src/main/res/layouts/somethingF',
                    'src/main/res/layouts/somethingG',
                    'src/main/res/layouts/somethingH',
                    'src/main/res/layouts/...many more',
                    'src/main/res'
            ]
    }
}

ليست مشكلة كبيرة ، ولكن:

  • انها ليست جميلة كما أصبحت القائمة طويلة جدا.
  • يجب عليك تغيير app/build.gradle كل مرة تقوم فيها بإضافة مجلد جديد.

تحسين

لذلك كتبت طريقة بسيطة Groovy للاستيلاء على جميع المجلدات المتداخلة:

def getLayoutList(path) {
    File file = new File(path)
    def throwAway = file.path.split("/")[0]
    def newPath = file.path.substring(throwAway.length() + 1)
    def array = file.list().collect {
        "${newPath}/${it}"
    }
    array.push("src/main/res");
    return array
}

الصق هذه الطريقة خارج كتلة android {...} في app/build.gradle .

كيف تستعمل

لهيكل مثل هذا:

<project root>
├── app <---------- TAKE NOTE
├── build
├── build.gradle
├── gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle

استخدمه على النحو التالي:

android {
    sourceSets {
        main {
            res.srcDirs = getLayoutList("app/src/main/res/layouts/")
        }
    }
}

إذا كان لديك بنية كهذه:

<project root>
├── my_special_app_name <---------- TAKE NOTE
├── build
├── build.gradle
├── gradle
├── gradle.properties
├── gradlew
├── gradlew.bat
├── local.properties
└── settings.gradle

سوف تستخدمها على هذا النحو:

android {
    sourceSets {
        main {
            res.srcDirs = getLayoutList("my_special_app_name/src/main/res/layouts/")
        }
    }
}

تفسير

getLayoutList() a relative path كوسيطة. relative path النسبي نسبة إلى جذر المشروع. لذلك عندما نقوم بإدخال "app/src/main/res/layouts/" ، فسوف يقوم بإرجاع اسم كل مجلدات فرعية كصفيف ، والذي سيكون مطابقًا تمامًا لما يلي:

            [
                    'src/main/res/layouts/somethingA',
                    'src/main/res/layouts/somethingB',
                    'src/main/res/layouts/somethingC',
                    'src/main/res/layouts/somethingD',
                    'src/main/res/layouts/somethingE',
                    'src/main/res/layouts/somethingF',
                    'src/main/res/layouts/somethingG',
                    'src/main/res/layouts/somethingH',
                    'src/main/res/layouts/...many more',
                    'src/main/res'
            ]

في ما يلي النص البرمجي مع التعليقات لفهمه:

def getLayoutList(path) {
    // let's say path = "app/src/main/res/layouts/
    File file = new File(path)

    def throwAway = file.path.split("/")[0]
    // throwAway = 'app'

    def newPath = file.path.substring(throwAway.length() + 1) // +1 is for '/'
    // newPath = src/main/res/layouts/

    def array = file.list().collect {
        // println "filename: ${it}" // uncomment for debugging
        "${newPath}/${it}"
    }

    array.push("src/main/res");
    // println "result: ${array}" // uncomment for debugging

    return array
}

آمل أن يساعد!


أردت فقط أن أضيف على إجابة رائعة eskis للأشخاص الذين يواجهون مشكلة. (ملاحظة: سيعمل هذا فقط وتبدو وكأنها أدلة منفصلة داخل عرض "المشروع" ، وليس وجهة نظر "الروبوت" للأسف.)

اختبار مع ما يلي. BuildToolsVersion = 23.0.0 gradle 1.2.3 و 1.3.0

هكذا حصلت على العمل مع مشروع تم بناؤه بالفعل.

  1. قم بنسخ كافة ملفات XML من دليل التخطيط الخاص بك ، ووضعها في دليل على سطح المكتب أو شيء ما للنسخ الاحتياطي.
  2. احذف دليل التخطيط بالكامل (تأكد من أنك قمت بنسخ كل شيء من الخطوة 1 !!!)
  3. انقر بزر الماوس الأيمن على دليل الدقة وحدد دليل> جديد.
  4. اسم هذا الدليل الجديد "تخطيطات". (يمكن أن يكون هذا ما تريد ، ولكنه لن يكون دليل "جزء" أو دليل "نشاط" ، يأتي لاحقًا).
  5. انقر بزر الماوس الأيمن على دليل "التخطيطات" الجديد وحدد دليل> جديد. (سيكون هذا هو اسم نوع ملفات XML الموجودة لديك ، على سبيل المثال ، "أجزاء" و "أنشطة").
  6. انقر بزر الماوس الأيمن على دليل 'fragment' أو 'activities' (ملاحظة: هذا لا يجب أن يكون 'fragment' أو 'activities' هذا ما أستخدمه كمثال) وحدد new> directory مرة أخرى واسم هذا الدليل "نسق". (ملاحظة: هذا يجب أن يسمى "تخطيط" !!! مهم جدا).
  7. ضع ملفات XML التي تريدها داخل دليل 'layout' الجديد من النسخة الاحتياطية التي قمت بها على سطح المكتب.
  8. كرر الخطوات من 5 إلى 7 لأكبر عدد من الدلائل المخصصة حسب رغبتك.
  9. بمجرد اكتمال هذا ، انتقل إلى ملف الوحدات النمطية gradle.build وإنشاء تعريف sourceSets مثل هذا ... (تأكد من 'src / main / res / layouts' & 'src / main / res' هي دائماً أسفل اثنين !! مثل أنا أعرض أدناه).

    sourceSets {
        main {
            res.srcDirs =
                    [
                            'src/main/res/layouts/activities',
                            'src/main/res/layouts/fragments',
                            'src/main/res/layouts/content',
                            'src/main/res/layouts',
                            'src/main/res'
                    ]
        }
    }
    
  10. الربح $$$$

ولكن على محمل الجد .. هذه هي الطريقة التي حصلت عليها للعمل. اسمحوا لي أن أعرف ما إذا كان أي شخص لديه أي أسئلة .. يمكنني محاولة المساعدة.

الصور تستحق أكثر من الكلمات.


أعتقد أن الحل الأكثر أناقة لهذه المشكلة (بالنظر إلى أن المجلدات الفرعية غير مسموح بها) هو إرفاق أسماء الملفات مع اسم المجلد الذي وضعته بداخله. على سبيل المثال ، إذا كان لديك مجموعة من التنسيقات لنشاط أو جزء أو طريقة عرض عامة تسمى "الأماكن" ، فيجب عليك إرفاقها مسبقًا بـ places_my_layout_name. على الأقل هذا يحل مشكلة تنظيمها بطريقة يسهل العثور عليها داخل IDE. إنه ليس الحل الأكثر روعة ، ولكنه أفضل من لا شيء.


إذا كنت تقوم بالتطوير على linux أو mac box ، فسيكون الحل البديل هو إنشاء مجلدات فرعية تتضمن روابط رمزية إلى ملفات التخطيط الخاصة بك. فقط استخدم الأمر ln مع -s

ln -s PATH_TO_YOUR_FILE

المشكلة مع هذا ، أن مجلد التنسيق الخاص بك لا يزال يحتوي على كافة ملفات .xml. ولكن يمكنك رغم ذلك تحديدها باستخدام المجلدات الفرعية. إنه أقرب شيء إلى ما ترغب في الحصول عليه.

لقد قرأت للتو ، أن هذا قد يعمل مع Windows ، أيضًا إذا كنت تستخدم Vista أو أحدث. هناك هذا الأمر mklink . مجرد جوجل ذلك ، لم تستخدم قط نفسي.

مشكلة أخرى ، إذا كان لديك ملف مفتوح ومحاولة فتحه مرة أخرى خارج البرنامج المساعد يطرح استثناء NULL Pointer. لكنها لا تقفل.


الآن يمكننا القيام بسهولة مع البرنامج المساعد JetBrains يسمى " تجميع ملفات Android "

تحقق من هذا الرابط

تجميع ملفات Android


الإجابة الأعلى منeski جيدة ، لكن الشفرة ليست أنيقة للاستخدام ، لذلك كتبت نصًا رائعًا في gradle للاستخدام العام. يتم تطبيقه على كل نوع البناء ونكهة المنتج وليس فقط يمكن استخدامه للتخطيط ، كما يمكنك إضافة مجلد فرعي لأي نوع موارد أخرى مثل drawable. هنا هو رمز (وضعها في كتلة android من الملف على مستوى المشروع) :

sourceSets.each {
    def rootResDir = it.res.srcDirs[0]
    def getSubDirs = { dirName ->
        def layoutsDir = new File(rootResDir, dirName)
        def subLayoutDirs = []
        if (layoutsDir.exists()) {
            layoutsDir.eachDir {
                subLayoutDirs.add it
            }
        }
        return subLayoutDirs
    }
    def resDirs = [
            "anims",
            "colors",
            "drawables",
            "drawables-hdpi",
            "drawables-mdpi",
            "drawables-xhdpi",
            "drawables-xxhdpi",
            "layouts",
            "valuess",
    ]
    def srcDirs = resDirs.collect {
        getSubDirs(it)
    }
    it.res.srcDirs = [srcDirs, rootResDir]
}

كيف تفعل في الممارسة؟

على سبيل المثال ، أريد إنشاء مجلد فرعي باسم activity layout ، وإضافة سلسلة بأي اسم في متغير resDirs مثل layouts ، ثم يجب وضع ملف تنسيق xml في res\layouts\activity\layout\xxx.xml .

إذا كنت أرغب في إنشاء مجلد فرعي مسمى selectors resDirs ، أضف سلسلة بأي اسم في متغير resDirs مثل drawables ، فيجب وضع ملف xml res\drawables\selectors\drawable\xxx.xml في res\drawables\selectors\drawable\xxx.xml .

يتم تعريف اسم المجلد مثل layouts و drawables في متغير resDirs ، يمكن أن يكون أي سلسلة. تعتبر كل المجلدات الفرعية التي أنشأتها مثل activity أو selectors نفس المجلد res . لذا في مجلد selectors ، يجب أن نقوم بإنشاء مجلد drawable بالإضافة إلى وضع ملفات xml في مجلد drawable ، بعد أن يتعرف ذلك على ملفات xml القابلة للرسم بشكل طبيعي.



حسنا ، الجواب القصير هو لا. ولكن يمكنك بالتأكيد أن يكون لديك مجلدات res متعددة. أعتقد أن هذا أقرب ما يمكن إلى الحصول على مجلدات فرعية لمجلد layout . Here's كيف تفعل ذلك.


على الرغم من أن جميع المقترحات لمجموعات الموارد المتعددة قد تعمل ، إلا أن المشكلة تكمن في أن المنطق الحالي للمكون الإضافي لـ Android Studio Gradle لن يعمل على تحديث ملفات الموارد بعد تغييرها لمجموعات الموارد المتداخلة. يحاول التطبيق الحالي التحقق من أدلة الموارد باستخدام beginWith () ، لذلك فإن بنية الدليل المتداخلة (أي src / main / res / layout / تخطيطات و src / main / res / layout / layouts_category2) ستختار src / main / res / تخطيط / تخطيطات باستمرار ولا يتم تحديث التغييرات فعليًا. والنتيجة النهائية هي أن عليك إعادة بناء / تنظيف المشروع في كل مرة.

لقد أرسلت تصحيحًا على https://android-review.googlesource.com/#/c/157971/ لمحاولة المساعدة في حل الأمور.


غير ممكن ، ولكن يتم فرز مجلد التخطيط حسب الاسم. لذا ، أقوم بإرفاق أسماء ملفات التخطيط بأسماء الحزم الخاصة بي. مثال على الحزمتين "الشراء" و "اللعب":

buying_bought_tracks.xml
buying_buy_tracks.xml
playing_edit_playlist.xml
playing_play_playlist.xml
playing_show_playlists.xml

  • الخطوة 1: انقر بزر الماوس الأيمن على التخطيط - إظهار في المستكشف
  • الخطوة 2: افتح مجلد التخطيط وأنشئ المجلدات الفرعية مباشرةً: layout_1 ، layout_2 ...
  • الخطوة 3: افتح layout_1 إنشاء تخطيط المجلد (ملاحظة: اسم إلزامي هو تخطيط) ، افتح layout_2 مجلد إنشاء دليل فرعي تخطيط (ملاحظة: اسم إلزامي هو تخطيط) ...
  • الخطوة 4: قم بنسخ ملفات xml في الدلائل الفرعية للتخطيط في layout_1 و layout_2
  • الخطوة 5: شغّل الرمز في buid.grade (تطبيق الوحدة) واضغط على المزامنة الآن:
sourceSets {
    main {
        res.srcDirs =
            [
                'src / main / res / layout / layout_1'
                'src / main / res / layout / layout_2',
                'src / main / res'
            ]
    }
}
  • الخطوة 6: ملخص: سوف تساعد جميع الخطوات المذكورة أعلاه في تجميع المجلدات وعرضها في وضع "المشروع" ، بينما سيعرض وضع "android" كالمعتاد.
  • لذلك أنا أرسم أن بادئات التسمية ربما تكون فعالة مثل مجلدات التجميع.




android-layout