Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce helpers for theme colors and document how to support light and dark themes #2178

Merged
merged 7 commits into from
May 17, 2018
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ https://github.com/opendatakit/collect/blob/master/CONTRIBUTING.md

#### Before submitting this PR, please make sure you have:
- [ ] run `./gradlew pmd checkstyle lint findbugs` and confirmed all checks still pass.
- [ ] verified that any new UI elements use theme colors so that they work with both light and dark themes.
- [ ] verified that any new UI elements use theme colors. [UI Components Style guidelines](https://github.com/opendatakit/collect/blob/master/CONTRIBUTING.md#ui-components-style-guidelines)
12 changes: 11 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,19 @@ Small fixes that target very particular bugs may occasionally be merged without

In addition to contributing code, you can help to triage issues. This can include reproducing bug reports, or asking for vital information such as version numbers or reproduction instructions. If you would like to start triaging issues, one easy way to get started is to [subscribe to opendatakit/collect on CodeTriage](https://www.codetriage.com/opendatakit/collect).

## Style guidelines
## Code Style guidelines
Follow the [Android style rules](http://source.android.com/source/code-style.html) and the [Google Java style guide](https://google.github.io/styleguide/javaguide.html).

## UI Components Style guidelines
Ensure that the added UI components are compatible with both light and dark themes.
Follow the below points to get the color for coloring the UI components like text and icons instead of directly using color values (eg. #000000 or R.color.colorName).

UI Component | Java | Xml _(layouts, drawables, vectors)_:
--- | --- | ---
text color | themeUtils.getPrimaryTextColor() | ?primaryTextColor
accent color | themeUtils.getAccentColor() | ?colorAccent
icon color | themeUtils.getIconColor() | ?iconColor

## Strings
Always use [string resources](https://developer.android.com/guide/topics/resources/string-resource.html) instead of literal strings. This ensures wording consistency across the project and also enables full translation of the app. Only make changes to the base `res/values/strings.xml` English file and not to the other language files. The translated files are generated from [Transifex](https://www.transifex.com/opendatakit/collect/) where translations can be submitted by the community. Names of software packages or other untranslatable strings should be placed in `res/values/untranslated.xml`.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
* Copyright (C) 2012 University of Washington
* Copyright (C) 2007 The Android Open Source Project
*
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
*
* http://www.apache.org/licenses/LICENSE-2.0
*
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
Expand Down Expand Up @@ -300,8 +300,8 @@ private void createQuitDrawDialog() {
ListView listView = DialogUtils.createActionListView(this);

List<IconMenuItem> items;
items = ImmutableList.of(new IconMenuItem(R.drawable.ic_save_grey_32dp, R.string.keep_changes),
new IconMenuItem(R.drawable.ic_delete_grey_32dp, R.string.do_not_save));
items = ImmutableList.of(new IconMenuItem(R.drawable.ic_save, R.string.keep_changes),
new IconMenuItem(R.drawable.ic_delete, R.string.do_not_save));

final IconMenuListAdapter adapter = new IconMenuListAdapter(this, items);
listView.setAdapter(adapter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1903,10 +1903,10 @@ private void createQuitDialog() {

List<IconMenuItem> items;
if ((boolean) AdminSharedPreferences.getInstance().get(AdminKeys.KEY_SAVE_MID)) {
items = ImmutableList.of(new IconMenuItem(R.drawable.ic_save_grey_32dp, R.string.keep_changes),
new IconMenuItem(R.drawable.ic_delete_grey_32dp, R.string.do_not_save));
items = ImmutableList.of(new IconMenuItem(R.drawable.ic_save, R.string.keep_changes),
new IconMenuItem(R.drawable.ic_delete, R.string.do_not_save));
} else {
items = ImmutableList.of(new IconMenuItem(R.drawable.ic_delete_grey_32dp, R.string.do_not_save));
items = ImmutableList.of(new IconMenuItem(R.drawable.ic_delete, R.string.do_not_save));
}

Collect.getInstance().getActivityLogger()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,9 +345,6 @@ public void onClick(View v) {
zoomToPoint();
}

themeUtils.setIconTint(this, reloadLocation, showLocation, layers,
clearPointButton, acceptLocation);

helper.setBasemap();

isMapReady = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ protected void onCreate(Bundle savedInstanceState) {
}

marker = new Marker(map);
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place_black));
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place));
myLocationOverlay = new MyLocationNewOverlay(map);

handler.postDelayed(new Runnable() {
Expand Down Expand Up @@ -246,9 +246,6 @@ public void onClick(View v) {
}
});

themeUtils.setIconTint(this, reloadLocationButton, showLocationButton, layersButton,
clearPointButton, saveLocationButton);

Intent intent = getIntent();
if (intent != null && intent.getExtras() != null) {

Expand Down Expand Up @@ -488,7 +485,7 @@ public boolean longPressHelper(GeoPoint geoPoint) {
showLocationButton.setEnabled(true);
map.invalidate();
marker.setPosition(geoPoint);
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place_black));
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place));
marker.setDraggable(true);
latLng = geoPoint;
isDragged = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ public void onClick(View v) {
showZoomDialog();
}

themeUtils.setIconTint(this, gpsButton, clearButton, layersButton, returnButton);
helper.setBasemap();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,6 @@ public void onClick(View v) {
zoomDialog.dismiss();
}
});

