Як створити прозорий демонстраційний екран для програми Android?


105

Я намагаюся створити напівпрозорий демонстраційний екран, який запускається лише тоді, коли користувач вперше встановить мою програму. Ось приклад програми Pulse News:

Galaxy Nexus

Приклад скріншоту з Pulse News на Galaxy Nexus

Nexus One

введіть тут опис зображення

Замість функції "натиснути для відхилення" я хочу, щоб користувач міг прогортати пару таких прозорих демонстраційних сторінок.

Для моєї першої спроби я змінив зразок з бібліотеки ViewPagerIndicator . Я використовував напівпрозорі PNG в ImageViews всередині фрагментів пейджера програми перегляду. Потім я запустив це як "демо-активність" у методі onCreate своєї "основної діяльності".

Проблема: "Основну діяльність" не можна було побачити на задньому плані - натомість вона була просто чорною. Я спробував рішення тут , але це не вирішило проблему.

Чи є кращий підхід до створення подібного, чи я на вірному шляху?

У мене також було ще одне пов'язане питання, яке залежить від того, як це здійснюється. Я намагаюся накласти текст і стрілки таким чином, щоб вони вказували на конкретні компоненти інтерфейсу у фоновому режимі. Використовуючи PNG, у якому є текст та стрілки, цілком ймовірно, що він не буде належним чином масштабувати на різних пристроях. Тобто стрілки не обов'язково вказують на правильний компонент інтерфейсу на задньому плані. Чи є також спосіб вирішити цю проблему?

Дякую!

Ось мій код для першої спроби:

DemoActivity.java

public class DemoActivity extends FragmentActivity {
    DemoFragmentAdapter mAdapter;
    ViewPager mPager;
    PageIndicator mIndicator;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.demo_activity);

        mAdapter = new DemoFragmentAdapter(getSupportFragmentManager());

        mPager = (ViewPager)findViewById(R.id.pager);
        mPager.setAdapter(mAdapter);
        //mPager.setAlpha(0);

        UnderlinePageIndicator indicator = (UnderlinePageIndicator)findViewById(R.id.indicator);
        indicator.setViewPager(mPager);
        indicator.setFades(false);
        mIndicator = indicator;
    }

}

DemoFragmentAdapter.java

class DemoFragmentAdapter extends FragmentPagerAdapter {
    protected static final int[] CONTENT = new int[] { R.drawable.demo1, R.drawable.demo2, R.drawable.demo3, R.drawable.demo4};

    private int mCount = CONTENT.length;

    public DemoFragmentAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return DemoFragment.newInstance(CONTENT[position % CONTENT.length]);
    }

    @Override
    public int getCount() {
        return mCount;
    }

    public void setCount(int count) {
        if (count > 0 && count <= 10) {
            mCount = count;
            notifyDataSetChanged();
        }
    } }

DemoFragment.java

public final class DemoFragment extends Fragment {
    private static final String KEY_CONTENT = "TestFragment:Content";

    public static DemoFragment newInstance(int content) {
        DemoFragment fragment = new DemoFragment();
        fragment.mContent = content;
        return fragment;
    }

    private int mContent;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if ((savedInstanceState != null) && savedInstanceState.containsKey(KEY_CONTENT)) {
            mContent = savedInstanceState.getInt(KEY_CONTENT);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        ImageView image = new ImageView(getActivity());
        image.setBackgroundResource(mContent);

        LinearLayout layout = new LinearLayout(getActivity());
        layout.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
        layout.setGravity(Gravity.CENTER);
        layout.addView(image);

        return layout;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt(KEY_CONTENT, mContent);
    }
}

Не дивлячись на ваш код, важко щось запропонувати. Якщо ви можете ввести код своєї діяльності, це може допомогти.
Саям

11
ось гарне запитання.
con_9

Відповіді:


79

Поставте свою демо-інформацію в іншу діяльність та надайте їй наступну тему.

<style name="Transparent" parent="@android:style/Theme.NoTitleBar">
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowNoTitle">true</item>      
    <item name="android:backgroundDimEnabled">false</item>
</style>

