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:
Related
I am trying to add a drawable background to a CustomTextView on android. I tried using style attribute in styles.xml but I was unable to apply it.
Here is my implementation so far.
CustomTextView.java
public class CustomTextView extends android.support.v7.widget.AppCompatTextView {
public CustomTextView(Context context) {
super(context);
Typeface face = Typeface.createFromAsset(context.getAssets(), "font/Montserrat-Regular.ttf");
context.getDrawable(R.drawable.tv_bottom_line_only);
this.setTypeface(face);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
context.getDrawable(R.drawable.tv_bottom_line_only);
Typeface face = Typeface.createFromAsset(context.getAssets(), "font/Montserrat-Regular.ttf");
this.setTypeface(face);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
Typeface face = Typeface.createFromAsset(context.getAssets(), "font/Montserrat-Regular.ttf");
context.getDrawable(R.drawable.tv_bottom_line_only);
this.setTypeface(face);
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
}
My drawable file:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:bottom="1dp"
android:left="-2dp"
android:right="-2dp"
android:top="-2dp">
<shape android:shape="rectangle">
<stroke
android:width="0.5dp"
android:color="#android:color/black" />
</shape>
</item>
Here, is my implementation in layout xml.
...
<com.project.utils.CustomTextView
android:id="#+id/profile_et_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionNext"
android:inputType="text"
android:padding="#dimen/_4sdp"
android:textColor="#color/black"
android:textSize="#dimen/_8sdp" />
Here is the snapshot of the issue. I want to remove the border appearing in top.
Thank you
To set the drawable as your background you should use :
setBackground(context.getDrawable(R.drawable.tv_bottom_line_only));
Now to have only a line at the bottom, you should remove the rectangle shape from your drawable.
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
Layout xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:gravity="center">
<org.mayday.myapplication.CustomTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</LinearLayout>
tv_bottom_line_only xml:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:top="-8dp" android:left="-8dp" android:right="-8dp">
<shape>
<stroke android:width="0.5dp" android:color="#android:color/black" />
</shape>
</item>
</layer-list>
Result:
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);
}
I tried to draw a custom linear layout, But the problem I faced is I am not getting the round corner for the linear layout
public class RoundLinearLayout extends LinearLayout {
private float radius;
private Path path = new Path();
private RectF rect = new RectF();
public RoundLinearLayout(Context context)
{
super(context);
radius = 20;
// setWillNotDraw(false);
}
public RoundLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// init(context);
}
public RoundLinearLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// init(context);
}
#Override
protected void onDraw(Canvas canvas) {
path.reset();
rect.set(0, 0, canvas.getWidth(), canvas.getHeight());
path.addRoundRect(rect, radius, radius, Path.Direction.CCW);
// Add 1px border RED here ?
path.close();
canvas.clipPath(path);
}
}
I really donno what went wrong.. Some please help me to sort this out.
I will suggest you to use simple CardView
use compile dependency
compile 'com.android.support:cardview-v7:21.0.+'
Example
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
.....
your other child layout goes here
</LinearLayout>
</android.support.v7.widget.CardView>
Use below xml in Drawables.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#FFFFFF" />
<stroke
android:width="2dp"
android:color="#000" />
<padding
android:bottom="1dp"
android:left="1dp"
android:right="1dp"
android:top="1dp" />
<corners
android:bottomLeftRadius="8dp"
android:bottomRightRadius="8dp"
android:radius="8dp"
android:topLeftRadius="8dp"
android:topRightRadius="8dp" />
</shape>
and set it as a Background of your LinearLayout.
You can choose your color and set background to your linear layout.
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="4dp" />
<solid android:color="#80000000" />
</shape>
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
}
}
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.