Changing TextView background color on click android - android

I'm trying to change the background of a textview when clicked.
For instance, if the textview is click it the background changes to yellow and remains yellow until it is click again. Then it returns to its default background.
Currently textview the background changes on pressed down, but returns to default on release.
I have search the internet for solutions and look at most of all the solution on stackoverflow, still no solution.
Drawable/selector.xml:
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/circle_on" android:state_enabled="true" android:state_pressed="true"/>
<item android:drawable="#drawable/circle_on" android:state_enabled="true" android:state_focused="true"/>
<item android:drawable="#drawable/circle_off"/>
</selector>
Drawable/circle_on:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<stroke
android:width="2dp"
android:color="#color/Gray" >
</stroke>
<solid android:color="#color/LightBlue" />
</shape>
Drawable/circle_off:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" >
<stroke
android:width="2dp"
android:color="#color/Gray" >
</stroke>
<solid android:color="#color/WhiteSmoke" />
</shape>
TextView:
<TextView
style="#style/RoundText"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#drawable/repeat_selector"
android:clickable="true"
android:text="Sun" >
</TextView>
Text Style:
<style name="RoundText">
<item name="android:textColor">#555555</item>
<item name="android:gravity">center_vertical|center_horizontal</item>
<item name="android:textSize">15sp</item>
<item name="android:textStyle">bold</item>
<item name="android:fontFamily">sans-serif-thin</item>
</style>
Can someone please tell me what I'm doing wrong
Thanks.
MY Solution:
public class PlanTextView extends TextView {
private boolean _stateChanged;
private boolean _selected;
public boolean is_stateChanged() {
return _stateChanged;
}
public void set_stateChanged(boolean _stateChanged) {
this._stateChanged = _stateChanged;
}
public boolean is_selected() {
return _selected;
}
public void set_selected(boolean _selected) {
this._selected = _selected;
}
public PlanTextView(Context context) {
super(context);
}
public PlanTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public PlanTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
}
<com.plan.views.PlanTextView
android:id="#+id/mon"
style="#style/RoundText"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="#drawable/circle_off"
android:clickable="true"
android:onClick="PlanOnClick"
android:text="mon" >
</com.plan.views.PlanTextView>
Activity
public void PlanOnClick(View v) {
PlanTextView view = (PlanTextView)v;
if (view.is_stateChanged()) {
view.setBackgroundResource(R.drawable.circle_off);
view.set_selected(false);
} else {
view.setBackgroundResource(R.drawable.circle_on);
view.set_selected(true);
}
view.set_stateChanged(!view.is_stateChanged());
}

Apart from the above answers,try this code snippet too.
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<gradient android:endColor="#AD1F2D" android:startColor="#AD1F2D" />
</shape>
</item>
<item android:state_focused="true">
<shape>
<gradient android:endColor="#ff4b46" android:startColor="#ff4b46" />
</shape>
</item>
<item>
<shape>
<gradient android:endColor="#ff4b46" android:startColor="#ff4b46" />
</shape>
</item>
</selector>
I hope this will useful for everyone.

If the textview is clicked the background changes to yellow and remains yellow until it is click again. Then it returns to its default background.
It's a matter of logic as you need to keep in your click listener the current click state.(blind coding):
textView.setOnClickClickListener(new View.OnClickListener() {
private boolean stateChanged;
public void onClick(View view) {
if(stateChanged) {
// reset background to default;
textView.setBackgroundDrawable(circleOffDrawable);
} else {
textView.setBackgroundDrawable(circleOnDrawable);
}
stateChanged = !stateChanged;
}
});
To improve the answer, you should keep stateChanged flag in the activity and retain its value across activity recreations - if the user rotates the activity. (Store the flag in onSaveInstanceState and restore in onCreate if its parameter is not null.)

