Jak stworzyć przejrzysty ekran demonstracyjny dla aplikacji na Androida?

105

Próbuję utworzyć półprzezroczysty ekran demonstracyjny, który jest uruchamiany tylko wtedy, gdy użytkownik po raz pierwszy instaluje moją aplikację. Oto przykład z aplikacji Pulse News:

Galaxy Nexus

Przykładowy zrzut ekranu z Pulse News na Galaxy Nexus

Nexus One

wprowadź opis obrazu tutaj

Zamiast funkcji „dotknij, aby odrzucić”, chcę, aby użytkownik mógł przeglądać kilka takich przezroczystych stron demonstracyjnych.

Przy pierwszej próbie zmodyfikowałem próbkę z biblioteki ViewPagerIndicator . Użyłem półprzezroczystych plików PNG w ImageViews wewnątrz każdego fragmentu pagera widoku. Następnie uruchomiłem to jako „działanie demonstracyjne” w metodzie onCreate mojej „głównej aktywności”.

Problem: „Główna czynność” nie była widoczna w tle - zamiast tego była po prostu czarna. Wypróbowałem tutaj rozwiązania , ale to nie rozwiązało problemu.

Czy jest lepsze podejście do tworzenia czegoś takiego, czy jestem na dobrej drodze?

Miałem też inne powiązane pytanie, które zależy od tego, jak jest to realizowane. Próbuję nałożyć tekst i strzałki w taki sposób, aby wskazywały na poszczególne elementy interfejsu użytkownika w tle. Używając pliku PNG zawierającego tekst i strzałki, prawdopodobnie nie będzie on poprawnie skalowany na różnych urządzeniach. Oznacza to, że strzałki niekoniecznie muszą wskazywać właściwy składnik interfejsu użytkownika w tle. Czy jest sposób na rozwiązanie również tego problemu?

Dzięki!

Oto mój kod do pierwszej próby:

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);
    }
}
Gautam
źródło
Bez patrzenia na kod trudno cokolwiek zasugerować. Gdybyś mógł umieścić swój kod aktywności, mogłoby to pomóc.
Sayyam
11
to dobre pytanie.
con_9

Odpowiedzi:

79

Umieść informacje demonstracyjne w innym działaniu i nadaj im następujący motyw.

<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>

Jeśli używasz ActionBarSherlock, zmień parentna @style/Theme.Sherlock.

Zapewni to przejrzystą aktywność, dzięki czemu będziesz mógł zobaczyć aktywność poniżej.

Domyślam się, że chcesz mieć również przezroczyste tło.

W układzie xml (Twojej przezroczystej aktywności) dodaj:

android:background="#aa000000" 

Ostatnie 6 cyfr określa kolor: 000000 to czarny.

Pierwsze 2 definiują krycie: 00 jest przezroczystością 100%, ff jest nieprzezroczysta 100%. Więc wybierz coś pomiędzy.

Benito Bertoli
źródło
1
Dziękuję za odpowiedź! Tak właśnie skończyłem, po wielu próbach i błędach . Nadal jestem ciekawy, w jaki sposób ekran demonstracyjny Pulse jest w stanie `` zmienić położenie '' nałożonych treści w odpowiednich miejscach, nawet na różnych rozmiarach ekranu - zobacz zaktualizowane zrzuty ekranu. Jakieś pomysły?
Gautam
2
W pierwszym działaniu znajdź widok, który chcesz wskazać ( findViewById). Następnie uzyskaj jego pozycję względem układu głównego za pomocą tej metody . Wyślij pozycję, aby nakładać aktywność w zamiarze. Wykonaj właściwe wyrównanie.
Benito Bertoli
2
Lub użyj View.getLocationOnScreen(int[] location)lub View.getLocationInWindow(int[] location). Nie jestem pewien, który jest lepszy.
Benito Bertoli
@Gautam: "Jakieś pomysły?" - w przypadku Pulse jest to kwestia umieszczenia jednego obrazu w lewym górnym rogu, innego obrazu w środku, a trzeciego w prawym dolnym rogu. Wystarczy kilkanaście wierszy XML opartych na a RelativeLayout.
CommonsWare
1
To zadziałało dla mnie, ale miałem problemy z wykonywaniem Rozszerzonej Aktywności. Aby użyć AppCompatActivity, zdefiniowałem następujący styl: <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> <item name =" android: windowNoTitle "> true </item> <item name =" android : backgroundDimEnabled "> false </item> </style>
Jose Q
65

