Android: set Background to custom view - android

I have created a customView in Android library and extended from AppCompatEditText. In init method I want to set background from my drawable resource.I write this code :
public class GrootAnimatedEditText extends AppCompatEditText {
public GrootAnimatedEditText(Context context) {
super(context);
init(context);
}
public GrootAnimatedEditText(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public GrootAnimatedEditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
setBackground(R.drawable.roundbg);
}
}
When i put a dot (.) roundbg and any drawable do not suggest to me.I also use :
setBackground(context.getResources().getDrawable(R.drawable.roundbg));
//or
setBackground(ContextCompat.getDrawable(context,R.drawable.roundbg));
again do not work! How can I set drawable to my custom TextView background?
**************** Edit ******************
roundbg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="5dp" />
<stroke
android:width="1dp"
android:color="#44433A" />
<solid android:color="#FFF" />
</shape>

Try to use setBackgroundResource() or setBackgroundDrawable() instead of setBackground().
More info here

Related

Style in custom view not affected on super constructor call

I'm trying to create custom view and set its style programatically. I created custom view based on AppCompatButton:
public class RangeSelectorButton extends androidx.appcompat.widget.AppCompatButton {
public int onClickKey = -1;
public RangeSelectorButton(Context context) {
this(context, null);
}
public RangeSelectorButton(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public RangeSelectorButton(Context context, AttributeSet attrs) {
this(context, attrs, R.style.RangeSelectorButton);
}
}
and now I get stuck in strange behaviour:
<ru.SomeDomain.CustomViews.RangeSelector
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true" android:focusable="true">
<!-- In this case all works fine -->
<ru.SomeDomain.RangeSelectorButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="10dp"
android:minWidth="40dp"
style="#style/RangeSelectorButton"
/>
<!-- Style not applies -->
<ru.SomeDomain.CustomViews.RangeSelectorButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="10dp"
android:minWidth="40dp"
/>
</ru.SomeDomain.CustomViews.RangeSelector>
What I should to do if I don't want use style attribute in xml every time when I create my custom view?
If it is necessary my style.xml contains:
<style name="RangeSelectorButton" parent="#android:style/Widget.Button">
<item name="android:background">#drawable/range_toggle_button_selector</item>
</style>
range_toggle_button_selector.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/range_unselected" android:state_pressed="false" />
<item android:drawable="#drawable/range_selected" android:state_pressed="true" />
</selector>
The problem here is that you're passing a style in the place of the defStyleAttr parameter, which expects an attribute, not a style. There's two solutions here:
Use an attribute. In attrs.xml declare:
<attr name="rangeSelectorButtonStyle" format="reference"/>
and in your app theme:
<item name="rangeSelectorButtonStyle">#style/RangeSelectorButton</style>
and change your constructor to:
public RangeSelectorButton(Context context, AttributeSet attrs) {
this(context, attrs, R.attr.rangeSelectorButtonStyle);
}
If you're making a library for example, this is the best way of doing it since it allows users to customize your widget style.
If you don't want to use an attribute, you can call the fourth View constructor, which has a parameter that takes a default style and not an attribute:
View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
Add this constructor to your view and in the second constructor, call the fourth like this:
public RangeSelectorButton(Context context, AttributeSet attrs) {
this(context, attrs, 0, R.style.RangeSelectorButton);
}
Note that the fourth constructor requires API 21.

Custom button with text and image

I'm looking for do a button like this preview :
I tried to do this with a button but my problem is that to put the border and the image I use android: background and I can not put the image and the border at the same time :/
Another problem for which I did not know how is a border to the text (which is simply the text of the button).
I wonder if I'm going in the wrong direction. I saw that there were button images but I'm not sure it suits me. Would there be a way to put a layout to a button?
<Button
android:id="#+id/mainButton1"
style="#style/Widget.AppCompat.Button.ButtonBar.AlertDialog"
android:layout_width="150"
android:layout_height="150"
android:background="#drawable/ic_add_circle_green_500_48dp"
android:drawable="#drawable/mainButton" <-- or android:drawable="#drawable/image" how for put the both ? -->
android:text="Text"
/>
mainButton.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<gradient android:startColor="#FFFFFF"
android:endColor="#00FF00"
android:angle="270" />
<corners android:radius="3dp" />
<stroke android:width="5px" android:color="#000000" />
</shape>
i have found many answers on Stackoverflow but the link to tutos was dead ...
You can create your custom View with desired background and ImageView,TextView inside. Then set ClickListener to it.
If you want background behind TextView you can use SpannableString or just create XML drawable and set it as TextView background.
Here what i've done:
Button class:
public class CustomButton extends LinearLayout {
public CustomButton(Context context) {
super(context);
inflateLayout(context);
}
public CustomButton(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
inflateLayout(context);
}
public CustomButton(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
inflateLayout(context);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomButton(Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
inflateLayout(context);
}
private void inflateLayout(Context context) {
inflate(context, R.layout.custom_button, this);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
TextView textView = findViewById(R.id.textView);
makeSpannable(textView);
}
private void makeSpannable(TextView textView) {
Spannable spannable = new SpannableString(textView.getText());
spannable.setSpan(new BackgroundColorSpan(0xFFFF0021), 0, textView.getText().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannable);
invalidate();
}
}
layout for CustomButton:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_gravity="center_horizontal"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:orientation="vertical"
android:background="#drawable/background"
android:padding="16dp">
<ImageView
android:id="#+id/imageView"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:src="#mipmap/ic_launcher" />
<TextView
android:id="#+id/textView"
android:gravity="center_horizontal"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_width="match_parent"
android:text="CLICK ME!"
android:textSize="16dp" />
</LinearLayout>
background for button:
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFF"/>
<stroke android:width="3dp" android:color="#00FFFF" />
<corners android:radius="10dp"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>
What I've got:

How to fix background red color TextInputLayout when isEmpty in Android

I want setError when TextInputLayout isEmpty, I write this code but when show error message, set red background for TextInputLayout!
I do not want set background! I want just show the error message.
My code:
if (TextUtils.isEmpty(userName)) {
register_UserName_layout.setError("Insert Username");
}
XML code :
<android.support.design.widget.TextInputLayout
android:id="#+id/register_userUsernameTextLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/register_headerLayout"
android:layout_margin="10dp"
android:textColorHint="#c5c5c5">
<EditText
android:id="#+id/register_userUserNameText"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#drawable/selector_bg_edit"
android:hint="نام کاربری"
android:paddingBottom="2dp"
android:textColor="#color/colorAccent"
android:textCursorDrawable="#drawable/bg_input_cursor"
android:textSize="16sp" />
</android.support.design.widget.TextInputLayout>
How can I fix this? Thanks all <3
I have found a workaround to this problem. You just need to create a custom EditText and override the getBackground() method of it to return a new drawable. That way TextInputLayout won't be able to set color filter on the EditText's background, since you do not return EditText's background, but some another drawable. See below:
#Override
public Drawable getBackground() {
return ContextCompat.getDrawable(getContext(), R.drawable.some_drawable);
}
and use the custom EditText inside TextInputLayout:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CustomEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/custom_edit_text_bg" />
</android.support.design.widget.TextInputLayout>
in my case I added line
<solid android:color="#color/transparent"/>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke android:color="#color/lightGray" android:width="1dp"/>
<solid android:color="#color/transparent"/>
<padding android:top="7dp" android:bottom="7dp" android:left="7dp" android:right="7dp"/>
<corners android:radius="2dp"/>
</shape>
this results in red border only not entire background
You can subclass TextInputLayout and use that:
package com.mypackage;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.support.design.widget.TextInputLayout;
import android.util.AttributeSet;
public class CustomTextInputLayout extends TextInputLayout {
public CustomTextInputLayout(Context context) {
super(context);
}
public CustomTextInputLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void drawableStateChanged() {
super.drawableStateChanged();
clearEditTextColorfilter();
}
#Override
public void setError(#Nullable CharSequence error) {
super.setError(error);
clearEditTextColorfilter();
}
private void clearEditTextColorfilter() {
EditText editText = getEditText();
if (editText != null) {
Drawable background = editText.getBackground();
if (background != null) {
background.clearColorFilter();
}
}
}
}
in your layout:
<com.mypackage.CustomTextInputLayout
android:id="#+id/register_userUsernameTextLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/register_headerLayout"
android:layout_margin="10dp"
android:textColorHint="#c5c5c5">
<EditText
android:id="#+id/register_userUserNameText"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#drawable/selector_bg_edit"
android:hint="نام کاربری"
android:paddingBottom="2dp"
android:textColor="#color/colorAccent"
android:textCursorDrawable="#drawable/bg_input_cursor"
android:textSize="16sp" />
</android.support.design.widget.TextInputLayout>
Bottom line with this issue is check if your EditText has a background color set. If so, remove it and put a background color on your text Input Layout widget instead. This will fix the issue of the big red box. At least it did for me.
Subclass EditText and apply the follow methods:
Override getBackground and create a Drawable with input background
#Override
public Drawable getBackground() {
return ContextCompat.getDrawable(getContext(), R.drawable.input_background);
}
your Drawable input_brackground can be like:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#color/inputBackgroundColor">
</solid>
</shape>
And apply EditText subclassed setBackground after TextInputLayout set error like:
private void showTheError(String error){
textInputLayout.setError(error);
editTextSubclassed.setBackgroundColor(getResources().getColor(R.color.inputBackgroundColor));
}
Similar to Shahin Mursalov's answer, I call method init() in the costructor to store the background drawable when the view is created. Also I've overriden method setBackgroundResource() to store the background as well, and return it from getBackground():
public class CustomEditText extends EditText{
private Drawable backgroundDrawable;
public EditTextContext context) {
super(context);
this.context = context;
}
public EditTextContext context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
init(attrs);
}
public EditText(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.context = context;
init(attrs);
}
public void init(AttributeSet attrs){
TypedArray attributes = context.obtainStyledAttributes(attrs, new int[]{android.R.attr.background});
this.backgroundDrawable = attributes.getDrawable(0);
attributes.recycle();
}
#Override
public void setBackgroundResource(#DrawableRes int resId) {
this.backgroundDrawable = ContextCompat.getDrawable(context, resId);
super.setBackgroundResource(resId);
}
#Override
public Drawable getBackground() {
if (backgroundDrawable != null){
return backgroundDrawable;
} else {
return super.getBackground();
}
}
}
This way I can specify a different background in my layout and change it programatically.
first your EditText background selector_bg_edit should be like that
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="#drawable/code_view_item"
android:state_focused="true"/>
<item android:drawable="#drawable/sign_in_fields"
android:state_focused="false"/>
<item android:drawable="#drawable/sign_in_fields"
android:state_active="false"/>
</selector>
And the most important thing is to put in the drawable to be transparent color like this
code_view_item.xml
<stroke android:width="1dp" android:color="#15A859" />
<solid android:color="#00FFFFFF" />
<corners android:radius="12dp"/>
What worked for me is just putting this below lines in my custom edit text class :
override fun getBackground(): Drawable {
return this.context.getDrawable(R.drawable.myDrawableResource)
}
My solution:
yourEdit.background.clearColorFilter()
if (TextUtils.isEmpty(userName)) {
register_UserName_layout.setError("Insert Username");
txtInpit.setColorFilter(R.color.white);
}

