Text in android button is being cut - android

I have an issue concerning the dynamic change of Button sizes.
So, I defined 4 Buttons bellow the yellow progressbar (2 above, 2 below) like shown in the image.
I have a class RatioButton that extend Button and in the method onMeasure() I redefine the size of the buttons to a certain ratio. The buttons above are RatioButton views and the buttons below are Button views. So far so good.
The problem, as you can see in the image, is that the text in the upper buttons is cut. What I want is that the text could adapt to the available space of the button. Can you help me?
Below is the RatioButton class:
public class RatioButton extends Button {
public static final double RATIO = 280.0/260.0;
public RatioButton(Context context) {
super(context);
}
public RatioButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RatioButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int size = width > height ? height : width;
setMeasuredDimension((int)(size*RATIO), size);
}
}
Below is the layout definiton of the buttons (is the same for all four but the two below are just Button instead of RatioButton):
<myapp.pt.quiz.utils.RatioButton
style="#style/ChoiceButton"
android:id="#+id/game_screen_button3"
android:layout_gravity="right"
android:textAlignment="center"
android:text="This text is for layout testing"/>
This is the style ChoiceButton used in four buttons:
<style name="ChoiceButton">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">match_parent</item>
<item name="android:background">#drawable/shape_choicebutton</item>
<item name="android:layout_margin">3dp</item>
<item name="android:textAllCaps">false</item>
<item name="android:padding">5dp</item>
</style>
And by the way, below is the drawable shape_choicebutton:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<layer-list>
<item android:left="1dp" android:top="3dp">
<shape>
<solid android:color="#ffffff" />
<corners android:radius="3dip"/>
</shape>
</item>
</layer-list>
</item>
<item>
<layer-list>
<item android:left="0dp" android:top="0dp">
<shape>
<solid android:color="#ffffff" />
<corners android:radius="3dip"/>
</shape>
</item>
<item android:bottom="3dp" android:right="2dp">
<shape>
<solid android:color="#ffffff" />
<corners android:radius="3dip"/>
</shape>
</item>
</layer-list>
</item>
</selector>
I hope the code helps to understand my doubt.

Related

Round button without corners in Android [duplicate]