Czy spojrzałeś na ShowcaseView? https://github.com/Espiandev/ShowcaseView .

Używając tego:

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);
Nik
źródło
1
Dzięki, właśnie tego szukałem.
Snicolas
Niesamowite! Czy znasz coś podobnego na iOS?
KVISH
Wycofane jeszcze ... Developer oznaczał, że projekt podstawowego API nie był wystarczająco dobry (co było częściowo prawdą).
Laurent Meyer
Próbowałem tego i stwierdziłem, że nie ma tagu do zmiany obrazów.
Anshul Tyagi
11

Pulse używa RelativeLayout z czterema ImageView i czterema TextView. Tekst na zrzucie ekranu to TextView z własną niestandardową czcionką.

W swoim Manifeście dodaj następujące informacje do swojej Aktywności:

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

W swoim zewnętrznym RelativeLayout dodaj:

android: background = "# aa000000"

Do pliku 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>    

Przykład programowania niestandardowej czcionki można znaleźć pod adresem:

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

Układ z przeglądarki hierarchii wygląda następująco (czerwone pole to kontener RelativeLayout):

wprowadź opis obrazu tutaj

proszek 366
źródło
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();

}
Ravikiran
źródło
dokładnie to, czego szukam, proste i proste i łatwe wywołanie metody bez kontrolowania lub nakładania działań. dzięki
Abhishek Garg
5

W tym celu musisz utworzyć układ pomocy w dolnej części głównego układu, np .: (struktura)

<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>
Surendar D.
źródło
2

Owiń swój główny układ w a RelativeLayout, a następnie dodaj do niego drugi układ, na przykład:

<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>

Uważam, że układ nakładki znajduje się poniżej głównego układu w pliku XML (jeśli pamięć służy). Następnie możesz utworzyć własny układ ViewFlipper, cokolwiek chcesz w tym drugim układzie.

Eric
źródło
1
Dzięki za twoją odpowiedź! Próbowałem tego i wydaje się, że działa. Jest jednak jeden problem - zawartość w układzie nakładki nie zakrywa kart ActionBar ani ActionBar, które mam w mojej aktywności.
Gautam
Dodałeś RelativeLayoutdo demo_activity.xmlpliku? A czy DemoActivitytwój główny (pierwszy) Activity?
Eric
Cóż, „DemoActivity” było moją próbą stworzenia przejrzystego działania, które robiłoby to samo. „MainActivity” to działanie, które chcę ukryć w tle. Więc zawinąłem układ dla „MainActivity”, czyli „main_activity.xml” z „RelativeLayout”, jak wspomniałeś, a także wstawiłem przezroczysty „LinearLayout”. Problem polega na tym, że cała zawartość „main_activity.xml” jest wyświetlana poniżej „ActionBar” i wszystkich jego kart nawigacyjnych.
Gautam
1

Zrób nowe ćwiczenie (powiedz Samouczek).

Przejdź do pliku układu xml swojego działania (activity_tutorial). W układzie nadrzędnym dodaj „android: background = # 000” i „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>

Teraz przejdź do pliku manifestu aplikacji i w obszarze aktywności samouczka dodaj atrybut 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>

To wszystko, teraz uruchom to ćwiczenie razem z innymi działaniami, a uzyskasz pożądane rezultaty. Dostosuj, dodaj tekst, widoki obrazów i inne rzeczy, aby uzyskać pożądany ekran samouczka. Jestem prawie pewien, że możesz sprawić, by przeglądarka działała z tą techniką.

Ankush Wadhwa
źródło
0

Możesz po prostu sprawdzić kod programu uruchamiającego Androida, tak jak to robią. Nie znam tam realizacji.

Gdybym to był ja, zrobiłbym to (gdyby była to zwykła nakładka), więc nie wkręcaj w układ swojej aplikacji, po prostu utwórz układ nakładki i dołącz go do układu aplikacji, dodając go bezpośrednio do swoich działań WindowManager. Może być tak proste, jak dodanie a ImageViewdo WindowManager, nasłuchiwanie dotknięć ImageViewlub czas na usunięcie ImageViewz Window.

Jug6ernaut
źródło