2015-11-29 3 views
-1

Я делаю проект андроида для своего университета, и мы хотим, чтобы его внешний вид менялся в зависимости от местоположения пользователя.Изменение динамического вида приложения android

Например, если пользователь находится рядом с морской зоной, это пиратский тематический, с деревянными кнопками, фоном океана и т. Д. Если пользователь находится рядом с горным районом, это, возможно, тема викинга. Вы поняли эту идею.

Мой вопрос сейчас: Каков наилучший способ реализации чего-то подобного?

Заранее спасибо за ответы :)

ответ

0

Лучший способ заключается в использовании пользовательских тем деятельности. Со стилями и (настраиваемыми) атрибутами темы вы можете разместить все настраиваемые стили в своей теме. Хотя это немного громоздко, вы можете изменить тему во время выполнения. Тема применяется при создании представлений, поэтому вам нужно будет гарантировать, что действия будут воссозданы. Вы можете обеспечить лучший опыт, если будете обрабатывать это изменение вручную.

Ваш макет обычно выглядит примерно так:

Пример типичного макета

<LinearLayout 
    android:id="@+id/layout" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" 
    android:background="@drawable/pirate_background"> 

    <ImageView 
     android:id="@+id/image" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:src="@drawable/pirate_greeting" 
     /> 

    <TextView 
     android:id="@+id/greeting" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:paddingStart="@dimen/activity_horizontal_margin" 
     android:paddingEnd="@dimen/activity_horizontal_margin" 
     android:text="@string/pirate_greeting" 
     /> 

</LinearLayout> 

Теперь, если все эти атрибуты, названных pirate_ * должны быть изменчивыми, вы хотите поместить те, в вашей теме , так что изменение темы автоматически изменяет эти элементы. Самый простой подход - определить атрибут темы для каждого атрибута, который вы хотите настроить. Это будет выглядеть следующим образом:

Компоновка с пользовательской темы атрибуты

<LinearLayout 
    android:id="@+id/layout" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" 
    android:background="?attr/my_layout_background"> 

    <ImageView 
     android:id="@+id/image" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:src="?attr/my_image_src" 
     /> 

    <TextView 
     android:id="@+id/greeting" 
     android:layout_width="wrap_content" 
     android:layout_height="match_parent" 
     android:paddingStart="@dimen/activity_horizontal_margin" 
     android:paddingEnd="@dimen/activity_horizontal_margin" 
     android:text="?attr/my_greeting_text" 
     /> 

</LinearLayout> 

Этот знак вопроса? указывает, что вы ссылаетесь на тематический атрибут. Вы определяете эти атрибуты в файле ресурсов, обычно называемом «attrs.xml».

значения/attrs.xml

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <attr name="my_layout_background" format="reference" /> 
    <attr name="my_image_src" format="reference" /> 
    <attr name="my_greeting_text" format="string" /> 
</resources> 

Эти атрибуты будут работать только, если ваша тема определила значение для них. Поэтому, независимо от того, какая у вас есть тема, убедитесь, что она включает определение атрибутов выше.

значения/themes.xml

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <style name="MyAppTheme" parent="[your base theme]"> 
     <item name="my_layout_background">@drawable/default_greeting</item> 
     <item name="my_image_src">@drawable/default_greeting</item> 
     <item name="my_greeting_text">@string/default_greeting</item> 
    </style> 

    <style name="MyAppTheme.Pirates"> 
     <item name="my_layout_background">@drawable/pirate_background</item> 
     <item name="my_image_src">@drawable/pirate_greeting</item> 
     <item name="my_greeting_text">@string/pirate_greeting</item> 
    </style> 

    <style name="MyAppTheme.China"> 
     <item name="my_layout_background">@drawable/china_background</item> 
     <item name="my_image_src">@drawable/nihao</item> 
     <item name="my_greeting_text">@string/nihao</item> 
    </style> 

</resources> 

Для краткости я буду считать, что вы знаете, как установить тему (если вы этого не сделаете, узнать его here). Совет. В редакторе макета Android Studio вы можете указать тему, которая позволяет просматривать макет в разных темах. Поиграйте с ним немного.

