Bagaimana Anda membuat layar demo transparan untuk aplikasi Android?

105

Saya mencoba membuat layar demo semi-transparan yang diluncurkan hanya saat pengguna pertama kali menginstal aplikasi saya. Berikut ini contoh dari aplikasi Pulse News:

Galaxy Nexus

Contoh tangkapan layar dari Pulse News di Galaxy Nexus

Nexus One

masukkan deskripsi gambar di sini

Alih-alih fitur 'ketuk-untuk-tutup', saya ingin pengguna dapat menggeser melalui beberapa halaman demo transparan seperti itu.

Untuk upaya pertama saya, saya memodifikasi sampel dari perpustakaan ViewPagerIndicator . Saya menggunakan PNG semi-transparan di ImageView di dalam setiap fragmen tampilan halaman. Saya kemudian meluncurkan ini sebagai 'aktivitas demo' dalam metode onCreate dari 'aktivitas utama' saya.

Masalah: 'Aktivitas utama' tidak dapat dilihat di latar belakang - hanya hitam. Saya mencoba solusi di sini , tetapi itu tidak memperbaiki masalah.

Apakah ada pendekatan yang lebih baik untuk menciptakan sesuatu seperti ini, atau apakah saya berada di jalur yang benar?

Saya juga punya pertanyaan terkait lainnya yang bergantung pada bagaimana ini diterapkan. Saya mencoba untuk melapisi teks dan panah sedemikian rupa sehingga mereka menunjuk ke komponen UI tertentu di latar belakang. Dengan menggunakan PNG yang memiliki teks dan panah, kemungkinan besar skala tidak akan benar pada perangkat yang berbeda. Yaitu, panah belum tentu mengarah ke komponen UI yang benar di latar belakang. Apakah ada cara untuk mengatasi masalah ini juga?

Terima kasih!

Ini kode saya untuk percobaan pertama:

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
sumber
Tanpa melihat kode Anda, sulit untuk menyarankan apa pun. Jika Anda dapat memasukkan kode aktivitas Anda, ini mungkin membantu.
Sayyam
11
itu pertanyaan yang bagus.
con_9

Jawaban:

79

Letakkan info demo Anda di aktivitas yang berbeda dan berikan tema berikut.

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

Jika Anda menggunakan ActionBarSherlock, ubah parentke @style/Theme.Sherlock.

Ini akan memberi Anda aktivitas transparan, sehingga Anda bisa melihat aktivitas di bawahnya.

Sekarang saya rasa Anda juga menginginkan latar belakang yang transparan.

Dalam tata letak xml (aktivitas transparan Anda) tambahkan:

android:background="#aa000000" 

6 digit terakhir menentukan warna: 000000 hitam.

2 yang pertama menentukan opasitas: 00 100% transparan, ff 100% buram. Jadi pilihlah sesuatu di antaranya.

Benito Bertoli
sumber
1
Terima kasih atas jawabannya! Inilah yang akhirnya saya lakukan, setelah banyak trial and error . Saya masih penasaran bagaimana layar demo Pulse dapat 'memposisikan ulang' konten yang dihamparkan di tempat yang tepat, bahkan pada ukuran layar yang berbeda - lihat tangkapan layar yang diperbarui. Ada ide?
Gautam
2
Dalam aktivitas pertama Anda, temukan tampilan yang ingin Anda tunjuk ( findViewById). Kemudian dapatkan posisinya yang relatif terhadap tata letak root menggunakan metode ini . Kirim posisi ke aktivitas overlay di maksud. Lakukan penyelarasan yang benar.
Benito Bertoli
2
Atau gunakan View.getLocationOnScreen(int[] location)atau View.getLocationInWindow(int[] location). Saya tidak yakin mana yang lebih baik.
Benito Bertoli
@Gautam: "Ada ide?" - untuk Pulse, ini masalah meletakkan satu gambar di pojok kiri atas, gambar lainnya di tengah, dan gambar ketiga di pojok kanan bawah. Selusin atau lebih baris XML, berdasarkan a RelativeLayout, sudah cukup.
CommonsWare
1
Ini berhasil untuk saya, tetapi saya memiliki masalah dalam aktivitas saya melakukan aktivitas perluasan. Jadi untuk menggunakan AppCompatActivity saya mendefinisikan gaya seperti ini: <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

Pernahkah Anda melihat ShowcaseView? https://github.com/Espiandev/ShowcaseView .

