I am using a custom seekbar to show a graph. I had done till this. I am showing this graph by applying a background drawable to the seekbar. Now my problem is, I need to set the blue one as progress drawable and need to set the background of seekbar as the red graph. So that when progress happens thumb moves over red the area where thumb passed should be changed to blue color like a masking effect. Can any one tell the best possible way to do this. My pictures are shown below
After reading all the questions and answers I hope this should be your scenario to get your thing done...
1.Create two graphs
As per your logic.
2.Generate two drwables from the particular bitmaps....
Drawable G_bg = new BitmapDrawable(Red graph bitmap);
Drawable G_pg = new BitmapDrawable(Blue graph bitmap);
3.And then customize your seek bar using layer list created through the java code.
ClipDrawable c=new ClipDrawable(G_pg, Gravity.LEFT,ClipDrawable.HORIZONTAL);
LayerDrawable ld =new LayerDrawable (new Drawable[]{G_bg,c});
4.Apply this layer list to your seekbar.
Graphbar.setProgressDrawable(ld);
This should work like you wanted....Thanksss
Is this not what you wanted?
my_seek_bar_progress.xml:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#android:id/background"
android:drawable="#drawable/red_graph"/>
<item android:id="#android:id/progress">
<clip android:drawable="#drawable/blue_graph" />
</item>
</layer-list>
in Fragment or Activity layout:
<com.example.seekbaroverlay.MySeekBar
android:id="#+id/mySeekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100" />
MySeekBar.java:
public class MySeekBar extends SeekBar {
public MySeekBar(Context context) {
this(context, null);
}
public MySeekBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MySeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setProgressDrawable(context.getResources().getDrawable(R.drawable.my_seek_bar_progress));
setThumb(context.getResources().getDrawable(R.drawable.my_thumb));
}
}
You should use a custom progressDrawable for your SeekBar. See this blog post for a great tutorial.
You can create a custom view.Override it's onTouch() method to change position of thumb.Also override it's onDraw() method and first draw red graph as background of your view and then the blue one from position that corresponds to the position of thumb.
Related
So I am running into a weird issue... I have made some code to tint a Drawable, and it is working on all Android versions for Vector assets, but not for regular PNG assets. The code is below:
public class TintHelper {
private Context mContext;
public TintHelper(Context context) {
mContext = context;
}
public Drawable getTintedDrawableFromResource(int resourceID, ColorStateList colorStateList) {
Drawable original = AppCompatDrawableManager.get().getDrawable(mContext, resourceID);
return performTintOnDrawable(original, colorStateList);
}
private Drawable performTintOnDrawable(Drawable drawable, ColorStateList colorStateList) {
Drawable tinted = DrawableCompat.wrap(drawable);
DrawableCompat.setTintList(tinted, colorStateList);
return tinted;
}
}
When I specify the resource ID of a vector asset, the code works perfectly and the image is tinted when pressed, but when I use a regular PNG, there is no tint applied when the icon is pressed. If anyone has any ideas of why this doesn't work, please post an alternative method that could potentially support both asset types.
Thanks in advance!
It is work for PNG in my environment.
set like this:
int resourceID = R.drawable.ic_launcher;
TintHelper tintHelper = new TintHelper(this);
Drawable drawable = tintHelper.getTintedDrawableFromResource(resourceID,
ContextCompat.getColorStateList(this, R.color.colors));
ImageView imageView = (ImageView) findViewById(R.id.image);
imageView.setImageDrawable(drawable);
colors.xml is like this:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:color="#android:color/holo_red_dark"/>
<item android:state_selected="true" android:color="#android:color/holo_red_dark"/>
<item android:state_pressed="true" android:color="#android:color/holo_red_dark"/>
<item android:color="#android:color/white"/>
</selector>
I found the problem. Essentially, DrawableCompat.setTintList() is not working as expected on Android 21 and above. This is due to their implementation not calling invalidate() when there are state changes. More details can be read on this bug report.
To get this tinting code working for all platforms and all resource types, I needed to create a custom ImageView class as shown below:
public class StyleableImageView extends AppCompatImageView {
public StyleableImageView(Context context) {
super(context);
}
public StyleableImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public StyleableImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
// This is the function to override...
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
invalidate(); // THE IMPORTANT LINE
}
}
Hopefully this helps someone that has had to deal with a similar situation.
EDIT I just tried an EditText without a TextInputLayout and it works as expected. So the problem must be with new changes in the TextInputLayout.
I have been using a custom EditText class as child of a TextInputLayout for around a month. When the user typed, an x would appear in the drawableRight field. I have successfully displayed images for drawableLeft, drawableTop, and drawableBottom, but setting drawableRight provides me with a blank. Note: Clicking the blank space where the X SHOULD be works as expected, the text is cleared.
This first picture is how it originally looked:
Ever since upgrading to support-v4:24.2.0 the functionality has been broken. It now places the "x" where a drawable set with drawableBottom should appear. This second picture shows the new behavior:
XML Code
<android.support.design.widget.TextInputLayout
android:id="#+id/til_delivery_info_state"
android:hint="#string/state_hint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/large_margin"
android:layout_marginRight="#dimen/large_margin">
<com.example.ui.edittexts.ClearableEditText
android:id="#+id/et_state"
android:inputType="textCapWords|text|textNoSuggestions"
android:nextFocusDown="#+id/et_di_zip_code"
android:text="#={deliveryViewModel.state}"
android:gravity="center_vertical|left"
android:singleLine="true"
android:textSize="#dimen/text_size"/>
</android.support.design.widget.TextInputLayout>
Java
final Drawable drawable = ContextCompat.getDrawable(context, R.drawable.ic_clear_text_gray_x);
final Drawable wrappedDrawable = DrawableCompat.wrap(drawable);
mClearTextIcon.setBounds(0, 0, mClearTextIcon.getIntrinsicWidth(), mClearTextIcon.getIntrinsicHeight());
mClearTextIcon.setVisible(true, false);
final Drawable[] compoundDrawables = getCompoundDrawables();
setCompoundDrawablesWithIntrinsicBounds(
compoundDrawables[0],
compoundDrawables[1],
visible ? mClearTextIcon : null,
compoundDrawables[3]);
UPDATE 14 SEP 2016
A new version of support library 24.2.1 is out and this issue is marked as fixed. According to changelog
Fixed issues:
TextInputLayout overrides right compound drawable. (AOSP issue 220728)
Original answer
Warning 1
This answer will break this new password visibility toggle feature.
Warning 2
This answer may cause an unexpected behaviour after updating support lib (assuming that they will fix this issue).
Looks like TextInputLayout screws things up here, specifically these lines from updatePasswordToggleView method.
final Drawable[] compounds = TextViewCompat.getCompoundDrawablesRelative(mEditText);
TextViewCompat.setCompoundDrawablesRelative(mEditText, compounds[0], compounds[1], mPasswordToggleDummyDrawable, compounds[2]);
As you can see it sets mPasswordToggleDummyDrawable as a right drawable and then sets compounds[2] (which is your custom drawable that you want to be one the right) as a bottom drawable.
updatePasswordToggleView method is called in onMeasure method. Possible workaround is to create a custom TextInputEditText and override it's onMeasure method. Let's call it PassFixTextInputEditText
public class PassFixTextInputEditText extends TextInputEditText {
public PassFixTextInputEditText(final Context context) {
super(context);
}
public PassFixTextInputEditText(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
public PassFixTextInputEditText(final Context context, final AttributeSet attrs, final int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Drawable[] drawables = getCompoundDrawables();
setCompoundDrawables(drawables[0], drawables[1], drawables[3], null);
}
}
and use it like this
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:errorEnabled="true">
<com.kamilzych.temp.PassFixTextInputEditText
android:id="#+id/textInputEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:maxLength="23"/>
</android.support.design.widget.TextInputLayout>
(don't forget to change the package name)
As you can see, after TextInputLayout sets your custom drawable as bottom drawable we set it as a right one.
I was trying to make a tricky layout for which i need the Android's default tab indicator color.
I have searched a lot but every where I find how to change and customize tab indicator but could not find how to get color code in hex of default tab indicator.
I did some research for your question, I hope this will help you.
The tab indicator color is set in the Inner Class SlidingTabStrip of the class TabLayout (Code). Sadly you can't access this variable.
private class SlidingTabStrip extends LinearLayout {
private final Paint mSelectedIndicatorPaint;
// ...
void setSelectedIndicatorColor(int color) {
if (mSelectedIndicatorPaint.getColor() != color) {
mSelectedIndicatorPaint.setColor(color);
ViewCompat.postInvalidateOnAnimation(this);
}
}
}
But in a constructor of the TabLayout the default tab indicator color is set.
public TabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// Add the TabStrip
mTabStrip = new SlidingTabStrip(context);
addView(mTabStrip, LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TabLayout, defStyleAttr, R.style.Widget_Design_TabLayout);
// <-- HERE
mTabStrip.setSelectedIndicatorColor(a.getColor(R.styleable.TabLayout_tabIndicatorColor, 0));
}
I think you need to access R.styleable.TabLayout_tabIndicatorColor to get what you want. I don't have the possibility right now to test if and how it works but I hope this helps you a bit.
Update
I tried this at home and it seems to work. I used this code in the onCreate() method of my Activity
TypedArray a = getContext().obtainStyledAttributes(null, R.styleable.TabLayout, 0, R.style.Widget_Design_TabLayout);
// returns -16738680 in my case which is the accentColor
int color = a.getColor(R.styleable.TabLayout_tabIndicatorColor, 0);
But I saw, that R.styleable.TabLayout_tabIndicatorColor just links to the accentColor. Maybe this is the better way to get what you want.
<style name="Base.Widget.Design.TabLayout" parent="android:Widget">
<item name="tabIndicatorColor">?attr/colorAccent</item>
<!-- other items -->
</style>
I have a lot of views using one and the same color as a background. I want to change the color of all views when I receive a call from the server programmatically. I don't want to call for every view
view.setBackgroundColor(new color);
Is there a way to change a color code that is in colors.xml.
Short answer: No, you can't. The resources are defined at compile time.
See this question for a similar case: How can I programmatically change the value of a color in colors.xml?
You can't replace the value of the color in the xml file. But you
can create different themes which are used in your application and
change the theme dynamically
See this tutorial:
http://www.developer.com/ws/android/changing-your-android-apps-theme-dynamically.html
What I end up doing is create a custom class that sets the color form preference. And use this class everywhere I want to change the color. And next time the view is drawn it gets the new color. Something like this:
public class ColoredToolbar extends android.support.v7.widget.Toolbar {
public ColoredToolbar(Context context) {
super(context);
setBackgroundColor(context);
}
public ColoredToolbar(Context context, AttributeSet attrs) {
super(context, attrs);
setBackgroundColor(context);
}
public ColoredToolbar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setBackgroundColor(context);
}
private void setBackgroundColor(Context context) {
int color = PreferenceHelper.getToolBarColor(context, Preferences.PREF_TITLE_BAR_COLOR_KEY);
this.setBackgroundColor(color);
}
}
I'm trying to create a View with rounded corners (and a background color of choice) that I can reuse with different background colors; hard to explain, so here's my code:
/app/src/com/packagename/whatever/CustomDrawableView.java
package com.packagename.whatever;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.PaintDrawable;
import android.util.AttributeSet;
import android.view.View;
public class CustomDrawableView extends View {
private PaintDrawable mDrawable;
int radius;
private void init(AttributeSet attrs) {
TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.RoundedRect);
radius = a.getInteger(R.styleable.RoundedRect_radius, 0);
}
public CustomDrawableView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
mDrawable = new PaintDrawable();
}
protected void onDraw(Canvas canvas) {
mDrawable.setCornerRadius(radius);
mDrawable.draw(canvas);
}
}
Here's the XML to display the custom component:
/app/res/layout/test.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ny="http://schemas.android.com/apk/res/com.packagename.whatever"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffffff"
android:padding="10dp">
<com.packagename.whatever.CustomDrawableView
android:id="#+id/custom"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#b80010"
ny:radius="50"
/>
</LinearLayout>
I'm wanting the red box to have 50px rounded corners, but as you'll see, it does not:
The idea is that I could easily change the background color in the XML and automatically have a nice View with rounded corners, without having to create multiple drawables.
Thanks for the help!
You need to set your corner radius and color into the background drawable.
Here is one way that would work. Grab the color you set in android:background, then use it to create a new drawable that you set into the background in the constructor. This will work as long as you only set android:background to a color value.
public CustomDrawableView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
// pull out the background color
int color = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "background", 0xffffffff);
// create a new background drawable, set the color and radius and set it in place
mDrawable = new PaintDrawable();
mDrawable.getPaint().setColor(color);
mDrawable.setCornerRadius(radius);
setBackgroundDrawable(mDrawable);
}
If you override onDraw, make sure you call super.onDraw(canvas) first to get the background drawn.
given a simple shapedrawable like this:
public ShapeDrawable Sd(int s){
float[] outerR = new float[] { 12, 12, 12, 12, 12, 12, 12, 12 };
ShapeDrawable mDrawable = new ShapeDrawable(new RoundRectShape(outerR, null,null));
mDrawable.getPaint().setColor(s);
return mDrawable;
}
you can do the following:
LinearLayout l=(LinearLayout) findViewById(R.id.testLayout);
l.setBackgroundDrawable(Sd(0xff74AC23));
where the 12's represent the radius.
you could apply this to any view for a background drawable.
Take a look at this question: How do I set the rounded corner radius of a color drawable using xml?
And perhaps also these two:
How to add rounded corner to a drawable I'm using as a background in Android?
How should I give images rounded corners in Android?