themeUtils.setIconTint(this, locationButton, layersButton, clearButton, saveButton);
}

@Override
Expand Down Expand Up @@ -238,7 +236,7 @@ private void overlayIntentPolygon(String str) {
Marker marker = new Marker(map);
marker.setPosition(new GeoPoint(gp[0], gp[1]));
marker.setDraggable(true);
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place_black));
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place));
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
marker.setOnMarkerClickListener(nullMarkerListener);
mapMarkers.add(marker);
Expand Down Expand Up @@ -424,7 +422,7 @@ public boolean longPressHelper(GeoPoint point) {
Marker marker = new Marker(map);
marker.setPosition(point);
marker.setDraggable(true);
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place_black));
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place));
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
marker.setOnMarkerClickListener(nullMarkerListener);
mapMarkers.add(marker);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,6 @@ public void onClick(View v) {
}

helper.setBasemap();

themeUtils.setIconTint(this, playButton, pauseButton, locationButton, layersButton,
clearButton, saveButton);
}

private void overlayIntentTrace(String str) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,6 @@ public void onClick(View v) {

locationClient = LocationClients.clientForContext(this);
locationClient.setListener(this);

themeUtils.setIconTint(this, playButton, pauseButton, locationButton, layersButton,
clearButton, saveButton);
}