MOCK UP
Requirement
I want to put custom button with selector.
Mock up is given above.
If anyone knows solution then share it.
Thank you.
basically you will need to create some new XML files and apply them to your Button element. As i can see from the mockup you will need a stroke and the background color with some shading effect applied, you can research more into the shading thing but the background color and the stroke is pretty straight forward.
Here is an example, done_rounded_btn.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:state_enabled="true"
android:drawable="#drawable/zzzzzzzzz_btn_orange" />
<item
android:state_focused="true"
android:state_enabled="true"
android:drawable="#drawable/zzzzzzzzz_btn_orange" />
<item
android:state_focused="false"
android:state_enabled="false"
android:drawable="#drawable/zzzzzzzzz_btn_inactiv" />
<item android:drawable="#drawable/zzzzzzzzz_btn_black"/>
</selector>
for the selection part and then you create the custom drawables corresponding to the mockup.
An example, zzzzzzzzzz_btn_orange:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid
android:color="#color/done_color">
</solid>
<corners
android:bottomLeftRadius="3dp"
android:bottomRightRadius="3dp"
android:topLeftRadius="3dp"
android:topRightRadius="3dp" />
</shape>
And then add it to your button as background, main.xml:
<Button
android:id="#+id/registers_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:background="#drawable/done_rounded_btn"
android:text="#string/done_txt"
android:textColor="#color/white"
android:textSize="15sp" />
Hope this helps!
You can use this instead of standard Button and set selector as background in xml:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
/**
* Custom Shape Button which ignores touches on transparent background.
*/
public class ButtonWithUntouchableTransparentBg extends Button {
public ButtonWithUntouchableTransparentBg(Context context) {
this(context, null);
}
public ButtonWithUntouchableTransparentBg(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ButtonWithUntouchableTransparentBg(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setDrawingCacheEnabled(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
// ignores touches on transparent background
if (isPixelTransparent(x, y))
return true;
else
return super.onTouchEvent(event);
}
/**
* #return true if pixel from (x,y) is transparent
*/
private boolean isPixelTransparent(int x, int y) {
Bitmap bmp = Bitmap.createBitmap(getDrawingCache());
int color = Color.TRANSPARENT;
try {
color = bmp.getPixel(x, y);
} catch (IllegalArgumentException e) {
// x or y exceed the bitmap's bounds.
// Reverts the View's internal state from a previously set "pressed" state.
setPressed(false);
}
// Ignores touches on transparent background.
if (color == Color.TRANSPARENT)
return true;
else
return false;
}
}
You can also create a shape that is using a selector inside. If your shape is just changing its color in different states, this is a lot cleaner.
color/color_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/blue_dark" android:state_pressed="true" />
<item android:color="#color/blue_light" />
</selector>
drawable/shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/color_selector" />
<corners android:bottomLeftRadius="6dip" android:bottomRightRadius="6dp" />
<padding android:bottom="0dip" android:left="0dip" android:right="0dip" android:top="0dip" />
</shape>
Button with rounded corners with two states (enabled/disabled):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<shape android:shape="rectangle">
<corners android:radius="28dp" />
<solid android:color="#color/white" />
<stroke android:width="1dp" android:color="#color/orange" />
</shape>
</item>
<item android:state_enabled="false">
<shape android:shape="rectangle">
<corners android:radius="28dp" />
<solid android:color="#color/grey_card_background" />
<stroke android:width="1dp" android:color="#color/grey" />
</shape>
</item>
</selector>
inside your item put the shape in the selector XML
EX FROM MY CODE :
<!-- if pressed -->
<item android:state_pressed="true"><shape android:padding="10dp" android:shape="rectangle">
<solid android:color="#color/blue" />
<corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp" android:topLeftRadius="10dp" android:topRightRadius="10dp" />
</shape></item>
<!-- if not pressed -->
<item><shape android:padding="10dp" android:shape="rectangle">
<solid android:color="#color/Purbble" />
<corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp" android:topLeftRadius="10dp" android:topRightRadius="10dp" />
</shape></item>

ColorStateList and TextColor not being applied using CustomAttr in ToggleButton in Android

I have a custom class called SkinableToggleButton which extends ToggleButton of Android. Its code is as below:
public class SkinableToggleButton extends ToggleButton {
public SkinableToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public SkinableToggleButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//Applied custom font/typeface here
init(context, attrs);
}
protected void init(Context context, AttributeSet attrs) {
if (isInEditMode()) return;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Skinable, 0, 0);
try {
if (a.hasValue(R.styleable.Skinable_skinableTextColor)) {
int textColorSkin = a.getInt(R.styleable.Skinable_skinableTextColor, 0);
SkinUtil.applyTextColorTheme(this, textColorSkin);//Applying custom text color through custom attr
}
if (a.hasValue(R.styleable.Skinable_skinableSrcTint)) {
int backgroundTintSkin = a.getInt(R.styleable.Skinable_skinableSrcTint, 0);
int checkedColor = SkinUtil.getColor(backgroundTintSkin);//util method returning correct color
int disabledColor = ContextCompat.getColor(getContext(), R.color.grey_3);
int[][] states = new int[][]{
new int[]{android.R.attr.state_checked}, // checked
new int[]{-android.R.attr.state_checked}, // unchecked
new int[]{android.R.attr.state_enabled}, // enabled
new int[]{-android.R.attr.state_enabled} // disabled
};
int[] colors = new int[]{
checkedColor,
checkedColor,
checkedColor,
disabledColor
};
compoundButton.setButtonTintList(new ColorStateList(states, colors));
}
} finally {
a.recycle();
}
}}
In XML, I have used it as follows:
<SkinableToggleButton
android:layout_width="wrap_content"
style="#style/tiny_toggle_button"
android:textOff="Connect"
android:textOn="Connected"/>
Style tiny_toggle_button code:
<style name="tiny_toggle_button">
<item name="android:background">#drawable/selector_toggle_btn</item>
<item name="android:layout_height">#dimen/spacing_5x</item>
<item name="android:textSize">#dimen/sp_12</item>
<item name="android:lineHeight">#dimen/sp_16</item>
<item name="android:letterSpacing">0.0175</item>
<item name="android:textColor">#color/selector_toggle_bg</item>
<item name="skinableSrcTint">primary1</item> <!--Custom Attr-->
</style>
selector_toggle_btn drawable:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:state_checked="false" android:state_enabled="true" >
<shape
android:shape="rectangle">
<solid android:color="#color/transparent"/>
<corners android:radius="#dimen/spacing_0_5x"/>
<stroke
android:width="1dp"
android:color="#color/black"
/>
</shape>
</item>
<item android:state_checked="true" android:state_enabled="true">
<shape android:shape="rectangle">
<solid android:color="#color/black"/>
<corners android:radius="#dimen/spacing_0_5x"/>
</shape>
</item>
<item android:state_enabled="false">
<shape
android:shape="rectangle">
<solid android:color="#color/white_1"/>
<corners android:radius="#dimen/spacing_0_5x"/>
<stroke
android:width="1dp"
android:color="#color/grey_4"/>
</shape>
</item>
</selector>
selector_toggle_bg in color:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:state_enabled="true" android:state_checked="true" android:color="#color/white_1"/>
<!-- Default State -->
<item android:state_enabled="true" android:state_checked="false"
android:color="#color/black"/>
<item android:color="#color/grey_3" android:state_enabled="false"/>
</selector>
Problem:
My custom attrs (Tint colors and text colors) are not being applied from selector drawable and color files. My drawable and text color selector is working perfectly fine except for my custom attrs. Am I doing something wrong with the custom attrs and applying ColorStateList? I have set my custom attr skinableSrcTint in my custom style in styles.xml. Custom style's code has already been pasted above.
I am not very much experienced at posting questions on StackOverflow. Please let me know if any other detail is required, I will edit it and post detail/or in comments.

