Wie erstellen Sie einen transparenten Demobildschirm für eine Android-App?

105

Ich versuche, einen halbtransparenten Demobildschirm zu erstellen, der nur gestartet wird, wenn ein Benutzer meine Anwendung zum ersten Mal installiert. Hier ist ein Beispiel aus der Pulse News App:

Nexus Galaxie

Beispiel-Screenshot von Pulse News auf dem Galaxy Nexus

Nexus Eins

Geben Sie hier die Bildbeschreibung ein

Anstelle einer Funktion zum Tippen zum Entlassen möchte ich, dass der Benutzer durch einige dieser transparenten Demoseiten wischen kann.

Bei meinem ersten Versuch habe ich ein Beispiel aus der ViewPagerIndicator- Bibliothek geändert . Ich habe in ImageViews in jedem Fragment des View Pagers halbtransparente PNGs verwendet. Ich habe dies dann als 'Demo-Aktivität' in der onCreate-Methode meiner 'Hauptaktivität' gestartet.

Problem: Die 'Hauptaktivität' war nicht im Hintergrund zu sehen - stattdessen war sie nur schwarz. Ich versuchte , die Lösungen hier , aber das hat nicht das Problem zu beheben.

Gibt es einen besseren Ansatz, um so etwas zu schaffen, oder bin ich auf dem richtigen Weg?

Ich hatte auch eine andere verwandte Frage, die davon abhängt, wie dies umgesetzt wird. Ich versuche, Text und Pfeile so zu überlagern, dass sie auf bestimmte UI-Komponenten im Hintergrund zeigen. Wenn Sie ein PNG mit Text und Pfeilen verwenden, wird es wahrscheinlich auf verschiedenen Geräten nicht richtig skaliert. Das heißt, die Pfeile müssen nicht unbedingt auf die richtige UI-Komponente im Hintergrund zeigen. Gibt es eine Möglichkeit, dieses Problem ebenfalls anzugehen?

Vielen Dank!

Hier ist mein Code für den ersten Versuch:

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
quelle
Ohne auf Ihren Code zu schauen, ist es schwierig, etwas vorzuschlagen. Wenn Sie Ihren Aktivitätscode eingeben könnten, könnte dies hilfreich sein.
Sayyam
11
Das ist eine gute Frage.
con_9

Antworten:

79

Stellen Sie Ihre Demo-Informationen in eine andere Aktivität und geben Sie ihr das folgende Thema.

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

Wenn Sie ActionBarSherlock verwenden, wechseln Sie parentzu @style/Theme.Sherlock.

Dadurch erhalten Sie eine transparente Aktivität, sodass Sie die Aktivität darunter sehen können.

Jetzt wollen Sie wohl auch einen durchscheinenden Hintergrund.

Fügen Sie im XML-Layout (Ihrer transparenten Aktivität) Folgendes hinzu:

android:background="#aa000000" 

Die letzten 6 Ziffern definieren die Farbe: 000000 ist schwarz.

Die ersten 2 definieren die Deckkraft: 00 ist 100% transparent, ff ist 100% undurchsichtig. Wählen Sie also etwas dazwischen.

Benito Bertoli
quelle
1
Danke für die Antwort! Dies ist ziemlich genau das, was ich nach viel Versuch und Irrtum getan habe . Ich bin immer noch gespannt, wie der Pulse-Demo-Bildschirm den überlagerten Inhalt auch auf verschiedenen Bildschirmgrößen an den richtigen Stellen neu positionieren kann - siehe die aktualisierten Screenshots. Irgendwelche Ideen?
Gautam
2
Suchen Sie in Ihrer ersten Aktivität die Ansicht, auf die Sie zeigen möchten ( findViewById). Ermitteln Sie dann mit dieser Methode die Position relativ zum Root-Layout . Position an Overlay-Aktivität in der Absicht senden. Richtig ausrichten.
Benito Bertoli
2
Oder verwenden Sie View.getLocationOnScreen(int[] location)oder View.getLocationInWindow(int[] location). Ich bin mir nicht sicher, welches besser ist.
Benito Bertoli
@ Gautam: "Irgendwelche Ideen?" - Für Pulse geht es darum, ein Bild in der oberen linken Ecke, ein anderes Bild zentriert und ein drittes Bild in der unteren rechten Ecke zu platzieren. Ein Dutzend XML-Zeilen, basierend auf a RelativeLayout, würden ausreichen.
CommonsWare
1
Dies funktionierte für mich, aber ich hatte Probleme bei meinen Aktivitäten, Aktivitäten zu erweitern. Um AppCompatActivity verwenden zu können, habe ich den Stil folgendermaßen definiert: <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

Haben Sie sich ShowcaseView angesehen? https://github.com/Espiandev/ShowcaseView .