До сих пор вы завершили легкую часть. Сейчас мы изменим конфигурацию во время выполнения, и это часть, которая не так проста. Но если следовать моим инструкциям, это не должно быть слишком сложно. Для типичной активности представления создаются (или накачиваются) в методе setContentView(...). Какая бы ни была тема в то время, выберете, как выглядят взгляды. Поэтому, если вы хотите изменить свою тему программно, вы должны убедиться, что вы это сделаете до того, как вызывается setContentView(...).

Деятельность, которая устанавливает пользовательскую тему

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setTheme(R.style.MyAppTheme_Pirates); 
    setContentView(R.layout.activity_main); 
    // ... 
} 

Большую часть времени вы, вероятно, хотите изменить тему, когда деятельность уже создана. Вы можете использовать метод recreate() для этого, который уничтожит текущую деятельность и сразу же создаст новую. Конечно, если вы уничтожите действие, вы потеряете все данные, которые он хранит (например, тему, которую вы хотите изменить). Существует два способа иметь дело с этим:

  1. Когда вы определяете тему для применения, не храните эти данные в активности, не храните ее где-то, она не исчезает, когда действие уничтожается.
  2. Используйте onSaveInstanceState() в действии, и сохрани туда тему. Если вы сделаете это, вы сможете восстановить эту информацию при создании новой активности.

Какой бы вы ни выбрали, зависит от вас. Что более подходит, действительно зависит от того, как вы выбираете структурировать свой код. Что бы вы ни выбрали, в конце концов, ваша деятельность будет иметь такой код:

активность, которая воссоздает себя применить новую тему

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setTheme(ThemeStorage.getTheme()); 
    setContentView(R.layout.activity_main); 
} 

public void applyNewTheme(@StyleRes int themeResId) { 
    ThemeStorage.setTheme(themeResId); 
    recreate(); 
} 

Теперь все, что вам нужно сделать, это есть некоторый код, который определяет, что темы для применения. Это может быть справочная служба, которая прослушивает обновления местоположения. Если он определяет, что приложение должно измениться на новую тему, вы просто вызываете applyNewTheme на некоторые или все текущие действия. Вы можете получить список всех текущих действий, используя ActivityLifecycleCallbacks. Вы регистрируете эти обратные вызовы в классе Application. Вот какой код, чтобы сделать это легко.

public class MyApplication extends Application { 

    private ActivityCollector mActivityCollector = new ActivityCollector(); 

    @Override 
    public void onCreate() { 
     super.onCreate(); 
     registerActivityLifecycleCallbacks(mActivityCollector.getCallbacks()); 
    } 

    public ActivityCollector getActivityCollector() { 
     return mActivityCollector; 
    } 
} 

/** 
* Uses {@link android.app.Application.ActivityLifecycleCallbacks} to 
* maintain a list of created activities. 
*/ 
public class ActivityCollector { 

    private List<Activity> mCreatedActivities = new ArrayList<>(); 
    private ActivityLifecycleCallbacks mLifecycleCallbacks = new ActivityLifecycleCallbacks() { 

     @Override 
     public void onActivityCreated(Activity activity, Bundle savedInstanceState) { 
      mCreatedActivities.add(activity); 
     } 

     @Override 
     public void onActivityDestroyed(Activity activity) { 
      mCreatedActivities.remove(activity); 
     } 

     @Override 
     public void onActivityStarted(Activity activity) { 
     } 

     @Override 
     public void onActivityResumed(Activity activity) { 
     } 

     @Override 
     public void onActivityPaused(Activity activity) { 
     } 

     @Override 
     public void onActivityStopped(Activity activity) { 
     } 

     @Override 
     public void onActivitySaveInstanceState(Activity activity, Bundle outState) { 
     } 
    }; 

    public List<Activity> getCreatedActivities() { 
     return mCreatedActivities; 
    } 

    public ActivityLifecycleCallbacks getCallbacks() { 
     return mLifecycleCallbacks; 
    } 
} 

Таким образом, передать этот ActivityCollector к коду, который необходимо применять темы для вашей деятельности, и вы все сделали.

+0

Cool thanks :) Мы хотим начать разработку очень скоро, и если бы мы могли реализовать это с самого начала, это было бы здорово! – MZero

+0

Я сбив с толку, насколько подробно описаны ваши инструкции, и я очень благодарен за это! – MZero

Смежные вопросы