Bagaimana cara _ benar-benar secara terprogram mengubah warna dasar dan aksen di Android Lollipop?


156

Pertama-tama, pertanyaan ini menanyakan pertanyaan yang sangat mirip. Namun, pertanyaan saya memiliki perbedaan tipis.

Yang ingin saya ketahui adalah apakah mungkin secara terprogram mengubah colorPrimaryatribut suatu tema menjadi warna yang sewenang - wenang ?

Jadi misalnya, kita memiliki:

<style name="AppTheme" parent="android:Theme.Material.Light">
    <item name="android:colorPrimary">#ff0000</item>
    <item name="android:colorAccent">#ff0000</item>
</style>

Saat runtime, pengguna memutuskan ingin menggunakan #ccffffsebagai warna utama. Tentu saya tidak bisa membuat tema untuk semua warna yang memungkinkan.

Saya tidak keberatan jika saya harus melakukan hal-hal yang peretasan, seperti mengandalkan internal pribadi Android, selama itu bekerja menggunakan SDK publik.

Tujuan saya adalah untuk akhirnya memiliki ActionBar dan semua widget ingin CheckBoxmenggunakan warna primer ini.


1
Anda tidak tahu apa itu "internal pribadi Android" untuk rilis Android yang tidak ada. Jangan berasumsi bahwa "internal privat" L adalah sama dengan yang untuk apa pun L berubah dalam hal rilis produksi.
CommonsWare

Tidak, Anda tidak dapat menempatkan data sewenang-wenang ke dalam tema. Yang mengatakan, colorPrimary hanya digunakan untuk latar belakang bilah tindakan, warna bar terkini, dan warna pemberitahuan dan Anda dapat mengubah semua ini secara dinamis.
alanv

2
Saya pikir Anda harus bertanya "Bagaimana mengubah atribut style dalam runtime", dan dari apa yang saya lihat jawabannya adalah Anda tidak bisa. Namun saya punya ide yang mungkin bisa membantu Anda. Gunakan ContextWrapper kustom dan berikan Sumberdaya sendiri. Lihat ini: github.com/negusoft/holoaccent/blob/master/HoloAccent/src/com/... Secara keseluruhan proyek ini mungkin memberi Anda ide bagaimana melakukan itu.
Mikooos

1
Hanya brainfarting di sini, tetapi semua XML akan dikonversi menjadi file .dex yang dimuat ke aplikasi android Anda sebagai objek java yang benar. Bukankah itu berarti kita harus dapat membuat dan mengatur seluruh tema dari kode serta menghasilkan tema dari pabrik yang belum ditulis? Kedengarannya seperti banyak pekerjaan.
G_V

1
@NiekHaarman apakah Anda pernah menemukan cara?
gbhall

Jawaban:


187

Tema tidak berubah, Anda tidak bisa.


8
Terima kasih, Chris! Bukan jawaban yang saya cari, tapi saya rasa saya harus hidup dengannya :)
nhaarman

5
Hai @Chris Banes, tetapi bagaimana aplikasi kontak mengubah warna bilah status dan warna bilah alat sesuai dengan warna tema kontak? Jika memungkinkan, saya pikir apa yang dibutuhkan Niek Haarman tidak terlalu jauh karena dia hanya perlu menyimpan kode warna yang diinginkan pengguna. Bisakah Anda menjelaskan lebih lanjut tentang ini? Saya juga ingin membuat sesuatu seperti ini tetapi saya benar-benar bingung dengannya.
Swan

39
Warna Bilah Status dapat diubah secara dinamis melalui Window.setStatusBarColor ().
Chris Banes

9
Apakah mungkin membuat tema secara terprogram?
Andrew Orobator

3
Dan sambil mengubah warna bilah status secara dinamis, Anda juga dapat mengubah warna bilah navigasi melalui Window.setNavigationBarColor () - API 21 :)
user802421

65

Saya membaca komentar tentang aplikasi kontak dan bagaimana menggunakan tema untuk setiap kontak.