Verwenden Sie diese:

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
quelle
1
Danke, genau das habe ich gesucht.
Snicolas
Genial! Kennen Sie etwas Ähnliches für iOS?
KVISH
Noch veraltet ... Entwickler meinten, das Design der Basis-API sei nicht gut genug (was teilweise zutraf).
Laurent Meyer
Ich habe es versucht und festgestellt, dass es kein Tag zum Ändern von Bildern gibt.
Anshul Tyagi
11

Pulse verwendet ein RelativeLayout mit vier ImageViews und vier TextViews. Der Text im Screenshot besteht ausschließlich aus TextViews mit einer eigenen benutzerdefinierten Schriftart.

Fügen Sie in Ihrem Manifest Folgendes zu Ihrer Aktivität hinzu:

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

Fügen Sie Ihrem äußeren RelativeLayout Folgendes hinzu:

android: background = "# aa000000"

Zu Ihrer Datei 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>    

Ein Beispiel für die Programmierung der benutzerdefinierten Schriftart finden Sie unter:

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

Das Layout im Hierarchy Viewer sieht folgendermaßen aus (das rote Feld ist der RelativeLayout-Container):

Geben Sie hier die Bildbeschreibung ein

Pulver366
quelle
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
quelle
genau das, wonach ich suche einfach und unkompliziert und einfach Methodenaufruf ohne Kontrolle oder Stapelung von Aktivitäten. danke
Abhishek Garg
5

Dazu müssen Sie unten im Hauptlayout ein Hilfelayout erstellen, z. B.: (Struktur)

<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.
quelle
2

Wickeln Sie Ihr Hauptlayout in ein RelativeLayoutund fügen Sie dann ein zweites Layout hinzu, etwa:

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

Ich glaube, das Overlay-Layout unterschreitet das Hauptlayout in der XML-Datei (sofern Speicherplatz zur Verfügung steht). Sie können dann Ihr eigenes Layout ViewFlippererstellen, was auch immer Sie in diesem zweiten Layout möchten.

Eric
quelle
1
Vielen Dank für Ihre Antwort! Ich habe es versucht und es scheint zu funktionieren. Es gibt jedoch ein Problem: Der Inhalt im Overlay-Layout deckt nicht die ActionBar- oder ActionBar-Registerkarten ab, die ich in meiner Aktivität habe.
Gautam
Sie haben das RelativeLayoutder demo_activity.xmlDatei hinzugefügt ? Und ist DemoActivitydein Haupt (erster) Activity?
Eric
Nun, 'DemoActivity' war mein Versuch, eine transparente Aktivität zu erstellen, die dasselbe tun würde. 'MainActivity' ist die Aktivität, die ich unten im Hintergrund sehen möchte. Also habe ich das Layout für 'MainActivity', dh 'main_activity.xml', mit dem 'RelativeLayout' wie von Ihnen erwähnt verpackt und auch das transparente 'LinearLayout' eingefügt. Das Problem ist, dass der gesamte Inhalt in 'main_activity.xml' unter der 'ActionBar' und einer der Navigationsregisterkarten angezeigt wird.
Gautam
1

Machen Sie eine neue Aktivität (sagen wir Tutorial).

Wechseln Sie zur Layout-XML-Datei Ihrer Aktivität (activity_tutorial). Fügen Sie unter dem übergeordneten Layout "android: background = # 000" und "android: alpha =" 0.5 "hinzu.

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

Gehen Sie nun zur Anwendungsmanifestdatei und fügen Sie unter Ihrer Lernaktivität das Attribut android: theme = "@ android: style / Theme.Translucent.NoTitleBar"> hinzu

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

Führen Sie diese Aktivität jetzt über jede andere Aktivität aus, und Sie können die gewünschten Ergebnisse erzielen. Passen Sie Text, Bildansichten und andere Dinge an, fügen Sie sie hinzu, um den gewünschten Tutorial-Bildschirm zu erhalten. Ziemlich sicher, dass Sie einen Viewpager mit dieser Technik zum Laufen bringen können.

Ankush Wadhwa
quelle
0

Sie können einfach den Android-Launcher-Code überprüfen, während sie es tun. Ich kenne dort keine Umsetzung.

Wenn ich es wäre, würde ich (wenn nur eine einfache Überlagerung), damit Sie nicht mit Ihrem Layout für Ihre Anwendung schrauben, erstellen Sie einfach Ihr Überlagerungslayout und hängen Sie es über Ihr Anwendungslayout an, indem Sie es direkt mit Ihren Aktivitäten hinzufügen WindowManager. Könnte so einfach sein wie das Hinzufügen eines ImageViewzu WindowManager, das Abhören von Berührungen des ImageViewoder eine Zeitüberschreitung, um das ImageViewvon Ihrem zu entfernen Window.

Jug6ernaut
quelle