Якщо ви використовуєте ActionBarSherlock змінити parentна @style/Theme.Sherlock.

Це дасть вам прозорий вид діяльності, тому ви зможете побачити активність під ним.

Тепер я здогадуюсь, що ви хочете і напівпрозорого фону.

У форматі XML (вашої прозорої діяльності) додайте:

android:background="#aa000000" 

Останні 6 цифр визначають колір: 000000 - чорний.

Перші 2 визначають непрозорість: 00 є 100% прозорим, ff - 100% непрозорим. Тож вибирайте щось середнє.


1
Дякую за відповідь! Це майже все, що я в кінцевому підсумку робив, після безлічі спроб і помилок . Мені все ще цікаво, як демонстраційний екран Pulse здатний "переставляти" накладений вміст у потрібних місцях, навіть у різних розмірах екрана - дивіться оновлені скріншоти. Якісь ідеї?
Гаутам

2
У своїй першій діяльності знайдіть подання, на яке хочете вказати ( findViewById). Потім отримайте його положення відносно кореневого макета за допомогою цього методу . Надіслати позицію для накладання активності у намірі. Зробіть правильне вирівнювання.
Беніто Бертолі

2
Або використовувати View.getLocationOnScreen(int[] location)або View.getLocationInWindow(int[] location). Я не впевнений, який із них кращий.
Беніто Бертолі

@Gautam: "Будь-які ідеї?" - для Pulse - це питання розмістити одне зображення у верхньому лівому куті, інше зображення по центру, а третє - у правому нижньому куті. Десяток або близько рядків XML, заснованих на a RelativeLayout, буде достатньо.
CommonsWare

1
Це працювало на мене, але у мене виникли проблеми в моїй діяльності, яка займалася розширеною діяльністю. Отже, для використання AppCompatActivity я визначив такий стиль, як такий: <style name = "Transparent" parent = "Theme.AppCompat"> <item name = "android: windowContentOverlay"> @ null </item> <item name = "android : windowIsTranslucent "> true </item> <item name =" android: windowBackground "> @ android: color / transparent </item> <name name =" android: windowNoTitle "> true </item> <item name =" android : backgroundDimEnabled "> false </item> </style>
Хосе Q

65

Ви подивилися на ShowcaseView? https://github.com/Espiandev/ShowcaseView .

Використовуючи це:

View showcasedView = findViewById(R.id.view_to_showcase);
ViewTarget target = new ViewTarget(showcasedView);
ShowcaseView.insertShowcaseView(target, this, R.string.showcase_title, R.string.showcase_details);

1
Дякую, саме це я шукав.
Snicolas

Дивовижно! Чи знаєте ви щось подібне для iOS?
KVISH

Поки застарілий ... Розробник мав на увазі, що дизайн базового API недостатньо хороший (що частково відповідає дійсності).
Лоран Мейєр

Я спробував це, і виявив, що немає тегу для зміни зображень.
Аншул Тяги

11

Імпульс використовує відносний макет із чотирма ImageView та чотирма TextView. Текст на знімку екрана - це текст TextView зі своїм власним шрифтом.

Додайте у свій Маніфест наступне:

android: theme = "@ style / Theme.Transparent">

До вашого зовнішнього RelativeLayout додайте:

android: background = "# aa000000"

У файл styles.xml:

<style name="Theme.Transparent" parent="android:Theme">
    <item name="android:windowIsTranslucent">true</item>
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowContentOverlay">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowIsFloating">false</item>
    <item name="android:backgroundDimEnabled">false</item>
</style>    

Приклад, як запрограмувати спеціальний шрифт, ви можете знайти на:

https://github.com/commonsguy/cw-android/tree/master/Fonts/FontSampler/

Макет з програми перегляду ієрархії виглядає приблизно так (червоне поле є контейнером RelativeLayout):

введіть тут опис зображення


6
setContentView(R.layout.sample_main);
showOverLay();