Mungkin, aplikasi kontak memiliki beberapa tema yang telah ditentukan sebelumnya (untuk setiap warna primer materi dari sini: http://www.google.com/design/spec/style/color.html ).

Anda dapat menerapkan tema sebelum metode setContentView di dalam metode onCreate.

Kemudian aplikasi kontak dapat menerapkan tema secara acak untuk setiap pengguna.

Metode ini adalah:

setTheme(R.style.MyRandomTheme);

Tetapi metode ini memiliki masalah, misalnya dapat mengubah warna bilah alat, warna efek gulir, warna riak, dll, tetapi tidak dapat mengubah warna bilah status dan warna bilah navigasi (jika Anda ingin mengubahnya juga).

Kemudian untuk mengatasi masalah ini, Anda dapat menggunakan metode ini sebelumnya dan:

if (Build.VERSION.SDK_INT >= 21) {
        getWindow().setNavigationBarColor(getResources().getColor(R.color.md_red_500));
        getWindow().setStatusBarColor(getResources().getColor(R.color.md_red_700));
    }

Dua metode ini mengubah warna bilah navigasi dan status. Ingat, jika Anda mengatur bilah navigasi Anda tembus, Anda tidak dapat mengubah warnanya.

Ini harus menjadi kode terakhir:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setTheme(R.style.MyRandomTheme);
    if (Build.VERSION.SDK_INT >= 21) {
        getWindow().setNavigationBarColor(getResources().getColor(R.color.myrandomcolor1));
        getWindow().setStatusBarColor(getResources().getColor(R.color.myrandomcolor2));
    }
    setContentView(R.layout.activity_main);

}

Anda dapat menggunakan sakelar dan menghasilkan nomor acak untuk menggunakan tema acak, atau, seperti di aplikasi kontak, setiap kontak mungkin memiliki nomor yang telah ditentukan terkait.

Contoh tema:

<style name="MyRandomTheme" parent="Theme.AppCompat.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/myrandomcolor1</item>
    <item name="colorPrimaryDark">@color/myrandomcolor2</item>
    <item name="android:navigationBarColor">@color/myrandomcolor1</item>
</style>

Maaf untuk bahasa inggris saya.


1
Terima kasih atas jawaban Anda. Sayangnya, permintaan saya adalah menggunakan warna yang sewenang - wenang . Tentu saja tidak layak untuk membuat tema untuk semua warna.
nhaarman

1
@DanielGomezRico - AFAIK Anda dapat mengesampingkan tema yang telah ditetapkan sebelumnya terlepas dari di mana pengaturan awalnya - selama Anda melakukannya cukup awal. Seperti jawaban mengatakan "Anda dapat menerapkan tema sebelum metode setContentView di dalam metode onCreate."
ToolmakerSteve

50

Anda dapat menggunakan Theme.applyStyle untuk mengubah tema saat runtime dengan menerapkan gaya lain ke dalamnya.

Katakanlah Anda memiliki definisi gaya ini:

<style name="DefaultTheme" parent="Theme.AppCompat.Light">
    <item name="colorPrimary">@color/md_lime_500</item>
    <item name="colorPrimaryDark">@color/md_lime_700</item>
    <item name="colorAccent">@color/md_amber_A400</item>
</style>

<style name="OverlayPrimaryColorRed">
    <item name="colorPrimary">@color/md_red_500</item>
    <item name="colorPrimaryDark">@color/md_red_700</item>
</style>

<style name="OverlayPrimaryColorGreen">
    <item name="colorPrimary">@color/md_green_500</item>
    <item name="colorPrimaryDark">@color/md_green_700</item>
</style>

<style name="OverlayPrimaryColorBlue">
    <item name="colorPrimary">@color/md_blue_500</item>
    <item name="colorPrimaryDark">@color/md_blue_700</item>
</style>

Sekarang Anda dapat menambal tema Anda saat runtime seperti:

getTheme().applyStyle(R.style.OverlayPrimaryColorGreen, true);

Metode applyStyleini harus dipanggil sebelum tata letak meningkat! Jadi, kecuali jika Anda memuat tampilan secara manual, Anda harus menerapkan gaya ke tema sebelum memanggil setContentViewaktivitas Anda.

Tentu saja ini tidak dapat digunakan untuk menentukan warna yang berubah-ubah, yaitu satu dari 16 juta (256 3 ) warna. Tetapi jika Anda menulis sebuah program kecil yang menghasilkan definisi gaya dan kode Java untuk Anda, maka sesuatu seperti satu dari 512 (8 3 ) harus dimungkinkan.

Apa yang membuat ini menarik adalah bahwa Anda dapat menggunakan overlay gaya yang berbeda untuk berbagai aspek tema Anda. colorAccentMisalnya , tambahkan beberapa definisi overlay . Sekarang Anda dapat menggabungkan nilai yang berbeda untuk warna primer dan warna aksen dengan hampir sewenang-wenang.

Anda harus memastikan bahwa definisi tema overlay Anda tidak sengaja mewarisi sekelompok definisi gaya dari definisi gaya induk. Misalnya gaya yang disebut AppTheme.OverlayRedsecara implisit mewarisi semua gaya yang didefinisikan AppThemedan semua definisi ini juga akan diterapkan ketika Anda menambal tema master. Jadi hindari titik-titik dalam nama tema overlay atau gunakan sesuatu seperti Overlay.Reddan definisikan Overlaysebagai gaya kosong.


11
Coba panggil applyStylesebelum memanggil setContentViewaktivitas Anda dan itu pasti berhasil.
devconsole

1
ya okai, maka mungkin berhasil! Saya sedang mencari cara untuk mengubah coloraccent di fragmen niveau bukan aktivitas! itulah sebabnya itu tidak bekerja untuk saya dengan sedih: <Kasus penggunaan saya adalah saya ingin warna yang berbeda untuk FAB atau indikator tab ketika beralih dari tab yang akan memulai fragmen yang berbeda!
Dennis Anderson

Terima kasih, ini banyak membantu! Namun, saya tidak dapat melakukannya berkali-kali. (satu untuk colorPrimary, satu untuk colorAccent, dll). Bisakah kamu membantuku? Terima kasih. stackoverflow.com/questions/41779821/…
Thomas Vos

1
Itulah jawaban yang ingin saya gunakan akun kedua hanya untuk memberi +1 sekali lagi. Terima kasih.
Benoit Duffez

Terima kasih banyak, inilah yang saya cari .... saya harap saya dapat mengubah warna Aksen tema saat ini menggunakan pendekatan ini.
Nasib

32

Saya telah menciptakan beberapa solusi untuk membuat tema warna apa saja, mungkin ini dapat bermanfaat bagi seseorang. API 9+

1. pertama buat " res / values-v9 / " dan letakkan di sana file ini: styles.xml dan folder "res / values" biasa akan digunakan dengan gaya Anda.

2. masukkan kode ini di res / values ​​/ styles.xml Anda:

<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <item name="colorPrimary">#000</item>
        <item name="colorPrimaryDark">#000</item>
        <item name="colorAccent">#000</item>
        <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
    </style>

    <style name="AppThemeDarkActionBar" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">#000</item>
        <item name="colorPrimaryDark">#000</item>
        <item name="colorAccent">#000</item>
        <item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
    </style>

    <style name="WindowAnimationTransition">
        <item name="android:windowEnterAnimation">@android:anim/fade_in</item>
        <item name="android:windowExitAnimation">@android:anim/fade_out</item>
    </style>
</resources>

3. masuk ke AndroidManifest:

<application android:theme="@style/AppThemeDarkActionBar">

4. buat kelas baru dengan nama "ThemeColors.java"

public class ThemeColors {

    private static final String NAME = "ThemeColors", KEY = "color";

    @ColorInt
    public int color;