use a onclicklistner() for your Textview
In your listener use
txt.setBackgroundColor(Color.RED);
For example
if(count==1)
{
txt.setBackgroundColor(Color.YELLOW);
count=0;
}
else
if(count==0)
{
txt.setBackgroundColor(Color.RED);
count==1;
}

In the onCreate() method,
LinearLayout(or Whatever layout you are using) ll = (LinearLayout)findViewById(R.id.mainlay);
and set the listener on textview:
TextView tv1 = (TextView)findViewById(R.id.maintext);
tv1.setOnClickListener(this);
And finally on click:
#Override
public void onClick(View v) {
ll.setBackgroundColor(whatever color);
or If you want to change the text background color,
tv1.setBackground(whatevercolor);
}
Hope this helps.

In case anyone needs it (Kotlin). This can toggle TextView's background and text color on click.
ToggleTextView.kt
class ToggleTextView : AppCompatTextView {
private var mfilterSelected = false
constructor(context: Context, attrs: AttributeSet?, defStyle: Int): super(context, attrs, defStyle) {}`
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {}
constructor(context: Context, checkableId: Int) : super(context) {}
constructor(context: Context) : super(context) {}
fun isFilterSelected(): Boolean {
return mfilterSelected
}
fun toggleFilterState() {
if (mfilterSelected) {
background = resources.getDrawable(R.drawable.toggle_1)
setTextColor(resources.getColor(R.color.gray))
mfilterSelected = false
} else {
background = resources.getDrawable(R.drawable.toggle_2)
setTextColor(resources.getColor(R.color.white))
mfilterSelected = true
}
}
}
--toggle_1.xml--
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<stroke android:width="1dp" android:color="#color/gray" />
<corners android:radius="10dp" />
<solid android:color="#color/white" />
</shape>
--toggle_2.xml--
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<corners android:radius="10dp" />
<solid android:color="#color/orange" />
</shape>
Click listener in your Activity/Fragment:
yourTextView?.setOnClickListener {
yourTextView.toggleFilterState()
}
Usage in our xml layout file:
<ToggleTextView
android:id="#+id/yourTextView"
android:background="#drawable/toggle_1"
android:clickable="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"/>

Related

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.

Custom AppCompatButton getting wrong colors on Android 5 (Api 21)

So I've implemented a custom button for our app, the implementation works perfect on Android 6 and up but I run into an issue on Android 5, where the background color doesn't get applied until I press the button once. Then it looks as it should.
Buttons not correct
Buttons correct
The implementation looks like this:
class MpButton #JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.style.ButtonStyle) : AppCompatButton(context, attrs, defStyleAttr) {
private val toScale = 0.9f
private val fromScale = 1f
init {
var style = 0
var allCaps = false
attrs?.let {
val a = context.obtainStyledAttributes(it, R.styleable.MpButton)
style = a.getInt(R.styleable.MpButton_MpButtonColor, 0)
allCaps = a.getBoolean(R.styleable.MpButton_MpButtonAllcaps, false)
a.recycle()
}
when (style) {
WHITE -> {
this.setBackgroundResource(R.drawable.mp_button_white)
this.setTextColor(ContextCompat.getColor(context, R.color.white))
}
RED -> {
this.setBackgroundResource(R.drawable.mp_button_red)
this.setTextColor(ContextCompat.getColor(context, R.color.white))
}
BLACK -> {
this.setBackgroundResource(R.drawable.mp_button_black)
this.setTextColor(ContextCompat.getColor(context, R.color.mp_black))
}
BLUE -> {
this.setBackgroundResource(R.drawable.mp_button_blue)
this.setTextColor(ContextCompat.getColor(context, R.color.white))
}
YELLOW -> {
this.setBackgroundResource(R.drawable.mp_button_yellow)
this.setTextColor(ContextCompat.getColor(context, R.color.white))
}
else -> {
this.setBackgroundResource(R.drawable.mp_button_green)
this.setTextColor(ContextCompat.getColor(context, R.color.white))
}
}
this.gravity = Gravity.CENTER
val padding = Utils.convertDpToPixel(context, 5)
this.setPadding(padding, padding, padding, padding)
this.isAllCaps = allCaps
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
when(event.action) {
MotionEvent.ACTION_DOWN -> {
this.animate().scaleX(toScale).scaleY(toScale).setDuration(100).start()
}
MotionEvent.ACTION_UP -> {
this.animate().scaleX(fromScale).scaleY(fromScale).setDuration(100).start()
}
}
return super.dispatchTouchEvent(event)
}
companion object {
const val WHITE = 1
const val RED = 2
const val BLACK = 3
const val BLUE = 4
const val YELLOW = 5
}
}
For info Ill also add the XML for one of the colors:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="#color/mp_black">
<item>
<selector
android:exitFadeDuration="#android:integer/config_mediumAnimTime"
android:enterFadeDuration="#android:integer/config_shortAnimTime">
<item android:state_enabled="true" android:state_pressed="false">
<shape android:shape="rectangle">
<corners android:radius="30dp"/>
<solid android:color="#color/jungle_green" />
</shape>
</item>
<item android:state_enabled="true" android:state_pressed="true">
<shape android:shape="rectangle">
<corners android:radius="30dp"/>
<solid android:color="#color/forest" />
</shape>
</item>
<item android:state_enabled="false">
<shape android:shape="rectangle">
<corners android:radius="30dp"/>
<solid android:color="#color/mp_gray_5" />
</shape>
</item>
</selector>
</item>
</ripple>
As a last ill copy the part of the XML of the view aswell to give as much info as possible:
<se.motesplatsen.app.ui.controls.MpButton
android:id="#+id/btnStartLogin"
android:layout_width="220dp"
android:layout_height="44dp"
android:text="#string/DEFAULT_LOGIN"
android:layout_marginBottom="10dp"
android:layout_marginTop="20dp"
app:MpButtonAllcaps="true"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#id/btnStartBecomeMember"/>
<se.motesplatsen.app.ui.controls.MpButton
android:id="#+id/btnStartBecomeMember"
android:layout_width="220dp"
android:layout_height="44dp"
android:layout_marginTop="25dp"
android:text="#string/BECOME_MEMBER_BUTTON"
app:MpButtonColor="1"
app:MpButtonAllcaps="true"
app:layout_constraintVertical_chainStyle="packed"
app:layout_constraintTop_toBottomOf="#id/tvStartDesc"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="#id/btnStartLogin"/>
UPDATE & SOLUTION!:
Finally got this to work! Solution was to remove
android:exitFadeDuration="#android:integer/config_mediumAnimTime"
android:enterFadeDuration="#android:integer/config_shortAnimTime"
Im guessing it somehow interferes with the ripple animation on certain Android versions. So for anyone else that have my issue, check so you dont have Ripple togheter with fadeduration in the selector :)!
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape >
<solid android:color="#android:color/white"/>
<size android:height="1dp"/>
</shape>
</item>
<item android:bottom="2dip" android:top="2dip" android:left="2dip" android:right="2dip">
<shape>
<solid android:color="#android:color/Transparent"/>
</shape>
</item>
this is exactly look like your correct button
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<corners
android:radius="5dp"
/>
<solid
android:color="#color/Transparent"
/>
just use this as background you are using on pressed state in your file

Android Adding Text inside switch toggle. Newer API approach

I want to add text inside switches and expect toggle to completely cover the texts
I was able to achieve this in API 16 with below option
<Switch
android:textOff="off"
android:showText="true"
android:textOn="on"/>
However same switch looks odd in the higher version(i'm testing with API 27) where switch toggle is a round icon behind the text.
Is there a way i can fit the text inside the switch toggle using native library/methods.
I found this code in GitHub. After some addition and modification, I get what I need. This toggle button has YES NO text on it and works like switch button. You can give it a go.
public class ToggleButton extends RelativeLayout implements View.OnClickListener {
FrameLayout layout;
TextView toggleCircle;
View background_oval_off, background_oval_on;
int dimen;
private Boolean _crossfadeRunning = false;
private ObjectAnimator _oaLeft, _oaRight;
public ToggleButton(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.toggle_button, this, true);
background_oval_off = findViewById(R.id.background_oval_off);
background_oval_on = findViewById(R.id.background_oval_on);
toggleCircle = findViewById(R.id.toggleCircle);
layout = (FrameLayout) findViewById(R.id.layout);
layout.setOnClickListener(this);
//get a pixel size for a particular dimension - will differ by device according to screen density
dimen = getResources().getDimensionPixelSize(R.dimen.toggle_width);
_oaLeft = ObjectAnimator.ofFloat(toggleCircle, "x", dimen / 2, 0).setDuration(250);
_oaRight = ObjectAnimator.ofFloat(toggleCircle, "x", 0, dimen / 2).setDuration(250);
//setState();
}
public ToggleButton(Context context) {
this(context, null);
}
public void setState(String answer) {
Log.d("simul", "ans - " + answer);
if (answer.equals("1")) {
toggleCircle.setTextColor(ContextCompat.getColor(getContext(), R.color.green));
toggleCircle.setX(dimen / 2);
_crossfadeViews(background_oval_off, background_oval_on, 1);
toggleCircle.setText("Yes");
} else {
toggleCircle.setTextColor(ContextCompat.getColor(getContext(), R.color.red));
toggleCircle.setX(0);
_crossfadeViews(background_oval_on, background_oval_off, 1);
toggleCircle.setText("No");
}
}
private void _crossfadeViews(final View begin, View end, int duration) {
_crossfadeRunning = true;
end.setAlpha(0f);
end.setVisibility(View.VISIBLE);
end.animate().alpha(1f).setDuration(duration).setListener(null);
begin.animate().alpha(0f).setDuration(duration).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
begin.setVisibility(View.GONE);
_crossfadeRunning = false;
}
});
}
#Override
public void onClick(View view) {
if (_oaLeft.isRunning() || _oaRight.isRunning() || _crossfadeRunning) return;
if (toggleCircle.getText().equals("Yes")) {
_oaLeft.start();
_crossfadeViews(background_oval_on, background_oval_off, 110);
toggleCircle.setText("No");
toggleCircle.setTextColor(ContextCompat.getColor(getContext(), R.color.red));
mListener.toggleButtonClickListener("No");
} else {
_oaRight.start();
_crossfadeViews(background_oval_off, background_oval_on, 400);
toggleCircle.setText("Yes");
toggleCircle.setTextColor(ContextCompat.getColor(getContext(), R.color.green));
mListener.toggleButtonClickListener("Yes");
}
}
public ToggleButtonListener mListener = null;
public void setToggleButtonClickListener(ToggleButtonListener listener) {
mListener = listener;
}
public interface ToggleButtonListener {
public void toggleButtonClickListener(String content);
}
}
toogle_button_red_oval.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:right="#dimen/toggle_circle_diameter">
<shape android:shape="oval">
<solid android:color="#color/red"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
<item android:left="#dimen/toggle_circle_radius" android:right="#dimen/toggle_circle_radius">
<shape android:shape="rectangle">
<solid android:color="#color/red"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
<item android:left="#dimen/toggle_circle_diameter">
<shape android:shape="oval">
<solid android:color="#color/red"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
</layer-list>
toogle_button_green_oval.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:right="#dimen/toggle_circle_diameter">
<shape android:shape="oval">
<solid android:color="#color/green"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
<item android:left="#dimen/toggle_circle_radius" android:right="#dimen/toggle_circle_radius">
<shape android:shape="rectangle">
<solid android:color="#color/green"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
<item android:left="#dimen/toggle_circle_diameter">
<shape android:shape="oval">
<solid android:color="#color/green"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
</item>
</layer-list>
toogle_button_circle.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
<solid android:color="#color/white"/>
<size
android:height="#dimen/toggle_circle_diameter"
android:width="#dimen/toggle_circle_diameter" />
</shape>
toogle_button.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:id="#+id/layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<View
android:layout_width="#dimen/toggle_width"
android:layout_height="#dimen/toggle_height"
android:id="#+id/background_oval_off"
android:background="#drawable/toggle_button_black_oval" />
<View
android:layout_width="#dimen/toggle_width"
android:layout_height="#dimen/toggle_height"
android:id="#+id/background_oval_on"
android:background="#drawable/toggle_button_green_oval"
android:visibility="gone" />
<TextView
android:paddingTop="10dp"
android:paddingLeft="10dp"
android:layout_width="#dimen/toggle_circle_diameter"
android:layout_height="#dimen/toggle_circle_diameter"
android:layout_gravity="center_vertical"
android:id="#+id/toggleCircle"
android:textSize="#dimen/toggle_text_size"
android:text="No"
android:background="#drawable/toggle_button_circle"/>
</FrameLayout>
</merge>
XML layout code
<package.name.ToggleButton
android:id="#+id/toggleButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</cpackage.name.ToggleButton>
Java Code :
ToggleButton toggleButton = findViewById(R.id.toggleButton);
toggleButton.setToggleButtonClickListener(new ToggleButton.ToggleButtonListener() {
#Override
public void toggleButtonClickListener(String content) {
if (content.equals("Yes")) {
} else {
}
}
});
dimens.xml
<dimen name="toggle_width">100dp</dimen>
<dimen name="toggle_height">50dp</dimen>
<dimen name="toggle_circle_diameter">50dp</dimen>
<dimen name="toggle_circle_radius">25dp</dimen>
Sorry for this long long answer. I had to add all the code here. please let me know if anything missing here. :)

Text in android button is being cut

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.

ImageButton background change with custom drawable state

I have a custom ImageButton class mimicing the ToggleButton's checked state based on this tutorial How to add a custom button state .
Everything works fine, when I have a state list drawable as the android:src attribute, but the custom state doesn't work with the ImageButton's android:background attribute.
Here is my code:
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Checkable;
import android.widget.ImageButton;
public class CheckableImageButton extends ImageButton implements Checkable {
private static final int[] STATE_CHECKED = {R.attr.state_checked};
private boolean mChecked = false;
public CheckableImageButton(Context context) {
super(context);
}
public CheckableImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if(mChecked){
mergeDrawableStates(drawableState, STATE_CHECKED);
}
return drawableState;
}
#Override
public boolean isChecked() {
return mChecked;
}
#Override
public void setChecked(boolean checked) {
mChecked = checked;
refreshDrawableState();
}
#Override
public void toggle() {
setChecked(!mChecked);
}
}
And the relevant snippet from the layout XML:
<com.my.package.view.CheckableImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:background="#drawable/header_button_bg"
android:padding="5dp"
android:src="#drawable/menu_button"
tools:ignore="ContentDescription" />
And the state list 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/my.package" >
<item android:state_pressed="true">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#ff000000" />
<gradient android:angle="-90" android:endColor="#d2914e" android:startColor="#906434" />
<corners android:radius="5dp" />
</shape>
</item>
<item app:state_checked="true">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#ff000000" />
<gradient android:angle="-90" android:endColor="#d2914e" android:startColor="#906434" />
<corners android:radius="5dp" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#ff000000" />
<gradient android:angle="-90" android:endColor="#4f5b6c" android:startColor="#345b75" />
<corners android:radius="5dp" />
</shape>
</item>
</selector>
Another wonderful trait of eclipse probably..
When I tried to revert my code to the last working version by hand (the state list drawable in the android:src tag), it produced the same error. I reverted from the SVN repo, it worked. Then I made the exact same changes as before, character by character, no difference, and voilá, it works now!
So that's it, the code in the question is fully functional.

Categories

Resources