Android: Make custom seekbar opaque - android-seekbar

Hi can anyone tell me why is my Seekbar's background and progress always have some opacity and just can't be removed even I have set the alpha to 1.0. Below is my progress_drawable.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background">
<shape>
<corners android:radius="5dip" />
<gradient
android:alpha="1.0"
android:startColor="#000000"
android:endColor="#000000"/>
</shape>
</item>
<item android:id="#android:id/secondaryProgress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:alpha="1.0"
android:startColor="#000000"
android:endColor="#000000" />
</shape>
</clip>
</item>
<item android:id="#android:id/progress">
<clip>
<shape>
<corners android:radius="5dip" />
<gradient
android:alpha="1.0"
android:endColor="#2e2dff"
android:startColor="#2e2dff" />
<solid android:color="#2e2dff" />
</shape>
</clip>
</item>
And this is the SeekBar tag in activity xml:
<SeekBar
android:padding="0dp"
android:id="#+id/normalSeekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/imgPenguin"
android:alpha="1"
android:progress="0"
android:progressDrawable="#drawable/progress_drawable"
android:secondaryProgress="0" />
I got this result but I want the bars to be opaque, please advise and thanks in advanced.

Just found the issue:
normalSB.setEnabled(false);
I shouldn't use setEnabled(false) to avoid user drag on thumb, instead, I have done this to reset progress when fromUser == true:
normalSB.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int originalProgress;
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
float seekBarStarting = seekBar.getX();
float seekBarWidth = seekBar.getWidth();
float seekBarOffset = seekBar.getThumbOffset();
float ratio = (float) progress / seekBar.getMax();
float scaledProgress = ratio * seekBarWidth;
if (scaledProgress > imgPenguin.getWidth()) {
imgPenguin.setX(seekBarStarting - imgPenguin.getWidth() + scaledProgress);
}
if (fromUser == true) {
seekBar.setProgress(originalProgress);
}
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
originalProgress = seekBar.getProgress();
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});

Related

Xamarin: How to change Stepper color in Android to look like in iOS?