Vertical progressbar in Android [duplicate]

I am trying to use a ProgressBar as a metering like display. I thought it was going to be an easy task and thought that ProgressBar had a property to set to be vertical, but I'm not seeing anything.
Additionally I'd like to be able to show ruler like indicator along the side of the bar to clearly indicate the current level.
Pointers appreciated - Thanks!
I had recently come across the need for a vertical progress bar but was unable to find a solution using the existing Progress Bar widget. The solutions I came across generally required an extension of the current Progress Bar or a completely new class in it self. I wasn't convinced rolling out a new class to achieve a simple orientation change was necessary.
This article presents a simple, elegant, and most importantly, a no-hack solution to achieving a vertical progress bar.
I'm going to skip the explanation and simply provide a cookie cutter solution. If you require further details feel free to contact me or leave a comment below.
Create an xml in your drawable folder (not drawable-hdpi or drawable-mdpi -- place it in drawable). For this example I call my xml vertical_progress_bar.xml
Here's what to place in the xml file:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background">
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#ff9d9e9d"
android:centerColor="#ff5a5d5a"
android:centerY="0.75"
android:endColor="#ff747674"
android:angle="180"
/>
</shape>
</item>
<item android:id="#android:id/secondaryProgress">
<clip android:clipOrientation="vertical" android:gravity="bottom">
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#80ffd300"
android:centerColor="#80ffb600"
android:centerY="0.75"
android:endColor="#a0ffcb00"
android:angle="180"
/>
</shape>
</clip>
</item>
<item android:id="#android:id/progress">
<clip android:clipOrientation="vertical" android:gravity="bottom">
<shape>
<corners android:radius="5dip" />
<gradient
android:startColor="#ffffd300"
android:centerColor="#ffffb600"
android:centerY="0.75"
android:endColor="#ffffcb00"
android:angle="180"
/>
</shape>
</clip>
</item>
</layer-list>
Create an xml file called styles.xml and place it in res/values. If your project already contains styles.xml in res/values then skip this step.
Modify your styles.xml file and append the following code to the end of the file:
<style name="Widget">
</style>
<style name="Widget.ProgressBar">
<item name="android:indeterminateOnly">true</item>
<item name="android:indeterminateBehavior">repeat</item>
<item name="android:indeterminateDuration">3500</item>
<item name="android:minWidth">48dip</item>
<item name="android:maxWidth">48dip</item>
<item name="android:minHeight">48dip</item>
<item name="android:maxHeight">48dip</item>
</style>
<style name="Widget.ProgressBar.Vertical">
<item name="android:indeterminateOnly">false</item>
<item name="android:progressDrawable">#drawable/progress_bar_vertical</item>
<item name="android:indeterminateDrawable">#android:drawable/progress_indeterminate_horizontal</item>
<item name="android:minWidth">1dip</item>
<item name="android:maxWidth">12dip</item>
</style>
Add your new vertical progress bar to your layout. Here's an example:
<ProgressBar
android:id="#+id/vertical_progressbar"
android:layout_width="12dip"
android:layout_height="300dip"
style="#style/Widget.ProgressBar.Vertical"
/>
That should be all you need to do to make use of a vertical progress bar in your project. Optionally, you might have custom drawable nine-patch images that you are using for the progress bar. You should make the appropriate changes in the progress_bar_vertical.xml file.
I hope this helps you out in your project!
You have to create your own custom progressbar.
In your xml add this layout:
<com.example.component.VerticalProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:id="#+id/verticalRatingBar1"
android:layout_width="wrap_content"
android:progress="50"
android:layout_height="fill_parent" />
VerticalProgressBar.java
public class VerticalProgressBar extends ProgressBar{
private int x, y, z, w;
#Override
protected void drawableStateChanged() {
// TODO Auto-generated method stub
super.drawableStateChanged();
}
public VerticalProgressBar(Context context) {
super(context);
}
public VerticalProgressBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
this.x = w;
this.y = h;
this.z = oldw;
this.w = oldh;
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setSelected(true);
setPressed(true);
break;
case MotionEvent.ACTION_MOVE:
setProgress(getMax()
- (int) (getMax() * event.getY() / getHeight()));
onSizeChanged(getWidth(), getHeight(), 0, 0);
break;
case MotionEvent.ACTION_UP:
setSelected(false);
setPressed(false);
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
#Override
public synchronized void setProgress(int progress) {
if (progress >= 0)
super.setProgress(progress);
else
super.setProgress(0);
onSizeChanged(x, y, z, w);
}
}
Or :
Jagsaund solution is also being perfect.
I know that it´s an old post but I found a very simple solution to this problem that maybe can help somebody.
First at all create a progress_drawable_vertical.xml like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background">
<color android:color="#777" />
</item>
<item android:id="#android:id/progress">
<clip
android:clipOrientation="vertical"
android:gravity="bottom">
<shape>
<gradient
android:startColor="#00FF00"
android:centerColor="#FFFF00"
android:endColor="#FF0000"
android:angle="90" />
</shape>
</clip>
</item>
</layer-list>
Then just use this in your progressBar:
<ProgressBar
android:id="#+id/progress_bar"
style="#android:style/Widget.ProgressBar.Horizontal"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:max="100"
android:progress="33"
android:progressDrawable="#drawable/progress_drawable_vertical" />
I also have created an progress_drawable_horizontal.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background">
<color android:color="#777" />
</item>
<item android:id="#android:id/progress">
<clip
android:clipOrientation="horizontal"
android:gravity="left">
<shape>
<gradient
android:startColor="#00FF00"
android:centerColor="#FFFF00"
android:endColor="#FF0000" />
</shape>
</clip>
</item>
</layer-list>
with the objetive of mantain the same style defined in progress_drawable_vertical.xml
The key here is the correct use of android:clipOrientation and android:gravity.
I found this solution here and the core of the solution is similar to jagsaund but a little bit more simple.
I found the probably best(easiest & most versatile) solution:)
This is an old post, but it was so hard for me to find this so easy solution so I thought I should post it..
Just use a scale-drawable (or a 9-patch if you want), no need for ANY OTHER code.
Example:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background" android:drawable="#color/transparent"/>
<item android:id="#android:id/progress">
<scale android:scaleGravity="bottom" android:scaleWidth="0%" android:scaleHeight="100%">
<shape >
<solid android:color="#color/blue"/>
<corners android:topRightRadius="1dp" android:topLeftRadius="1dp"/>
</shape>
</scale>
</item>
</layer-list>
And of course the normal code:
<ProgressBar
android:id="#+id/progress_bar"
style="#android:style/Widget.ProgressBar.Horizontal"
android:layout_width="24dp"
android:layout_height="match_parent"
android:max="1000"
android:progress="200"
android:progressDrawable="#drawable/progress_scale_drawable" />
Notice the scale-drawable's xml lines (the magic lines):
android:scaleGravity="bottom" //scale from 0 in y axis (default scales from center Y)
android:scaleWidth="0%" //don't scale width (according to 'progress')
android:scaleHeight="100%" //do scale the height of the drawable
This perfectly works
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background">
<shape>
<gradient
android:startColor="#DDDDDD"
android:centerColor="#DDDDDD"
android:centerY="0.75"
android:endColor="#DDDDDD"
android:angle="270"
/>
</shape>
</item>
<item
android:id="#android:id/progress">
<clip
android:clipOrientation="vertical"
android:gravity="top">
<shape>
<gradient
android:angle="0"
android:startColor="#302367"
android:centerColor="#7A5667"
android:endColor="#C86D67"/>
</shape>
</clip>
</item>
</layer-list>
<ProgressBar
android:id="#+id/progress_bar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="5dp"
android:layout_height="match_parent"`enter code here`
android:progressDrawable="#drawable/progress_dialog"/>
Creating the progress bar (I converted my code from c# to java so might not be 100% correct)
ProgressBar progBar = new ProgressBar(Context, null, Android.resource.attribute.progressDrawable);
progBar.progressDrawable = ContextCompat.getDrawable(Context, resource.drawable.vertical_progress_bar);
progBar.indeterminate = false;
vertical_progress_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="#android:id/background">
<shape>
<solid android:color="#color/grey" />
<corners android:radius="20dip" />
</shape>
</item>
<item android:id="#android:id/progress">
<scale
android:drawable="#drawable/vertical_progress_bar_blue_progress"
android:scaleHeight="100%"
android:scaleGravity="bottom"/>
</item>
</layer-list>
vertical_progress_bar_blue_progress.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners
android:radius="20dip" />
<solid android:color="#color/ProgressBarFourth" />
</shape>
What's going to make your bar vertical is the scaleHeight and scaleGravity attributes in vertical_progress_bar.xml.
It ends up looking something like this:
Simple and Easy way:
Just add a view to a LinearLayout and scale it.
<LinearLayout
android:layout_width="4dp"
android:layout_height="300dp"
android:background="#color/md_green_50"
android:orientation="vertical">
<View
android:id="#+id/progressView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="top"
android:layout_weight="1"
android:background="#color/md_green_500"
android:scaleY="0.0" />
</LinearLayout>
Set View's pivotY to zero:
progressView.pivotY = 0F
Now you can fill the progress using scaleY between 0F and 1F:
progressView.scaleY = 0.3F
Bonus:
Animate progress using animate():
progressView.animate().scaleY(0.3F).start()
Here is a simple solution, just rotate your progress bar
android:rotation="270"
Add this to the xml code
android:rotation="90"
android:transformPivotX="0dp"
So this is how your Progress Bar xml should look
<ProgressBar
android:id="#+id/progressBar6"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:rotation="90"
android:transformPivotX="0dp"
tools:layout_editor_absoluteX="101dp"
tools:layout_editor_absoluteY="187dp" />
To utilize the ProgressBar and make it vertical, you would have to create your own custom View extending the ProgressBar view and override the onDraw() method. This will allow you to draw it in a reverse orientation. Take a look at the source code of the ProgressBar.onDraw() (located at the bottom of the link) for help on how to do this. Best case scenario, you'll just have to swap a few x and y variables.
I have the exact problem. Making a custom class (extending ProgressBar) will create code that are hard to maintain. Using a custom style will cause compatibility issue with different theme from new OS (e.g. lollipop)
Eventually, I just apply a rotation animation to an horizontal progress bar. Inspired by Pete.
Create the tag in your layout xml like normal horizontal progress bar.
Make sure that the size and position of the ProgressBar is what you want after rotation. (Perhaps setting negative margin will help). In my code I rotate the view from 0,0.
Use the method below to rotate and set new progress.
Code:
private void setProgress(final ProgressBar progressBar, int progress) {
progressBar.setWillNotDraw(true);
progressBar.setProgress(progress);
progressBar.setWillNotDraw(false);
progressBar.invalidate();
}
private void rotateView(final View v, float degree) {
Animation an = new RotateAnimation(0.0f, degree);
an.setDuration(0);
an.setRepeatCount(0);
an.setFillAfter(true); // keep rotation after animation
v.setAnimation(an);
}
Simple progrebar image view
example
viewHolder.proBarTrueImage.setMaximalValue(147);
viewHolder.proBarTrueImage.setLevel(45);
viewHolder.proBarTrueImage.setColorResource(R.color.corner_blue);
simple class
public class ProgressImageView extends ImageView {
private Context mContext;
private Paint paint;
private RectF rectf;
private int maximalValue = 1;
private int level = 0;
private int width;
private int height;
public ProgressImageView(Context context) {
super(context);
init(context, null, 0);
}
public ProgressImageView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
public ProgressImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr){
mContext = context;
paint = new Paint();
rectf = new RectF();
paint.setColor(Color.GRAY);
paint.setStyle(Paint.Style.FILL);
};
#Override
protected void onDraw(Canvas canvas) {
float dif = (float) height / (float) maximalValue;
int newHeight = height - (int) (dif * level);
rectf.set(0,newHeight, width, height);
canvas.drawRect(rectf, paint);
super.onDraw(canvas);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.width = w;
this.height = h;
}
public void setMaximalValue(int maximalValue) {
this.maximalValue = maximalValue;
invalidate();
}
public void setLevel(int level) {
this.level = level;
invalidate();
}
public void setColorResource(int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
color = mContext.getResources().getColor(color,mContext.getTheme());
}else {
color = mContext.getResources().getColor(R.color.corner_blue);
}
setColor(color);
}
public void setColor(int color){
if (paint != null){
paint.setColor(color);
invalidate();
}
}
}
<ProgressBar
android:id="#+id/battery_pb"
android:rotation="270"
android:progress="100"
...
/>
Use android:rotation="270" to 100% be like bottom to top or android:rotation="90" to 100% be like top to bottom
enter link description here
**Check this link out, I was trying to use a similar thing and also you can use stepper for your requirement, few projects are available on Github about HOW TO USE STEPPER IN ANDROID STUDIO **
For making a vertical ProgressBar, The way that I solved it was first rotating it by 90 degrees, then scaling it with a value entered by hand.
scaleX = layout_height/layout_width
Here's an example of my attributes on the ProgressBar
android:layout_width="20dp"
android:layout_height="233dp"
android:rotation="-90"
android:scaleX="11.65"
This can be a little manual, but because they don't have a vertical progress bar by default, this was a pretty good workaround for me. The scaleX could be calculated automatically, but it would have to be after everything is drawn on the screen.
Vertical progress bars are not supported by default.