    public ThemeColors(Context context) {
        SharedPreferences sharedPreferences = context.getSharedPreferences(NAME, Context.MODE_PRIVATE);
        String stringColor = sharedPreferences.getString(KEY, "004bff");
        color = Color.parseColor("#" + stringColor);

        if (isLightActionBar()) context.setTheme(R.style.AppTheme);
        context.setTheme(context.getResources().getIdentifier("T_" + stringColor, "style", context.getPackageName()));
    }

    public static void setNewThemeColor(Activity activity, int red, int green, int blue) {
        int colorStep = 15;
        red = Math.round(red / colorStep) * colorStep;
        green = Math.round(green / colorStep) * colorStep;
        blue = Math.round(blue / colorStep) * colorStep;

        String stringColor = Integer.toHexString(Color.rgb(red, green, blue)).substring(2);
        SharedPreferences.Editor editor = activity.getSharedPreferences(NAME, Context.MODE_PRIVATE).edit();
        editor.putString(KEY, stringColor);
        editor.apply();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) activity.recreate();
        else {
            Intent i = activity.getPackageManager().getLaunchIntentForPackage(activity.getPackageName());
            i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            activity.startActivity(i);
        }
    }

    private boolean isLightActionBar() {// Checking if title text color will be black
        int rgb = (Color.red(color) + Color.green(color) + Color.blue(color)) / 3;
        return rgb > 210;
    }
}

5. MainActivity:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new ThemeColors(this);
        setContentView(R.layout.activity_main);
    }

    public void buttonClick(View view){
        int red= new Random().nextInt(255);
        int green= new Random().nextInt(255);
        int blue= new Random().nextInt(255);
        ThemeColors.setNewThemeColor(MainActivity.this, red, green, blue);
    }
}

Untuk mengubah warna, ganti saja Random dengan RGB Anda, Semoga ini bisa membantu.

masukkan deskripsi gambar di sini

Ada contoh lengkap: ColorTest.zip


dapatkah Anda membagikan proyek seperti?
Erselan Khan

Buat proyek baru, unduh file - "styles.xml", dan gunakan kode di atas. Semoga berhasil.
IQ.Fitur

1
Saya tidak bisa membungkukkan kepala, context.setTheme(context.getResources().getIdentifier("T_" + stringColor, "style", context.getPackageName()));bisakah Anda memberi saya penjelasan atau tautan untuk menindaklanjuti topik ini?
Langusten Gustel

1
@ IQ.Fitur Saya pikir mendorong kode Anda ke repo Github lebih cocok untuk berbagi kode
Vadim Kotov

1
Hanya untuk memperjelas orang lain karena saya jatuh cinta pada ini ... ada file res-v9 / styles.xml yang menyatakan daftar seluruh tema dengan warna yang berbeda dan kode dasarnya menerapkan salah satu tema tersebut dan menciptakan kembali kegiatan. Itulah yang juga dicoba diraih oleh jawaban lain .. yaitu pemecahan masalah dengan menentukan tema sebelumnya dan bukan secara dinamis atau dinamis membuat tema.
frezq

3

Saya menggunakan kode Dahnark tetapi saya juga perlu mengubah latar belakang ToolBar:

if (dark_ui) {
    this.setTheme(R.style.Theme_Dark);

    if (Build.VERSION.SDK_INT >= 21) {
        getWindow().setNavigationBarColor(getResources().getColor(R.color.Theme_Dark_primary));
        getWindow().setStatusBarColor(getResources().getColor(R.color.Theme_Dark_primary_dark));
    }
} else {
    this.setTheme(R.style.Theme_Light);
}

setContentView(R.layout.activity_main);

toolbar = (Toolbar) findViewById(R.id.app_bar);

if(dark_ui) {
    toolbar.setBackgroundColor(getResources().getColor(R.color.Theme_Dark_primary));
}

tambahkan kode ini: android: background = "? attr / colorPrimary", ke toolbar Anda (dalam file .xml), jadi Anda tidak perlu mengatur latar belakang di java.
JavierSegoviaCordoba