@Override
Expand Down Expand Up @@ -396,7 +393,7 @@ public void overlayIntentTrace(String str) {
marker.setOnMarkerClickListener(nullMarkerListener);
marker.setDraggable(true);
marker.setOnMarkerDragListener(dragListener);
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place_black));
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place));
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
mapMarkers.add(marker);
List<GeoPoint> points = polyline.getPoints();
Expand Down Expand Up @@ -642,7 +639,7 @@ private void addLocationMarker() {
Float lastKnownAccuracy =
myLocationOverlay.getMyLocationProvider().getLastKnownLocation().getAccuracy();
myLocationOverlay.getMyLocationProvider().getLastKnownLocation().getAccuracy();
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place_black));
marker.setIcon(ContextCompat.getDrawable(getApplicationContext(), R.drawable.ic_place));
marker.setSubDescription(Float.toString(lastKnownAccuracy));
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
marker.setDraggable(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
viewHolder.imgViewIcon.setImageResource(ApplicationConstants.getSortLabelToIconMap().get(sortList[position]));
viewHolder.imgViewIcon.setImageDrawable(DrawableCompat.wrap(viewHolder.imgViewIcon.getDrawable()).mutate());

int color = themeUtils.getAttributeValue(position == selectedSortingOrder ? R.attr.colorAccent : R.attr.primaryTextColor);
int color = position == selectedSortingOrder ? themeUtils.getAccentColor() : themeUtils.getPrimaryTextColor();
viewHolder.txtViewTitle.setTextColor(color);
DrawableCompat.setTintList(viewHolder.imgViewIcon.getDrawable(), position == selectedSortingOrder ? ColorStateList.valueOf(color) : null);
}
Expand Down Expand Up @@ -91,11 +91,11 @@ public void onClick(View v) {

public void updateItemColor(int selectedSortingOrder) {
ViewHolder previousHolder = (ViewHolder) recyclerView.findViewHolderForAdapterPosition(selectedSortingOrder);
previousHolder.txtViewTitle.setTextColor(themeUtils.getAttributeValue(R.attr.primaryTextColor));
previousHolder.txtViewTitle.setTextColor(themeUtils.getPrimaryTextColor());
DrawableCompat.setTintList(previousHolder.imgViewIcon.getDrawable(), null);

txtViewTitle.setTextColor(themeUtils.getAttributeValue(R.attr.colorAccent));
DrawableCompat.setTint(imgViewIcon.getDrawable(), themeUtils.getAttributeValue(R.attr.colorAccent));
txtViewTitle.setTextColor(themeUtils.getAccentColor());
DrawableCompat.setTint(imgViewIcon.getDrawable(), themeUtils.getAccentColor());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.annotation.AttrRes;
import android.support.annotation.ColorInt;
import android.support.annotation.StyleRes;
import android.util.TypedValue;
import android.widget.ImageButton;

import org.odk.collect.android.R;
import org.odk.collect.android.preferences.GeneralSharedPreferences;
Expand All @@ -35,51 +35,42 @@ public ThemeUtils(Context context) {
this.context = context;
}

@StyleRes
public int getAppTheme() {
return isDarkTheme() ? R.style.DarkAppTheme : R.style.LightAppTheme;
}

@StyleRes
public int getSettingsTheme() {
return isDarkTheme() ? R.style.AppTheme_SettingsTheme_Dark : R.style.AppTheme_SettingsTheme_Light;
}

@StyleRes
public int getBottomDialogTheme() {
return isDarkTheme() ? R.style.DarkMaterialDialogSheet : R.style.LightMaterialDialogSheet;
}

/*
* TODO : Remove this method once all drawables are converted to vectors and use ?colorControlNormal for android:fillColor attribute
*/
public void setIconTint(Context context, ImageButton... imageButtons) {
for (ImageButton imageButton : imageButtons) {
setIconTint(context, imageButton.getDrawable());
}
}

private void setIconTint(Context context, Drawable drawable) {
DrawableCompat.setTint(drawable, context.getResources()
.getColor(isDarkTheme() ? android.R.color.white : android.R.color.black));
}

public boolean isHoloDialogTheme(int theme) {
return theme == android.R.style.Theme_Holo_Light_Dialog ||
theme == android.R.style.Theme_Holo_Dialog;
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@StyleRes
public int getMaterialDialogTheme() {
return isDarkTheme() ?
android.R.style.Theme_Material_Dialog :
android.R.style.Theme_Material_Light_Dialog;
}

@StyleRes
public int getHoloDialogTheme() {
return isDarkTheme() ?
android.R.style.Theme_Holo_Dialog :
android.R.style.Theme_Holo_Light_Dialog;
}

public int getAttributeValue(int resId) {
private int getAttributeValue(@AttrRes int resId) {
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(resId, outValue, true);
return outValue.data;
Expand All @@ -93,4 +84,28 @@ private boolean isDarkTheme() {
String theme = (String) GeneralSharedPreferences.getInstance().get(PreferenceKeys.KEY_APP_THEME);
return theme.equals(context.getString(R.string.app_theme_dark));
}

/**
* @return Text color for the current {@link android.content.res.Resources.Theme}
*/
@ColorInt
public int getPrimaryTextColor() {
return getAttributeValue(R.attr.primaryTextColor);
}

/**
* @return Accent color for the current {@link android.content.res.Resources.Theme}
*/
@ColorInt
public int getAccentColor() {
return getAttributeValue(R.attr.colorAccent);
}

/**
* @return Icon color for the current {@link android.content.res.Resources.Theme}
*/
@ColorInt
public int getIconColor() {
return getAttributeValue(R.attr.iconColor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public void setPlayTextColor(int textColor) {
*/
public void resetTextFormatting() {
// first set it to defaults
viewText.setTextColor(new ThemeUtils(context).getAttributeValue(R.attr.primaryTextColor));
viewText.setTextColor(new ThemeUtils(context).getPrimaryTextColor());
// then set the text to our original (brings back any html formatting)
viewText.setText(originalText);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ private void initMediaPlayer() {
});
mediaPlayer.setOnCompletionListener(player -> {
Timber.i("Completed");
playButton.setImageResource(R.drawable.ic_play_arrow_black_24dp);
playButton.setImageResource(R.drawable.ic_play_arrow_24dp);
});
}

Expand Down Expand Up @@ -198,7 +198,7 @@ private void play() {
.logInstanceAction(this, "play", "click",
formEntryPrompt.getIndex());

playButton.setImageResource(R.drawable.ic_pause_black_24dp);
playButton.setImageResource(R.drawable.ic_pause_24dp);
mediaPlayer.start();
updateProgressBar();
}
Expand All @@ -209,7 +209,7 @@ private void pause() {
.logInstanceAction(this, "pause", "click",
formEntryPrompt.getIndex());

playButton.setImageResource(R.drawable.ic_play_arrow_black_24dp);
playButton.setImageResource(R.drawable.ic_play_arrow_24dp);
mediaPlayer.pause();
seekHandler.removeCallbacks(updateTimeTask);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public ExStringWidget(Context context, FormEntryPrompt prompt) {
answer.setLayoutParams(params);
textBackground = answer.getBackground();
answer.setBackground(null);
answer.setTextColor(themeUtils.getAttributeValue(R.attr.primaryTextColor));
answer.setTextColor(themeUtils.getPrimaryTextColor());

// capitalize nothing
answer.setKeyListener(new TextKeyListener(Capitalize.NONE, false));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public QuestionWidget(Context context, FormEntryPrompt prompt) {
super(context);

themeUtils = new ThemeUtils(context);
playColor = themeUtils.getAttributeValue(R.attr.colorAccent);
playColor = themeUtils.getAccentColor();

if (context instanceof FormEntryActivity) {
state = ((FormEntryActivity) context).getState();
Expand Down Expand Up @@ -209,7 +209,7 @@ private TextView configureGuidanceTextView(TextView guidanceTextView, String gui

guidanceTextView.setText(TextUtils.textToHtml(guidance));

guidanceTextView.setTextColor(themeUtils.getAttributeValue(R.attr.primaryTextColor));
guidanceTextView.setTextColor(themeUtils.getPrimaryTextColor());
guidanceTextView.setMovementMethod(LinkMovementMethod.getInstance());
return guidanceTextView;
}
Expand Down Expand Up @@ -245,7 +245,7 @@ private MediaLayout createQuestionMediaLayout(FormEntryPrompt prompt) {
questionText.setTextSize(TypedValue.COMPLEX_UNIT_DIP, getQuestionFontSize());
questionText.setTypeface(null, Typeface.BOLD);
questionText.setPadding(0, 0, 0, 7);
questionText.setTextColor(themeUtils.getAttributeValue(R.attr.primaryTextColor));
questionText.setTextColor(themeUtils.getPrimaryTextColor());
questionText.setText(TextUtils.textToHtml(FormEntryPromptUtils.markQuestionIfIsRequired(promptText, prompt.isRequired())));
questionText.setMovementMethod(LinkMovementMethod.getInstance());

Expand Down Expand Up @@ -427,7 +427,7 @@ private TextView setupHelpText(TextView helpText, FormEntryPrompt prompt) {
} else {
helpText.setText(TextUtils.textToHtml(s));
}
helpText.setTextColor(themeUtils.getAttributeValue(R.attr.primaryTextColor));
helpText.setTextColor(themeUtils.getPrimaryTextColor());
helpText.setMovementMethod(LinkMovementMethod.getInstance());
return helpText;
} else {
Expand Down Expand Up @@ -549,7 +549,7 @@ protected TextView getAnswerTextView(String text) {
TextView textView = new TextView(getContext());

textView.setId(R.id.answer_text);
textView.setTextColor(themeUtils.getAttributeValue(R.attr.primaryTextColor));
textView.setTextColor(themeUtils.getPrimaryTextColor());
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, getAnswerFontSize());
textView.setPadding(20, 20, 20, 20);
textView.setText(text);
Expand Down
Loading