Android 3D button text position

How to change text position for different button states?
On image you can see how its look like now:
drawable
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true">
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="4dp">
<shape android:shape="rectangle">
<solid android:color="#DCDBDB" />
<corners android:radius="7dp" />
<stroke android:width="1dp" android:color="#B1B1B1"/>
</shape>
</item>
<item android:bottom="4.5dp" android:left="1.5dp" android:right="1.5dp" android:top="5.5dp">
<shape android:shape="rectangle" android:gravity="bottom">
<solid android:color="#F2F1F1" />
<corners android:radius="6dp" />
<stroke android:width="1dp" android:color="#FFFFFF"/>
</shape>
</item>
</layer-list>
</item>
<item>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="#DCDBDB" />
<corners android:radius="7dp" />
<stroke android:width="1dp" android:color="#B1B1B1"/>
</shape>
</item>
<item android:bottom="8.5dp" android:left="1.5dp" android:right="1.5dp" android:top="1.5dp">
<shape android:shape="rectangle">
<solid android:color="#F2F1F1" />
<corners android:radius="6dp" />
<stroke android:width="1dp" android:color="#FFFFFF"/>
</shape>
</item>
</layer-list>
</item>
</selector>
Few days ago I asked similar question - Android 3D button src padding, but for text I cant use this trick :/ (or dont know how).
You will need to create a custom Button and override the methods for changing it's state in order to customize it's gravity based on the current state.
For example here is the code for a custom Button whose text will jump to the bottom when it is pressed:
public class VariableGravityButton extends Button {
public VariableGravityButton(Context context) {
super(context);
}
public VariableGravityButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public VariableGravityButton(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
}
#Override
public void setPressed(boolean pressed) {
if (pressed != isPressed()) {
setGravity(pressed ? Gravity.CENTER_HORIZONTAL |
Gravity.BOTTOM : Gravity.CENTER);
}
super.setPressed(pressed);
}
}