I have Xamarin PCL app which uses Stepper. I wanted to change the color of my Stepper button and now using the following renderer.
In PCL:
public class MyStepper : Stepper
{
public static readonly BindableProperty ColorProperty =
BindableProperty.Create(nameof(Color), typeof(Color), typeof(MyStepper), Color.Default);
public Color MyColor
{
get { return (Color)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
}
}
In iOS:
public class MyStepperRenderer : StepperRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
{
base.OnElementChanged(e);
MyStepper s = Element as MyStepper;
if (Control != null)
Control.TintColor = s.MyColor.ToUIColor();
}
}
In Android:
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
{
base.OnElementChanged(e);
MyStepper s = Element as MyStepper;
if (Control != null)
{
Control.GetChildAt(0).Background.SetColorFilter(s.MyColor.ToAndroid(), PorterDuff.Mode.Multiply);
Control.GetChildAt(1).Background.SetColorFilter(s.MyColor.ToAndroid(), PorterDuff.Mode.Multiply);
}
}
In XAML:
<local:MyStepper MyColor="Red" Maximum="10" Minimum="0" ....... />
As expected it would work like the images attached. But is it possible to make the Android color to change just the "outline" of the button like what it looks like in iOS?
How about changing the colors of the - and + also to red. Is there a way to do that also?
Based on #Sven-Michael Stübe's answer, I add some code to change the "-" and "+" color:
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
{
base.OnElementChanged(e);
MyStepper s = Element as MyStepper;
if (Control != null)
{
var button = Control.GetChildAt(0) as Android.Widget.Button;
button.SetTextColor(s.MyColor.ToAndroid());
button.SetBackground(ResourcesCompat.GetDrawable(Resources, Resource.Drawable.button_selector, null));
button.Background.SetColorFilter(s.MyColor.ToAndroid(), PorterDuff.Mode.Multiply);
var button2 = Control.GetChildAt(1) as Android.Widget.Button;
button2.SetTextColor(s.MyColor.ToAndroid());
button2.SetBackground(ResourcesCompat.GetDrawable(Resources, Resource.Drawable.button_selector, null));
button2.Background.SetColorFilter(s.MyColor.ToAndroid(), PorterDuff.Mode.Multiply);
}
}
Effectt.
go and create a the drawable with the states and set them in your Renderer instead of setting a single color.
Sven-Michael Stübe wanna say that if you set a single color as a background, then your Button will have no click effect. You could refer to: Material effect on button with background color
for more detail information.
For example:
button_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/colorAccent" android:state_pressed="true"/>
<item android:drawable="#color/colorPrimaryDark" android:state_focused="true"/>
<item android:drawable="#drawable/button_border"/>
</selector>
button_border.xml:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#00FFFFFF" />
<corners android:radius="5dp" />
<stroke
android:width="2dp"
android:color="#FFFFFF" />
</shape>
You can do it if you create a custom vector drawable
button_border.xml
Place this file in your Android Resources\drawable folder and ensure the build action is set to AndroidResource
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid android:color="#00FFFFFF" />
<corners android:radius="5dp" />
<stroke
android:width="2dp"
android:color="#FFFFFF" />
</shape>
MyStepperRenderer.cs
Then you just need to set it as background of your two buttons.
protected override void OnElementChanged(ElementChangedEventArgs<Stepper> e)
{
base.OnElementChanged(e);
var s = Element as MyStepper;
if (Control != null)
{
Control.GetChildAt(0).SetBackground(Resources.GetDrawable(Resource.Drawable.button_border));
Control.GetChildAt(1).SetBackground(Resources.GetDrawable(Resource.Drawable.button_border));
Control.GetChildAt(0).Background.SetColorFilter(s.MyColor.ToAndroid(), PorterDuff.Mode.Multiply);
Control.GetChildAt(1).Background.SetColorFilter(s.MyColor.ToAndroid(), PorterDuff.Mode.Multiply);
}
}
This will look like:
discussion
You loose states like pressed, disabled, ... (see https://developer.android.com/guide/topics/resources/color-list-resource.html)
If you don't have many different colors, go and create a the drawable with the states and set them in your Renderer instead of setting a single color. So your user will get a better feedback.

SlidingPanel for Xamarin.Android

I'm creating a slide view with 2 tabs, but I don't know why the part of tabs are "transparent", they take the background color and not the AppBar color..anyone knows why?
MainActivity:
using Android.App;
using Android.Widget;
using Android.OS;
using Android.Support.Design.Widget;
using Android.Support.V4.View;
namespace M_v1
{
[Activity(Label = "M_v1", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
SetContentView(Resource.Layout.Main);
TabLayout tabLayout = (TabLayout)FindViewById(Resource.Id.tablayout_navigation);
ViewPager viewPager = (ViewPager)FindViewById(Resource.Id.pager);
SetupviewPager(viewPager);
tabLayout.SetupWithViewPager(viewPager);
}
private void SetupviewPager(ViewPager viewPager)
{
viewPager.OffscreenPageLimit = 2;
PageAdapter adapter = new PageAdapter(SupportFragmentManager);
adapter.AddFragment(new Fragment1(), "One");
adapter.AddFragment(new Fragment2(), "Two");
viewPager.Adapter = adapter;
}
}
}
Here the theme:
<style name = "AppTheme" parent = "Theme.AppCompat.Light.NoActionBar">
<item name = "windowActionBar">true</item>
<item name ="windowNoTitle">false</item>
<item name ="colorPrimary">#2B5C56</item>
<item name ="colorPrimaryDark">#000000</item>
<item name ="colorAccent">#FFEE58</item>
</style>
Having the problem that the new TabLayout uses the indicator colour from the value colorAccent, I decided to dig into the android.support.design.widget.TabLayout implementation, finding that there are no public methods to customize this. However, I found this style specification of the TabLayout:
<style name="Base.Widget.Design.TabLayout" parent="android:Widget">
<item name="tabMaxWidth">#dimen/tab_max_width</item>
<item name="tabIndicatorColor">?attr/colorAccent</item>
<item name="tabIndicatorHeight">2dp</item>
<item name="tabPaddingStart">12dp</item>
<item name="tabPaddingEnd">12dp</item>
<item name="tabBackground">?attr/selectableItemBackground</item>
<item name="tabTextAppearance">#style/TextAppearance.Design.Tab</item>
<item name="tabSelectedTextColor">?android:textColorPrimary</item>
Having this style specification, now we can customize the TabLayout like this:
<android.support.design.widget.TabLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#id/pages_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="#style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:tabIndicatorColor="#android:color/white"
app:tabIndicatorHeight="4dp"/>

Set Spark TextInput Background when fail validation

How do I specify what a TextInput looks like in the error state? There appears to be a real scarcity of documentation on the subject!
There isn't an error state, but there is an errorSkin which you can specify (does it have to be a subclass of ErrorSkin?).
I want to set the TextInput's background color and increase the thickness of the border when validation fails. How do I do this?
Here's what I ended up with:
public class ObviousErrorSkin extends ErrorSkin
{
private static var glowFilter:GlowFilter = new GlowFilter(0xFF0000, 0.85, 8, 8, 3, 1, true, true);
private static var rect:Rectangle = new Rectangle();
private static var filterPt:Point = new Point();
override protected function processBitmap():void
{
rect.x = rect.y = 0;
rect.width = bitmap.bitmapData.width;
rect.height = bitmap.bitmapData.height;
glowFilter.color = target.getStyle("errorColor");
bitmap.bitmapData.applyFilter(bitmap.bitmapData, rect, filterPt, glowFilter);
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
// Early exit if we don't have a target object
if (!target)
return;
super.updateDisplayList(unscaledWidth, unscaledHeight);
graphics.clear();
graphics.beginFill(target.getStyle("errorColor"), 0.25);
graphics.drawRect(bitmap.x, bitmap.y, bitmap.width, bitmap.height);
graphics.endFill();
}
}
you should use errorString property to activate error state
Flex, any way to programmatically highlight a field in red the way the validators do?
have a look on this answer, I think it will help you to understand
As far as I know, there's no easy way to achieve this. The problem is that in error state component doesn't change it's own skin, it's just adds instance of errorSkin as new child. Here's code from SkinnableComponent
mx_internal function updateErrorSkin():void
{
if (errorString != null && errorString != "" && getStyle("showErrorSkin"))
{
if (!errorObj)
{
var errorObjClass:Class = getStyle("errorSkin");
if (errorObjClass)
errorObj = new errorObjClass();
if (errorObj)
{
if ("target" in errorObj)
errorObj["target"] = this;
super.addChild(errorObj);
}
}
}
else
{
if (errorObj)
super.removeChild(errorObj);
errorObj = null;
}
}
If you are adding errorSkin and extend it from SparkSkin it will have zero sizes. Of course you can set its width and height properties to parent component, but then it will overlap this parent component.
Mostly the same thing will happen if you are using skin inherited from ErrorSkin. But you need to do something with it's bitmap property. And still it will be over your main component. Yes, you can interchange error skin and main skin then make main skin transparent and maybe achieve what you need, but I advice to create your own component kinda like this:
TextInputWithError.as
package
{
import spark.components.TextInput;
[SkinState("error")]
public class TextInputWithError extends TextInput
{
public function TextInputWithError()
{
super();
}
protected var useErrorSkin:Boolean;
override public function set errorString(value:String):void
{
super.errorString = value;
setStyle("errorSkin", null);
if (value != "")
useErrorSkin = true;
else
useErrorSkin = false;
invalidateProperties();
}
override protected function commitProperties():void
{
super.commitProperties();
if (useErrorSkin != "")
skin.currentState = "error";
else
skin.currentState = getCurrentSkinState();
}
}
}
TextInputWithErrorSkin.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:fb="http://ns.adobe.com/flashbuilder/2009"
alpha.disabledStates="0.5" blendMode="normal">
<fx:Metadata>
<![CDATA[
/**
* #copy spark.skins.spark.ApplicationSkin#hostComponent
*/
[HostComponent("TextInputWithError")]
]]>
</fx:Metadata>
<s:states>
<s:State name="normal"/>
<s:State name="error"/>
<s:State name="disabled" stateGroups="disabledStates"/>
<s:State name="normalWithPrompt"/>
<s:State name="disabledWithPrompt" stateGroups="disabledStates"/>
</s:states>
<s:Rect id="background" left="1" right="1" top="1" bottom="1">
<s:fill>
<s:SolidColor id="bgFill" color="0xFFFFFF" color.error="0x00FF00" />
</s:fill>
</s:Rect>
<s:Rect left="0" right="0" top="0" bottom="0" id="border">
<s:stroke>
<s:SolidColorStroke id="borderStroke" weight="1" weight.error="2" color.error="0xFF0000" />
</s:stroke>
</s:Rect>
<s:Rect left="1" top="1" right="1" height="1" id="shadow">
<s:fill>
<s:SolidColor color="0x000000" alpha="0.12" />
</s:fill>
</s:Rect>
<s:RichEditableText id="textDisplay"
verticalAlign="middle"
widthInChars="10"
left="1" right="1" top="1" bottom="1" />
<s:Label id="promptDisplay" maxDisplayedLines="1"
verticalAlign="middle"
mouseEnabled="false" mouseChildren="false"
includeIn="normalWithPrompt,disabledWithPrompt"
includeInLayout="false"
/>
</s:SparkSkin>
And I will appreciate if someone will guide me to better solution of this problem, because I have it too =)