private void showOverLay(){

    final Dialog dialog = new Dialog(context, android.R.style.Theme_Translucent_NoTitleBar);

    dialog.setContentView(R.layout.transparent);

    RelativeLayout layout = (RelativeLayout) dialog.findViewById(R.id.transparent);

    layout.setOnClickListener(new View.OnClickListener() {

        @Override

        public void onClick(View arg0) {

            dialog.dismiss();

        }

    });

    dialog.show();

}

саме те, що я шукаю простий і прямий вперед, і легко виклик методу, не контролюючи і не укладаючи дії. спасибі
Абхішек Гарг

5

Для цього вам потрібно створити довідковий макет внизу вашого основного макета, наприклад: (структура)

<Parent layout>

<Layout 1>(Linear,Relative,....)
  Main layout
  your view...
</Layout 1>

<Layout help>
  set #70000000 as background of this layout 
  #70(transparent range can change) 000000(black)
  and height and width as fillparent
</Layout help>

</Parent layout>

2

Оберніть основний макет у RelativeLayout, а потім додайте до нього другий макет, наприклад:

<RelativeLayout
    .... >

    <LinearLayout
        .... >

        <!-- Contents of your main layout -->

    </LinearLayout>

    <LinearLayout
        ....
        android:background="#44000000" > <!-- This is alpha 68/255, black -->

        <!-- Contents of your overlay layout -->

    </LinearLayout>

</RelativeLayout>

Я вважаю, що макет накладання опускається нижче основного макета у файлі XML (якщо використовується пам'ять). Тоді ви можете зробити свій власний макет ViewFlipper, що завгодно, в рамках цього другого макета.


1
Дякую за Вашу відповідь! Я спробував це, і це, здається, працює. Однак є одна проблема - вміст у макеті накладки не охоплює вкладки ActionBar або ActionBar, які я маю в своїй діяльності.
Гаутам

Ви додали файл RelativeLayoutу demo_activity.xmlфайл? А DemoActivityваш головний (перший) Activity?
Ерік

Ну "DemoActivity" була моєю спробою створити прозору діяльність, яка б робила те саме. "MainActivity" - це діяльність, яку я хочу шукати під фоном. Тому я загорнув макет для "MainActivity", тобто "main_activity.xml" з "RelativeLayout", як ви згадали, і також вставив прозорий "LinearLayout". Проблема полягає в тому, що весь вміст у "main_activity.xml" відображається під "ActionBar" та будь-якими його вкладками навігації.
Гаутам

1

Створіть нову діяльність (скажімо Підручник).

Перейдіть до XML-файлу макета вашої діяльності (Activity_tutorial). Під батьківським макетом додайте "android: background = # 000" та "android: alpha =" 0.5 "

<RelativeLayout 
    
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
                
                
    tools:context=".Tutorial_Activity" 
    android:background="#000"
    android:alpha="0.5">
  ..................................................
  ....................................................
  .............................................
  ...............................................
  
  </RelativeLayout>

Тепер перейдіть до файлу маніфесту програми та під вашою діяльністю підручника додайте атрибут android: theme = "@ android: style / Theme.Translucent.NoTitleBar">

<application>
 .........................................
..........................................
....................................
..........................................

<activity
            android:name="com.aird.airdictionary.Tutorial_Activity"
            android:label="@string/title_activity_tutorial"
            
          android:theme="@android:style/Theme.Translucent.NoTitleBar">
  
        </activity>
    </application>

</manifest>

Ось це, тепер запустіть цю діяльність поверх будь-якої іншої діяльності, і ви зможете отримати бажані результати. Налаштуйте, додайте текст, перегляд зображень та інші речі, щоб отримати потрібний екран підручника. Досить впевнений, що з цією технікою можна змусити роботу оглядача.


0

Ви можете просто перевірити код запуску Android, як вони це роблять. Я не знаю там реалізації.

Якби це я, я б (якщо просто проста накладка), щоб ви не закрутили макет для вашої програми, просто створили макет накладки та прикладіть його до макета додатка ур, додавши його безпосередньо до своєї діяльності WindowManager. Це може бути таким же простим, як додавання ImageViewдо WindowManager, слухати дотики до ImageViewабо мати час, який потрібно видалити ImageViewзі свого Window.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.