PageRenderTime 40ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/src/br/com/carlosrafaelgn/fplay/ui/RadioStationView.java

https://gitlab.com/madamovic-bg/FPlayAndroid
Java | 299 lines | 229 code | 31 blank | 39 comment | 50 complexity | 86697274929473ca316200dcecefd9c3 MD5 | raw file
  1. //
  2. // FPlayAndroid is distributed under the FreeBSD License
  3. //
  4. // Copyright (c) 2013-2014, Carlos Rafael Gimenes das Neves
  5. // All rights reserved.
  6. //
  7. // Redistribution and use in source and binary forms, with or without
  8. // modification, are permitted provided that the following conditions are met:
  9. //
  10. // 1. Redistributions of source code must retain the above copyright notice, this
  11. // list of conditions and the following disclaimer.
  12. // 2. Redistributions in binary form must reproduce the above copyright notice,
  13. // this list of conditions and the following disclaimer in the documentation
  14. // and/or other materials provided with the distribution.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  17. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
  20. // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. //
  27. // The views and conclusions contained in the software and documentation are those
  28. // of the authors and should not be interpreted as representing official policies,
  29. // either expressed or implied, of the FreeBSD Project.
  30. //
  31. // https://github.com/carlosrafaelgn/FPlayAndroid
  32. //
  33. package br.com.carlosrafaelgn.fplay.ui;
  34. import android.annotation.TargetApi;
  35. import android.content.Context;
  36. import android.graphics.Canvas;
  37. import android.graphics.drawable.Drawable;
  38. import android.os.Build;
  39. import android.support.annotation.NonNull;
  40. import android.text.Layout.Alignment;
  41. import android.text.StaticLayout;
  42. import android.view.Gravity;
  43. import android.view.View;
  44. import android.view.ViewDebug.ExportedProperty;
  45. import android.widget.LinearLayout;
  46. import br.com.carlosrafaelgn.fplay.R;
  47. import br.com.carlosrafaelgn.fplay.list.RadioStation;
  48. import br.com.carlosrafaelgn.fplay.ui.drawable.TextIconDrawable;
  49. public final class RadioStationView extends LinearLayout implements View.OnClickListener, View.OnLongClickListener {
  50. private RadioStation station;
  51. private BgButton btnFavorite;
  52. private String ellipsizedTitle, ellipsizedOnAir;
  53. private String[] descriptionLines, tagsLines;
  54. private int state, width, position, descriptionY, tagsY;
  55. private static int height;
  56. public static int getViewHeight() {
  57. return (height = UI.verticalMargin + UI._22spBox + UI.controlXSmallMargin + UI._18spBox + (3 * UI._14spBox) + UI.controlSmallMargin + Math.max(UI.defaultControlSize + (UI.isDividerVisible ? (UI.controlXSmallMargin + UI.strokeSize) : UI.controlXSmallMargin), UI.verticalMargin + (UI._14spBox << 1)) + UI.controlSmallMargin);
  58. }
  59. public RadioStationView(Context context) {
  60. super(context);
  61. setOnClickListener(this);
  62. setOnLongClickListener(this);
  63. setBaselineAligned(false);
  64. setGravity(Gravity.RIGHT | Gravity.BOTTOM);
  65. getViewHeight();
  66. descriptionLines = new String[4];
  67. tagsLines = new String[3];
  68. btnFavorite = new BgButton(context);
  69. LayoutParams p = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  70. p.bottomMargin = (UI.isDividerVisible ? UI.strokeSize : 0);
  71. btnFavorite.setLayoutParams(p);
  72. btnFavorite.setHideBorders(true);
  73. btnFavorite.formatAsCheckBox(UI.ICON_FAVORITE_ON, UI.ICON_FAVORITE_OFF, true, true, true);
  74. btnFavorite.setContentDescription(context.getText(R.string.favorite));
  75. btnFavorite.setOnClickListener(this);
  76. btnFavorite.setTextColor(UI.colorState_text_listitem_reactive);
  77. addView(btnFavorite);
  78. super.setDrawingCacheEnabled(false);
  79. }
  80. private void processEllipsis() {
  81. final int hMargin = (UI.controlMargin << 1);
  82. if (width <= hMargin) {
  83. ellipsizedTitle = "";
  84. ellipsizedOnAir = "";
  85. descriptionLines[0] = null;
  86. tagsLines[0] = null;
  87. return;
  88. }
  89. ellipsizedTitle = UI.ellipsizeText(station.title, UI._22sp, width - hMargin, true);
  90. ellipsizedOnAir = UI.ellipsizeText(station.onAir, UI._18sp, width - hMargin - UI._18sp - UI.controlSmallMargin, true);
  91. UI.textPaint.setTextSize(UI._14sp);
  92. //push the tags to the bottom!
  93. StaticLayout layout = new StaticLayout(station.tags, UI.textPaint, width - hMargin - UI.defaultControlSize, Alignment.ALIGN_NORMAL, 1, 0, false);
  94. int i, visibleLines = Math.min(2, layout.getLineCount());
  95. for (i = 0; i < visibleLines; i++)
  96. tagsLines[i] = station.tags.substring(layout.getLineStart(i), layout.getLineEnd(i));
  97. tagsLines[i] = null;
  98. if (layout.getLineCount() > 2) {
  99. //ellipsize last line...
  100. if (tagsLines[1].length() > 2)
  101. tagsLines[1] = tagsLines[1].substring(0, tagsLines[1].length() - 2) + "\u2026";
  102. else
  103. tagsLines[1] += "\u2026";
  104. }
  105. tagsY = height - UI.verticalMargin - (visibleLines * UI._14spBox) + UI._14spYinBox;
  106. //center the description vertically, considering all available space
  107. final int top = UI.verticalMargin + UI._22spBox + UI.controlXSmallMargin + UI._18spBox, bottom = Math.max(UI.defaultControlSize + (UI.isDividerVisible ? (UI.controlXSmallMargin + UI.strokeSize) : UI.controlXSmallMargin), UI.verticalMargin + (visibleLines * UI._14spBox));
  108. layout = new StaticLayout(station.description, UI.textPaint, width - hMargin, Alignment.ALIGN_NORMAL, 1, 0, false);
  109. visibleLines = Math.min(3, layout.getLineCount());
  110. for (i = 0; i < visibleLines; i++)
  111. descriptionLines[i] = station.description.substring(layout.getLineStart(i), layout.getLineEnd(i));
  112. descriptionLines[i] = null;
  113. if (layout.getLineCount() > 3) {
  114. //ellipsize last line...
  115. if (descriptionLines[2].length() > 2)
  116. descriptionLines[2] = descriptionLines[2].substring(0, descriptionLines[2].length() - 2) + "\u2026";
  117. else
  118. descriptionLines[2] += "\u2026";
  119. }
  120. descriptionY = top + (((height - top - bottom) - (visibleLines * UI._14spBox)) >> 1) + UI._14spYinBox;
  121. }
  122. public void refreshItemFavoriteButton() {
  123. if (station != null && btnFavorite != null)
  124. btnFavorite.setChecked(station.isFavorite);
  125. }
  126. @Override
  127. public CharSequence getContentDescription() {
  128. if (station != null)
  129. return station.title;
  130. return super.getContentDescription();
  131. }
  132. public void setItemState(RadioStation station, int position, int state) {
  133. this.position = position;
  134. if (btnFavorite != null && (this.state & UI.STATE_SELECTED) != (state & UI.STATE_SELECTED))
  135. btnFavorite.setTextColor((state != 0) ? UI.colorState_text_selected_static : UI.colorState_text_listitem_reactive);
  136. this.state = (this.state & ~(UI.STATE_CURRENT | UI.STATE_SELECTED | UI.STATE_MULTISELECTED)) | state;
  137. //watch out, DO NOT use equals() in favor of speed!
  138. if (this.station == station)
  139. return;
  140. this.station = station;
  141. if (btnFavorite != null)
  142. btnFavorite.setChecked(station.isFavorite);
  143. processEllipsis();
  144. }
  145. @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
  146. @Override
  147. public void setBackground(Drawable background) {
  148. super.setBackground(null);
  149. }
  150. @SuppressWarnings("deprecation")
  151. @Override
  152. @Deprecated
  153. public void setBackgroundDrawable(Drawable background) {
  154. super.setBackgroundDrawable(null);
  155. }
  156. @Override
  157. public void setBackgroundResource(int resid) {
  158. super.setBackgroundResource(0);
  159. }
  160. @Override
  161. public void setBackgroundColor(int color) {
  162. super.setBackgroundResource(0);
  163. }
  164. @Override
  165. public Drawable getBackground() {
  166. return null;
  167. }
  168. @Override
  169. public void invalidateDrawable(@NonNull Drawable drawable) {
  170. }
  171. @Override
  172. protected boolean verifyDrawable(Drawable drawable) {
  173. return false;
  174. }
  175. @Override
  176. @ExportedProperty(category = "drawing")
  177. public boolean isOpaque() {
  178. return false;//((state & ~UI.STATE_CURRENT) != 0);
  179. }
  180. @Override
  181. protected void drawableStateChanged() {
  182. super.drawableStateChanged();
  183. final boolean old = (state == 0);
  184. state = UI.handleStateChanges(state, isPressed(), isFocused(), this);
  185. if ((state == 0) != old && btnFavorite != null)
  186. btnFavorite.setTextColor((state != 0) ? UI.colorState_text_selected_static : UI.colorState_text_listitem_reactive);
  187. }
  188. @Override
  189. protected int getSuggestedMinimumHeight() {
  190. return height;
  191. }
  192. @Override
  193. public int getMinimumHeight() {
  194. return height;
  195. }
  196. @Override
  197. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  198. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  199. setMeasuredDimension(resolveSize(0, widthMeasureSpec), height);
  200. }
  201. @Override
  202. protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  203. super.onSizeChanged(w, h, oldw, oldh);
  204. if (width != w) {
  205. width = w;
  206. processEllipsis();
  207. }
  208. }
  209. //Android Custom Layout - onDraw() never gets called
  210. //http://stackoverflow.com/questions/13056331/android-custom-layout-ondraw-never-gets-called
  211. @Override
  212. protected void dispatchDraw(@NonNull Canvas canvas) {
  213. if (ellipsizedTitle == null)
  214. return;
  215. final int txtColor = (((state & ~UI.STATE_CURRENT) == 0) ? UI.color_text_listitem : UI.color_text_selected);
  216. final int txtColor2 = (((state & ~UI.STATE_CURRENT) == 0) ? UI.color_text_listitem_secondary : UI.color_text_selected);
  217. getDrawingRect(UI.rect);
  218. UI.drawBgBorderless(canvas, state | ((state & UI.STATE_SELECTED & ((BgListView)getParent()).extraState) >>> 2), true);
  219. UI.drawText(canvas, ellipsizedTitle, txtColor, UI._22sp, UI.controlMargin, UI.verticalMargin + UI._22spYinBox);
  220. TextIconDrawable.drawIcon(canvas, UI.ICON_FPLAY, UI.controlMargin, UI.verticalMargin + UI._22spBox + UI.controlXSmallMargin + ((UI._18spBox - UI._18sp) >> 1), UI._18sp, txtColor2);
  221. UI.drawText(canvas, ellipsizedOnAir, txtColor2, UI._18sp, UI.controlMargin + UI._18sp + UI.controlSmallMargin, UI.verticalMargin + UI._22spBox + UI.controlXSmallMargin + UI._18spYinBox);
  222. int i = 0, y = descriptionY;
  223. while (descriptionLines[i] != null) {
  224. UI.drawText(canvas, descriptionLines[i], txtColor, UI._14sp, UI.controlMargin, y);
  225. y += UI._14spBox;
  226. i++;
  227. }
  228. i = 0;
  229. y = tagsY;
  230. while (tagsLines[i] != null) {
  231. UI.drawText(canvas, tagsLines[i], txtColor2, UI._14sp, UI.controlMargin, y);
  232. y += UI._14spBox;
  233. i++;
  234. }
  235. super.dispatchDraw(canvas);
  236. }
  237. @Override
  238. protected void dispatchSetPressed(boolean pressed) {
  239. }
  240. @Override
  241. protected void onDetachedFromWindow() {
  242. station = null;
  243. btnFavorite = null;
  244. ellipsizedTitle = null;
  245. ellipsizedOnAir = null;
  246. descriptionLines = null;
  247. tagsLines = null;
  248. super.onDetachedFromWindow();
  249. }
  250. @Override
  251. public void onClick(View view) {
  252. if (view == btnFavorite) {
  253. if (station != null)
  254. station.isFavorite = btnFavorite.isChecked();
  255. if (UI.browserActivity != null)
  256. UI.browserActivity.processItemCheckboxClick(position);
  257. } else {
  258. if (UI.browserActivity != null)
  259. UI.browserActivity.processItemClick(position);
  260. }
  261. }
  262. @Override
  263. public boolean onLongClick(View view) {
  264. if (UI.browserActivity != null)
  265. UI.browserActivity.processItemLongClick(position);
  266. return true;
  267. }
  268. }