How to create custom shape button with selector in android?

MOCK UP
Requirement
I want to put custom button with selector.
Mock up is given above.
If anyone knows solution then share it.
Thank you.
basically you will need to create some new XML files and apply them to your Button element. As i can see from the mockup you will need a stroke and the background color with some shading effect applied, you can research more into the shading thing but the background color and the stroke is pretty straight forward.
Here is an example, done_rounded_btn.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true"
android:state_enabled="true"
android:drawable="#drawable/zzzzzzzzz_btn_orange" />
<item
android:state_focused="true"
android:state_enabled="true"
android:drawable="#drawable/zzzzzzzzz_btn_orange" />
<item
android:state_focused="false"
android:state_enabled="false"
android:drawable="#drawable/zzzzzzzzz_btn_inactiv" />
<item android:drawable="#drawable/zzzzzzzzz_btn_black"/>
</selector>
for the selection part and then you create the custom drawables corresponding to the mockup.
An example, zzzzzzzzzz_btn_orange:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<solid
android:color="#color/done_color">
</solid>
<corners
android:bottomLeftRadius="3dp"
android:bottomRightRadius="3dp"
android:topLeftRadius="3dp"
android:topRightRadius="3dp" />
</shape>
And then add it to your button as background, main.xml:
<Button
android:id="#+id/registers_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="10dp"
android:background="#drawable/done_rounded_btn"
android:text="#string/done_txt"
android:textColor="#color/white"
android:textSize="15sp" />
Hope this helps!
You can use this instead of standard Button and set selector as background in xml:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.Button;
/**
* Custom Shape Button which ignores touches on transparent background.
*/
public class ButtonWithUntouchableTransparentBg extends Button {
public ButtonWithUntouchableTransparentBg(Context context) {
this(context, null);
}
public ButtonWithUntouchableTransparentBg(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ButtonWithUntouchableTransparentBg(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setDrawingCacheEnabled(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
// ignores touches on transparent background
if (isPixelTransparent(x, y))
return true;
else
return super.onTouchEvent(event);
}
/**
* #return true if pixel from (x,y) is transparent
*/
private boolean isPixelTransparent(int x, int y) {
Bitmap bmp = Bitmap.createBitmap(getDrawingCache());
int color = Color.TRANSPARENT;
try {
color = bmp.getPixel(x, y);
} catch (IllegalArgumentException e) {
// x or y exceed the bitmap's bounds.
// Reverts the View's internal state from a previously set "pressed" state.
setPressed(false);
}
// Ignores touches on transparent background.
if (color == Color.TRANSPARENT)
return true;
else
return false;
}
}
You can also create a shape that is using a selector inside. If your shape is just changing its color in different states, this is a lot cleaner.
color/color_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#color/blue_dark" android:state_pressed="true" />
<item android:color="#color/blue_light" />
</selector>
drawable/shape.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/color_selector" />
<corners android:bottomLeftRadius="6dip" android:bottomRightRadius="6dp" />
<padding android:bottom="0dip" android:left="0dip" android:right="0dip" android:top="0dip" />
</shape>
Button with rounded corners with two states (enabled/disabled):
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="true">
<shape android:shape="rectangle">
<corners android:radius="28dp" />
<solid android:color="#color/white" />
<stroke android:width="1dp" android:color="#color/orange" />
</shape>
</item>
<item android:state_enabled="false">
<shape android:shape="rectangle">
<corners android:radius="28dp" />
<solid android:color="#color/grey_card_background" />
<stroke android:width="1dp" android:color="#color/grey" />
</shape>
</item>
</selector>
inside your item put the shape in the selector XML
EX FROM MY CODE :
<!-- if pressed -->
<item android:state_pressed="true"><shape android:padding="10dp" android:shape="rectangle">
<solid android:color="#color/blue" />
<corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp" android:topLeftRadius="10dp" android:topRightRadius="10dp" />
</shape></item>
<!-- if not pressed -->
<item><shape android:padding="10dp" android:shape="rectangle">
<solid android:color="#color/Purbble" />
<corners android:bottomLeftRadius="10dp" android:bottomRightRadius="10dp" android:topLeftRadius="10dp" android:topRightRadius="10dp" />
</shape></item>

Categories

Resources