{"id":3321,"date":"2012-12-29T16:19:15","date_gmt":"2012-12-30T00:19:15","guid":{"rendered":"http:\/\/blog.xamarin.com\/?p=3321"},"modified":"2012-12-29T16:19:15","modified_gmt":"2012-12-30T00:19:15","slug":"android-tricks-a-youtube-style-like-bar","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/xamarin\/android-tricks-a-youtube-style-like-bar\/","title":{"rendered":"Android Tricks: A Karma Bar Inspired by YouTube"},"content":{"rendered":"<p>\t\t\t\tTo represent the two competing &#8220;like&#8221; and &#8220;dislike&#8221; tallies on individual videos, YouTube uses an elegant solution&mdash;a partially filled bar that indicates both values:<\/p>\n<p><a href=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/2012-12-21_2355.png\"><img decoding=\"async\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/2012-12-21_2355.png\" alt=\"2012-12-21_2355\" width=\"545\" height=\"194\" class=\"aligncenter size-full wp-image-3361\" \/><\/a><\/p>\n<p>I wanted to use a similar interface in one of my applications to represent the &#8220;given&#8221; and &#8220;received&#8221; counts for an item. To display the values, I created a custom Android control called <code>KarmaMeter<\/code>. The bar uses the color theme defined <a href=\"http:\/\/developer.android.com\/design\/style\/color.html\">in the corresponding section<\/a> in the Android design documentation.<\/p>\n<p><a href=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/karma-bar.png\"><img decoding=\"async\" src=\"\/wp-content\/uploads\/sites\/44\/2019\/04\/karma-bar.png\" alt=\"karma-bar\" width=\"800\" height=\"172\" class=\"aligncenter size-full wp-image-3362\" \/><\/a><\/p>\n<p>The code for the control is given below. It&#8217;s implemented as a <code>View<\/code> and supports animating the changes between different values:<\/p>\n<pre class=\"lang:csharp decode:true\">\npublic class KarmaMeter : View\n{\n\tconst int DefaultHeight = 10;\n\tconst int DefaultWidth = 120;\n\n\tdouble position = 0.5;\n\tfloat lastWidth = -1;\n\tPaint positivePaint;\n\tPaint negativePaint;\n\n\tpublic KarmaMeter (Context context, IAttributeSet attrs) :\n\t\tbase (context, attrs)\n\t{\n\t\tInitialize ();\n\t}\n\n\tpublic KarmaMeter (Context context, IAttributeSet attrs, int defStyle) :\n\t\tbase (context, attrs, defStyle)\n\t{\n\t\tInitialize ();\n\t}\n\n\tvoid Initialize ()\n\t{\n\t\tpositivePaint = new Paint {\n\t\t\tAntiAlias = true,\n\t\t\tColor = Color.Rgb (0x99, 0xcc, 0),\n\t\t};\n\t\tpositivePaint.SetStyle (Paint.Style.FillAndStroke);\n\n\t\tnegativePaint = new Paint {\n\t\t\tAntiAlias = true,\n\t\t\tColor = Color.Rgb (0xff, 0x44, 0x44)\n\t\t};\n\t\tnegativePaint.SetStyle (Paint.Style.FillAndStroke);\n\t}\n\n\tpublic void SetKarmaBasedOnValues (int totalGiven, int totalGotten, bool animate = true)\n\t{\n\t\tvar value = (((totalGiven - totalGotten) \/ (float)(totalGiven + totalGotten)) + 1) \/ 2f;\n\t\tSetKarmaValue (value, animate);\n\t}\n\n\tpublic double KarmaValue {\n\t\tget {\n\t\t\treturn position;\n\t\t}\n\t\tset {\n\t\t\tposition = Math.Max (0f, Math.Min (value, 1f));\n\t\t\tInvalidate ();\n\t\t}\n\t}\n\n\tpublic void SetKarmaValue (double value, bool animate)\n\t{\n\t\tif (!animate) {\n\t\t\tKarmaValue = value;\n\t\t\treturn;\n\t\t}\n\n\t\tvar animator = ValueAnimator.OfFloat ((float)position, (float)Math.Max (0f, Math.Min (value, 1f)));\n\t\tanimator.SetDuration (500);\n\t\tanimator.Update += (sender, e) =&amp;gt; KarmaValue = (double)e.Animation.AnimatedValue;\n\t\tanimator.AnimationEnd += (sender, e) =&amp;gt; animator.RemoveAllListeners ();\n\t\tanimator.Start ();\n\t}\n\n\tprotected override void OnMeasure (int widthMeasureSpec, int heightMeasureSpec)\n\t{\n\t\tvar width = View.MeasureSpec.GetSize (widthMeasureSpec);\n\t\tSetMeasuredDimension (width &amp;lt; DefaultWidth ? DefaultWidth : width,\n\t\t                      DefaultHeight);\n\t}\n\n\tprotected override void OnDraw (Canvas canvas)\n\t{\n\t\tbase.OnDraw (canvas);\n\n\t\tfloat middle = canvas.Width * (float)position;\n\t\tcanvas.DrawPaint (negativePaint);\n\t\tcanvas.DrawRect (0,\n\t\t                 0,\n\t\t                 middle,\n\t\t                 canvas.Height,\n\t\t                 positivePaint);\n\t}\n}\n<\/pre>\n<p>To set the value displayed by the bar (between `0.0f` and `1.0f`), you can either directly use the property <code>KarmaValue<\/code>\/<code>SetKarmaValue<\/code>. Or, if you maintain a count of your positive\/negatives values, you can use the <code>SetKarmaBasedOnValues<\/code> method.\t\t<\/p>\n","protected":false},"excerpt":{"rendered":"<p>To represent the two competing &#8220;like&#8221; and &#8220;dislike&#8221; tallies on individual videos, YouTube uses an elegant solution&mdash;a partially filled bar that indicates both values: I wanted to use a similar interface in one of my applications to represent the &#8220;given&#8221; and &#8220;received&#8221; counts for an item. To display the values, I created a custom Android [&hellip;]<\/p>\n","protected":false},"author":1925,"featured_media":39167,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[5,4],"class_list":["post-3321","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-developers","tag-android","tag-xamarin-platform"],"acf":[],"blog_post_summary":"<p>To represent the two competing &#8220;like&#8221; and &#8220;dislike&#8221; tallies on individual videos, YouTube uses an elegant solution&mdash;a partially filled bar that indicates both values: I wanted to use a similar interface in one of my applications to represent the &#8220;given&#8221; and &#8220;received&#8221; counts for an item. To display the values, I created a custom Android [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/3321","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/users\/1925"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/comments?post=3321"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/posts\/3321\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media\/39167"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/media?parent=3321"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/categories?post=3321"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/xamarin\/wp-json\/wp\/v2\/tags?post=3321"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}