flex 4 - image not adding to UIComponenet

I am trying to load an image dynamically to the Image control and then add it to a sprite and add the sprite to the UIComponent.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"
applicationComplete="init()">
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<fx:int id = "_rows" />
<fx:int id = "_cols" />
</fx:Declarations>
<s:layout>
<s:VerticalLayout>
</s:VerticalLayout>
</s:layout>
<fx:Script>
<![CDATA[
import as3isolib.geom.Pt;
import as3isolib.utils.IsoDrawingUtil;
import mx.controls.Alert;
import mx.core.IVisualElement;
private var sprite:Sprite;
[Binable]
private var imgUrl:String = "http://localhost/greenrev/images//marketitems/menu_houses.png";
//[Bindable]
// private var _rows:int = 1;
// //[Bindable]
// private var _cols:int = 1;
private var _cellSize:int=40;
private function init(){
sprite = new Sprite();
//Alert.show(sprite.numChildren.toString());
imgContainer.addChild(sprite);
//Alert.show(sprite.numChildren.toString());
loadImage(imgUrl);
}
private function loadImage(url:String):void{
//img.source = url;
img.load(url);
}
private function loadingComplete(event:Event):void{
if (sprite.numChildren>0){
sprite.removeChildAt(0);
}
sprite = new Sprite();
sprite.addChild(img);
sprite.cacheAsBitmap = true;
sprite.graphics.clear();
sprite.graphics.beginFill(0xffff00, 0.3);
_rows = int(rows.text);
_cols = int(cols.text);
Alert.show(_rows.toString() + "," + _cols.toString());
IsoDrawingUtil.drawIsoRectangle(sprite.graphics,new Pt(0,0),_cellSize * _rows,_cellSize * _cols);
sprite.graphics.endFill();
if (imgContainer.numChildren>0){
imgContainer.removeChildAt(0);
}
imgContainer.addChild(sprite);
// imgContainer.addChild(img);
//Alert.show("loading complete");
}
private function loadingFail(event:IOErrorEvent):void{
Alert.show(event.text);
}
]]>
</fx:Script>
<s:BorderContainer id="main" verticalCenter="-244" horizontalCenter="-422" width="80%" height="90%">
<s:layout>
<s:VerticalLayout verticalAlign="middle" horizontalAlign="center">
</s:VerticalLayout>
</s:layout>
<s:BorderContainer>
<mx:UIComponent id="imgContainer">
</mx:UIComponent>
</s:BorderContainer>
<s:BorderContainer>
<s:layout>
<s:HorizontalLayout>
</s:HorizontalLayout>
</s:layout>
<s:VGroup>
<s:TextInput id="rows" minWidth="100" text = "{_rows}"/>
<s:TextInput id = "cols" minWidth="100" text = "{_cols}"/>
<s:TextInput id = "txtImgUrl" minWidth="400" text="{imgUrl}"/>
<s:Button label="Refresh" click="loadImage(imgUrl)"/>
</s:VGroup>
</s:BorderContainer>
</s:BorderContainer>
<mx:Image id="img" complete="loadingComplete(event)" visible="true" ioError="loadingFail(event)">
</mx:Image>
</s:Application>
I have no clue why the image is not being shown. Like you can see, I am trying to add the image after the COMPLETE event occurs. Please help
I changed the URL to "http://horses-bg.net/wp-content/uploads/2009/11/2752_beloved-horses.jpg" and the image appeared.
I've also commented out the IsoDrawingUtil.drawIsoRectangle(..) cause i don't have the lib you're using.
The problem might be in your URL or in that IsoDrawingutil thing :]
Hope this helps,
Good luck!
Blaze