Tapi saya punya dua Toolbar berbeda, satu untuk tema terang dan lainnya untuk tema gelap. Jika saya menambahkan android: background = "? Attr / colorPrimary" Saya harus menggunakan semacam pemilih.
lgallard

Saya punya banyak tema dan saya hanya menggunakan kode itu. Lihatlah aplikasi ini: play.google.com/store/apps/…
JavierSegoviaCordoba

-1

Anda tidak dapat mengubah warna colorPrimary, tetapi Anda dapat mengubah tema aplikasi Anda dengan menambahkan gaya baru dengan warna colorPrimary yang berbeda

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <!-- Customize your theme here. -->
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
</style>

<style name="AppTheme.NewTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="colorPrimary">@color/colorOne</item>
    <item name="colorPrimaryDark">@color/colorOneDark</item>
</style>

dan di dalam tema set aktivitas

 setTheme(R.style.AppTheme_NewTheme);
 setContentView(R.layout.activity_main);

Saya melihat bahwa sudah ada jawaban sebelumnya yang menggambarkan gaya switching. Dalam situasi apa jawaban Anda lebih tepat daripada jawaban itu? Dan untuk lebih jelas, pertanyaannya mengatakan "Saat runtime, pengguna memutuskan dia ingin menggunakan #ccffff sebagai warna primer. Tentu saja tidak ada cara saya bisa membuat tema untuk semua warna yang mungkin." Ini tidak menyelesaikan kebutuhan itu; namun jika tidak ada yang menjelaskan cara melakukan ini, akan berguna untuk mengetahui.
ToolmakerSteve

-2

dari suatu kegiatan yang dapat Anda lakukan:

getWindow().setStatusBarColor(i color);

2
Lucu bahwa jawaban ini memiliki -8 suara tetapi menyelesaikan masalah saya: D
Nabin Bhandari

-4

GUNAKAN TOOLBAR

Anda dapat mengatur warna item toolbar kustom secara dinamis dengan membuat kelas toolbar kustom:

package view;

import android.app.Activity;
import android.content.Context;
import android.graphics.ColorFilter;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.support.v7.internal.view.menu.ActionMenuItemView;
import android.support.v7.widget.ActionMenuView;
import android.support.v7.widget.Toolbar;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AutoCompleteTextView;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

public class CustomToolbar extends Toolbar{