Menggunakan ini:

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
sumber
1
Terima kasih, itulah yang saya cari.
Snicolas
Hebat! Apakah Anda mengetahui hal serupa untuk iOS?
KVISH
Tidak digunakan lagi ... Pengembang berarti desain API dasar tidak cukup baik (yang sebagian benar).
Laurent Meyer
Saya mencoba ini dan saya menemukan bahwa tidak ada tag untuk mengubah gambar.
Anshul Tyagi
11

Pulse menggunakan RelativeLayout dengan empat ImageView dan empat TextView. Teks di tangkapan layar adalah semua TextView dengan font khusus mereka sendiri.

Dalam Manifes Anda, tambahkan yang berikut ini ke Aktivitas Anda:

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

Di luar RelativeLayout Anda tambahkan:

android: background = "# aa000000"

Ke file styles.xml Anda:

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

Contoh bagaimana memprogram font khusus yang dapat Anda temukan di:

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

Tata letak dari Hierarchy Viewer terlihat seperti ini (kotak merahnya adalah penampung RelativeLayout):

masukkan deskripsi gambar di sini

bubuk 366
sumber
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
sumber
persis apa yang saya cari sederhana dan lurus ke depan, dan metode panggilan mudah tanpa mengendalikan atau menumpuk kegiatan. terima kasih
Abhishek Garg
5

Untuk ini, Anda perlu membuat tata letak bantuan di bagian bawah tata letak utama Anda, misalnya: (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
sumber
2

Bungkus tata letak utama Anda dalam a RelativeLayout, lalu tambahkan tata letak kedua ke dalamnya, seperti:

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

Saya yakin tata letak overlay berada di bawah tata letak utama dalam file XML (jika memori berfungsi). Anda kemudian dapat membuat tata letak Anda sendiri ViewFlipper, apa pun yang Anda inginkan dalam tata letak kedua ini.

Eric
sumber
1
Terimakasih atas tanggapan Anda! Saya mencoba ini dan tampaknya berhasil. Namun, ada satu masalah - konten dalam tata letak overlay tidak menutupi ActionBar atau tab ActionBar yang saya miliki dalam aktivitas saya.
Gautam
Anda menambahkan RelativeLayoutke demo_activity.xmlfile? Dan apakah DemoActivityutama Anda (pertama) Activity?
Eric
Nah 'DemoActivity' adalah upaya saya untuk membuat aktivitas transparan yang akan melakukan hal yang sama. 'MainActivity' adalah aktivitas yang saya inginkan di bawahnya di latar belakang. Jadi saya membungkus tata letak untuk 'MainActivity', yaitu 'main_activity.xml' dengan 'RelativeLayout' seperti yang Anda sebutkan dan juga memasukkan 'LinearLayout' transparan. Masalahnya adalah, semua konten di 'main_activity.xml' ditampilkan di bawah 'ActionBar' dan tab navigasinya.
Gautam
1

Buat Aktivitas baru (katakanlah Tutorial).

Pergi ke file xml tata letak Aktivitas Anda (activity_tutorial). Di bawah tata letak induk, tambahkan "android: background = # 000" dan "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>

Sekarang, buka file manifes aplikasi dan di bawah aktivitas tutorial Anda tambahkan atribut 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>

Itu saja, sekarang jalankan aktivitas ini di atas aktivitas lain dan Anda bisa mendapatkan hasil yang diinginkan. Kustomisasi, tambahkan teks, tampilan gambar, dan hal-hal lain untuk mendapatkan layar tutorial yang Anda inginkan. Cukup yakin bahwa Anda bisa membuat viewpager berfungsi dengan teknik ini.

Ankush Wadhwa
sumber
0

Anda bisa melihat kode peluncur Android, saat mereka melakukannya. Saya tidak tahu ada implementasi.

Jika itu saya, saya akan (jika hanya overlay sederhana) sehingga Anda tidak mengacaukan tata letak Anda untuk aplikasi Anda, cukup buat tata letak overlay Anda, dan lampirkan di atas tata letak aplikasi Anda dengan menambahkannya langsung dengan aktivitas Anda WindowManager. Bisa sesederhana menambahkan ImageViewke WindowManager, mendengarkan sentuhan di ImageView, atau memiliki waktu tunggu untuk menghapus ImageViewdari Window.

Jug6ernaut
sumber