Unable to set Background in Imagebutton

Here i have a ImageButton:
<com.defcomdevs.invento16.SquareImageView
android:id="#+id/picture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal|top"
android:background="#drawable/custom_button"
android:layout_margin="1dp"
android:scaleType="fitCenter" />
SquareImageView is a class that extends the Imagebutton to basically set the width and height automatically according to the Screen size.
custom_button.xml:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="false">
<shape android:shape="rectangle">
<stroke android:width="5dp" android:color="#885599"/>
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="rectangle">
<stroke android:width="8dp" android:color="#802196f3"/>
<gradient android:startColor="#802196f3" android:endColor="#802196f3"/>
</shape>
</item>
My Problem is that when i set the background as custom_button the image that i set programmatically overlaps the entire area of the button.not showing the background.Otherwise the image perfectly sets inside the button.
Some thing like this:
As you can see this is the case with background=custom_button.
this is the case otherwise.
Now i don't want any of these.
What i want is that the custom_button is set as the background of the ImageButton and the src as that image as shown.How to da that??Please help.Thanks.
SquareImageView.class:
package com.defcomdevs.invento16;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Button;
import android.widget.ImageButton;
public class SquareImageView extends ImageButton {
public SquareImageView(Context context) {
super(context);
}
public SquareImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()); //Snap to width
}
}

DrawerLayout Causing Slow Selector

I started implementing DrawerLayout in my application and I noticed that the selector for my button responds very slowly. When I change DrawerLayout to LinearLayout, the lag disappears. I'm not sure if this is caused by extra touch processing occurring in the DrawerLayout that causes this lag or something else. Is there anything I can do to reduce this lag?
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/my_button"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#drawable/button_background"
android:text="" />
</android.support.v4.widget.DrawerLayout>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape>
<solid android:color="#000080"/>
</shape>
</item>
<item>
<shape>
<solid android:color="#0000ff"/>
</shape>
</item>
</selector>
DrawerLayout doesn't override shouldDelayChildPressedState() like LinearLayout does so it creates a delay. Had to create a layout class like this:
public class MyDrawerLayout extends DrawerLayout {
public MyDrawerLayout (Context context) {
super(context);
}
public MyDrawerLayout (Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyDrawerLayout (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
public boolean shouldDelayChildPressedState() {
// prevents touch delay
return false;
}
}
The only side effect I notice is the swipe gesture will select the view before bringing the drawer out.

Categories

Resources