Blinking of primitive (lines/rect), images and text in Flex

We are building a visual learning program and need to display the "question content" with highlights. We were considering using blinking text, primitives and images.
We don't want to use timer, given that it leads to a load of pain when there are other timer-driven animation on screen.
Any thoughts on how to achieve this?
Hello :]
One way to achieve the blinking effect is to create a glow filter and then animate it's alpha property.
Then set the effect to the label you want.
If you want the whole text blinking, then just animate the alpha property of the text. Here is some
example code:
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
<s:GlowFilter id="myGlowFilter"
color="#00FFAA"
blurX="5"
blurY="5"
quality="8"
/>
<s:AnimateFilter id="myGlowEffect"
bitmapFilter="{myGlowFilter}"
repeatCount="0"
repeatBehavior="reverse"
duration="1000"
>
<s:motionPaths>
<s:SimpleMotionPath property="alpha"
valueFrom="0"
valueTo="1"
/>
</s:motionPaths>
</s:AnimateFilter>
<s:Animate id="myBlinkingEffect"
repeatCount="0"
repeatBehavior="reverse"
target="{backgroundColorOfRect}"
duration="1000"
>
<s:motionPaths>
<s:SimpleMotionPath property="alpha"
valueFrom="1"
valueTo="0"
/>
</s:motionPaths>
</s:Animate>
</fx:Declarations>
<s:layout>
<s:VerticalLayout />
</s:layout>
<s:Label text="How fast can a dragonfly fly?"
creationCompleteEffect="{myGlowEffect}"
fontSize="24"
buttonMode="true"
click="myFadeEffect.play()"
/>
<s:Rect width="200" height="200">
<s:fill>
<s:SolidColor id="backgroundColorOfRect" color="red" />
</s:fill>
</s:Rect>
I suppose you should create a set of components with blinking ability and use them across your application. For better results you can use frame based events. For example a code for a blinking label:
package
{
import flash.events.Event;
import spark.components.Label;
[Style(name="numOfFramesPerBlink", inherit="yes", type="uint")]
public class BlinkingLabel extends Label
{
private static const DEFAULT_NUM_OF_FRAMES_PER_BLINK:Number = 10;
private var _explicitVisibility:Boolean = true;
private var blinkingDirty:Boolean;
private var currentBlinkingPhaseFrames:uint;
private var numOfFramesPerBlinkValue:uint = DEFAULT_NUM_OF_FRAMES_PER_BLINK;
override public function get visible():Boolean
{
return _explicitVisibility;
}
override public function set visible(value:Boolean):void
{
super.visible = value;
_explicitVisibility = value;
}
private var _blinking:Boolean;
[Bindable]
public function get blinking():Boolean
{
return _blinking;
}
public function set blinking(value:Boolean):void
{
if (_blinking == value)
return;
_blinking = value;
blinkingDirty = true;
invalidateProperties();
}
override public function styleChanged(styleProp:String):void
{
super.styleChanged(styleProp);
var allStyles:Boolean = styleProp == null || styleProp == "styleName";
if (allStyles || styleProp == "numOfFramesPerBlink")
{
var newNumOfFramesPerBlink:uint = getStyle("numOfFramesPerBlink");
if (newNumOfFramesPerBlink > 0)
numOfFramesPerBlinkValue = newNumOfFramesPerBlink;
else
numOfFramesPerBlinkValue = DEFAULT_NUM_OF_FRAMES_PER_BLINK
}
}
override protected function commitProperties():void
{
super.commitProperties();
if (blinkingDirty)
{
if (_blinking)
{
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
currentBlinkingPhaseFrames = 0;
}
else
{
removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
setVisibleState(_explicitVisibility);
}
blinkingDirty = false;
}
}
private function setVisibleState(value:Boolean):void
{
super.visible = value;
}
private function enterFrameHandler(event:Event):void
{
currentBlinkingPhaseFrames++;
if (currentBlinkingPhaseFrames > numOfFramesPerBlinkValue)
{
setVisibleState(!super.visible);
currentBlinkingPhaseFrames = 0;
}
}
}
}
The usage is pretty simple:
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" xmlns:local="*">
<s:layout>
<s:VerticalLayout horizontalAlign="center" verticalAlign="middle" />
</s:layout>
<local:BlinkingLabel text="Test Label" id="blinkingLabel" numOfFramesPerBlink="{framesPerBlinkSlider.value}" />
<s:CheckBox label="Blink Label" selected="#{blinkingLabel.blinking}" />
<s:HSlider minimum="1" maximum="100" value="10" id="framesPerBlinkSlider" />
</s:Application>
Hope this helps!

Resources