    public CustomToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub
    }

    public CustomToolbar(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    public CustomToolbar(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        ctxt = context;
    }

    int itemColor;
    Context ctxt;

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        Log.d("LL", "onLayout");
        super.onLayout(changed, l, t, r, b);
        colorizeToolbar(this, itemColor, (Activity) ctxt);
    } 

    public void setItemColor(int color){
        itemColor = color;
        colorizeToolbar(this, itemColor, (Activity) ctxt);
    }



    /**
     * Use this method to colorize toolbar icons to the desired target color
     * @param toolbarView toolbar view being colored
     * @param toolbarIconsColor the target color of toolbar icons
     * @param activity reference to activity needed to register observers
     */
    public static void colorizeToolbar(Toolbar toolbarView, int toolbarIconsColor, Activity activity) {
        final PorterDuffColorFilter colorFilter
                = new PorterDuffColorFilter(toolbarIconsColor, PorterDuff.Mode.SRC_IN);

        for(int i = 0; i < toolbarView.getChildCount(); i++) {
            final View v = toolbarView.getChildAt(i);

            doColorizing(v, colorFilter, toolbarIconsColor);
        }

      //Step 3: Changing the color of title and subtitle.
        toolbarView.setTitleTextColor(toolbarIconsColor);
        toolbarView.setSubtitleTextColor(toolbarIconsColor);
    }

    public static void doColorizing(View v, final ColorFilter colorFilter, int toolbarIconsColor){
        if(v instanceof ImageButton) {
            ((ImageButton)v).getDrawable().setAlpha(255);
            ((ImageButton)v).getDrawable().setColorFilter(colorFilter);
        }

        if(v instanceof ImageView) {
            ((ImageView)v).getDrawable().setAlpha(255);
            ((ImageView)v).getDrawable().setColorFilter(colorFilter);
        }

        if(v instanceof AutoCompleteTextView) {
            ((AutoCompleteTextView)v).setTextColor(toolbarIconsColor);
        }

        if(v instanceof TextView) {
            ((TextView)v).setTextColor(toolbarIconsColor);
        }

        if(v instanceof EditText) {
            ((EditText)v).setTextColor(toolbarIconsColor);
        }

        if (v instanceof ViewGroup){
            for (int lli =0; lli< ((ViewGroup)v).getChildCount(); lli ++){
                doColorizing(((ViewGroup)v).getChildAt(lli), colorFilter, toolbarIconsColor);
            }
        }

        if(v instanceof ActionMenuView) {
            for(int j = 0; j < ((ActionMenuView)v).getChildCount(); j++) {

                //Step 2: Changing the color of any ActionMenuViews - icons that
                //are not back button, nor text, nor overflow menu icon.
                final View innerView = ((ActionMenuView)v).getChildAt(j);

                if(innerView instanceof ActionMenuItemView) {
                    int drawablesCount = ((ActionMenuItemView)innerView).getCompoundDrawables().length;
                    for(int k = 0; k < drawablesCount; k++) {
                        if(((ActionMenuItemView)innerView).getCompoundDrawables()[k] != null) {
                            final int finalK = k;

                            //Important to set the color filter in seperate thread, 
                            //by adding it to the message queue
                            //Won't work otherwise. 
                            //Works fine for my case but needs more testing

                            ((ActionMenuItemView) innerView).getCompoundDrawables()[finalK].setColorFilter(colorFilter);

//                              innerView.post(new Runnable() {
//                                  @Override
//                                  public void run() {
//                                      ((ActionMenuItemView) innerView).getCompoundDrawables()[finalK].setColorFilter(colorFilter);
//                                  }
//                              });
                        }
                    }
                }
            }
        }
    }



}

kemudian lihat di file tata letak Anda. Sekarang Anda dapat mengatur warna khusus menggunakan

toolbar.setItemColor(Color.Red);

Sumber:

Saya menemukan informasi untuk melakukan ini di sini: Cara mengubah warna ikon Toolbar Android secara dinamis

dan kemudian saya mengeditnya, memperbaikinya, dan mempostingnya di sini: GitHub: AndroidDynamicToolbarItemColor


Ini tidak menjawab pertanyaan. Terutama bagian "Tujuan saya adalah untuk akhirnya memiliki ActionBar dan semua widget seperti Kotak Centang untuk menggunakan warna primer ini. ".
nhaarman

Kemudian tambahkan saja untuk memasukkan kotak centang. Sebagai contoh, tambahkan if (v instanceof CheckBox) {themeChexnoxWithColor (toolbarIconsColor); Saya tidak melihat bagaimana ini tidak menjawab pertanyaan Anda dengan jujur
Michael Kern

@nhaarman Anda dapat secara dinamis mengatur warna actionbar seperti ini stackoverflow.com/questions/23708637/change-actionbar-background-color-dynamically Saya hanya tidak mengerti persis pertanyaan Anda
Michael Kern

Saya memiliki aplikasi tempat pengguna dapat memilih warna actionbar dan warna item actionbar. Saya tidak melihat apa lagi yang Anda butuhkan
Michael Kern

2
Ini sangat membantu saya.
Firefly

-6

Inilah yang BISA Anda lakukan:

tulis file dalam folder yang dapat digambar, beri nama background.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
    <solid android:color="?attr/colorPrimary"/>
</shape>

kemudian atur Layout Anda (atau apa pun masalahnya) android:background="@drawable/background"

pada pengaturan tema Anda warna ini akan mewakili yang sama.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.