¿Cómo se crea una pantalla de demostración transparente para una aplicación de Android?

105

Estoy intentando crear una pantalla de demostración semitransparente que se inicia solo cuando un usuario instala por primera vez mi aplicación. Aquí hay un ejemplo de la aplicación Pulse News:

Galaxy Nexus

Captura de pantalla de ejemplo de Pulse News en Galaxy Nexus

Nexus One

ingrese la descripción de la imagen aquí

En lugar de una función de 'tocar para descartar', quiero que el usuario pueda deslizar un par de páginas de demostración transparentes.

Para mi primer intento, modifiqué una muestra de la biblioteca ViewPagerIndicator . Usé PNG semitransparentes en ImageViews dentro de cada uno de los fragmentos del paginador de vistas. Luego lo lancé como una 'actividad de demostración' en el método onCreate de mi 'actividad principal'.

Problema: La 'actividad principal' no se podía ver de fondo, sino que era simplemente negra. Probé las soluciones aquí , pero eso no solucionó el problema.

¿Existe un mejor enfoque para crear algo como esto, o estoy en el camino correcto?

También tuve otra pregunta relacionada que depende de cómo se implemente. Estoy tratando de superponer texto y flechas de manera que apunten a componentes particulares de la interfaz de usuario en segundo plano. Al usar un PNG que tiene el texto y las flechas, es probable que no se escale correctamente en diferentes dispositivos. Es decir, es posible que las flechas no apunten necesariamente al componente de IU correcto en segundo plano. ¿Hay alguna forma de abordar este problema también?

¡Gracias!

Aquí está mi código para el primer intento:

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);
    }
}
Gautama
fuente
Sin mirar su código, es difícil sugerir nada. Si pudiera poner su código de actividad, podría ayudar.
Sayyam
11
buena pregunta.
con_9

Respuestas:

79

Pon tu información de demostración en una actividad diferente y dale el siguiente tema.

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

Si está utilizando ActionBarSherlock, cambie parenta @style/Theme.Sherlock.

Esto le dará una actividad transparente, por lo que podrá ver la actividad debajo.

Ahora supongo que también querrás un fondo translúcido.

En el diseño xml (de su actividad transparente) agregue:

android:background="#aa000000" 

Los últimos 6 dígitos definen el color: 000000 es negro.

Los 2 primeros definen la opacidad: 00 es 100% transparente, ff es 100% opaco. Así que elige algo intermedio.

Benito Bertoli
fuente
1
¡Gracias por la respuesta! Esto es más o menos lo que terminé haciendo, después de mucho ensayo y error . Todavía tengo curiosidad por saber cómo la pantalla de demostración de Pulse puede 'reposicionar' el contenido superpuesto en los lugares correctos, incluso en diferentes tamaños de pantalla; vea las capturas de pantalla actualizadas. ¿Algunas ideas?
Gautam
2
En su primera actividad, busque la vista a la que desea apuntar ( findViewById). Luego, obtenga su posición relativa al diseño de la raíz usando este método . Enviar posición para superponer la actividad en la intención. Realice una alineación adecuada.
Benito Bertoli
2
O use View.getLocationOnScreen(int[] location)o View.getLocationInWindow(int[] location). No estoy seguro de cuál es mejor.
Benito Bertoli
@Gautam: "¿Alguna idea?" - para Pulse, se trata de poner una imagen en la esquina superior izquierda, otra imagen centrada y una tercera imagen en la esquina inferior derecha. RelativeLayoutBastaría con una docena de líneas de XML, basadas en a .
CommonsWare
1
Esto funcionó para mí, pero tuve problemas en mis actividades al realizar la actividad extendida. Entonces, para usar AppCompatActivity, definí el estilo así: <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

¿Ha mirado ShowcaseView? https://github.com/Espiandev/ShowcaseView .

Usando esto:

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
fuente
1
Gracias, eso es exactamente lo que estaba buscando.
Snicolas
¡Increíble! ¿Conoces algo similar para iOS?
KVISH
En desuso todavía ... El desarrollador quería decir que el diseño de la API básica no era lo suficientemente bueno (lo cual era parcialmente cierto).
Laurent Meyer
Intenté esto y descubrí que no hay una etiqueta para cambiar las imágenes.
Anshul Tyagi
11

Pulse está utilizando un RelativeLayout con cuatro ImageView y cuatro TextView. El texto de la captura de pantalla es todo TextView con su propia fuente personalizada.

En su manifiesto, agregue lo siguiente a su actividad:

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

En su RelativeLayout externo agregue:

android: background = "# aa000000"

A su archivo 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>    

Un ejemplo de cómo programar la fuente personalizada que puede encontrar en:

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

El diseño del visor de jerarquía se ve así (el cuadro rojo es el contenedor RelativeLayout):

ingrese la descripción de la imagen aquí

polvo366
fuente
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
fuente
exactamente lo que busco simple y directo, y fácilmente método de llamada sin controlar o apilar actividades. gracias
Abhishek Garg
5

Para esto, necesita crear un diseño de ayuda en la parte inferior de su diseño principal, por ejemplo: (estructura)

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

Envuelva su diseño principal en a RelativeLayout, luego agregue un segundo diseño, algo como:

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

Creo que el diseño de superposición va debajo del diseño principal en el archivo XML (si la memoria sirve). A continuación, puede hacer su propio diseño ViewFlipper, lo que desee dentro de este segundo diseño.

Eric
fuente
1
¡Gracias por su respuesta! Intenté esto y parece funcionar. Sin embargo, hay un problema: el contenido en el diseño de superposición no cubre las pestañas ActionBar o ActionBar que tengo en mi actividad.
Gautam
¿Agregaste el RelativeLayoutal demo_activity.xmlarchivo? ¿Y es DemoActivitytu principal (primero) Activity?
Eric
Bueno, 'DemoActivity' fue mi intento de crear una actividad transparente que hiciera lo mismo. 'MainActivity' es la actividad que quiero debajo en segundo plano. Así que envolví el diseño de 'MainActivity', es decir, 'main_activity.xml' con el 'RelativeLayout' como mencionaste y también inserté el 'LinearLayout' transparente. El problema es que todo el contenido de 'main_activity.xml' se muestra debajo de la 'ActionBar' y cualquiera de sus pestañas de navegación.
Gautam
1

Haga una nueva actividad (digamos Tutorial).

Vaya al archivo xml de diseño de su actividad (activity_tutorial). En el diseño principal, agregue "android: background = # 000" y "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>

Ahora, vaya al archivo de manifiesto de la aplicación y en la actividad del tutorial agregue el atributo 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>

Eso es todo, ahora ejecute esta actividad sobre cualquier otra actividad y podrá obtener los resultados deseados. Personalice, agregue texto, vistas de imágenes y otras cosas para obtener la pantalla del tutorial que desee. Estoy bastante seguro de que puede hacer que un visor funcione con esta técnica.

Ankush Wadhwa
fuente
0

Podrías ver el código de inicio de Android, mientras lo hacen. No sé que hay implementación.

Si fuera yo, lo haría (si solo fuera una simple superposición) para que no arruine el diseño de su aplicación, solo cree su diseño de superposición y adjúntelo sobre el diseño de su aplicación agregándolo directamente con sus actividades WindowManager. Podría ser tan simple como agregar un ImageViewal WindowManager, escuchar los toques del ImageViewo tener un tiempo de espera para eliminar el ImageViewdel Window.

Jug6ernaut
fuente