Custom declare-styleable not displaying text attribute - java

I have been working on a custom "Button" and it works just as I want it to so far. However, I am trying to add text to the button instead of a drawable (which is what I was doing before).
Currently I have used a declare-styleable in my attrs.xml file which looks like the following:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Custom attributes for the button -->
<declare-styleable name="StyledButton">
<attr name="cornerRadius" format="dimension" />
<attr name="borderWidth" format="dimension" />
<attr name="startColor" format="color" />
<attr name="centerColor" format="color" />
<attr name="endColor" format="color" />
</declare-styleable>
</resources>
Alongside this, I have the accompanying class StyledButton.java :
package com.example.test;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.graphics.Path;
import android.graphics.Paint;
import android.graphics.LinearGradient;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatImageButton;
public class StyledButton extends AppCompatImageButton {
private float cornerRadius = 0f;
private float borderWidth = 0f;
private int startColor = 0;
private int centerColor = 0;
private int endColor = 0;
private Path path = new Path();
private Paint borderPaint = new Paint();
{
borderPaint.setStyle(Paint.Style.FILL);
}
public StyledButton(Context context, #Nullable AttributeSet attrs) {
super(context, attrs, 0);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.StyledButton);
try {
cornerRadius = a.getDimension(R.styleable.StyledButton_cornerRadius, 10f);
borderWidth = a.getDimension(R.styleable.StyledButton_borderWidth, 10f);
startColor = a.getColor(R.styleable.StyledButton_startColor, getResources().getColor(R.color.colorPrimaryDark, context.getTheme()));
centerColor = a.getColor(R.styleable.StyledButton_centerColor, getResources().getColor(R.color.colorAccent, context.getTheme()));
endColor = a.getColor(R.styleable.StyledButton_endColor, Color.WHITE);
}
finally {
a.recycle();
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
borderPaint.setShader(new LinearGradient(0f, 0f, 0f, (float) getHeight(), new int[] {startColor, centerColor, endColor}, null, Shader.TileMode.CLAMP));
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
path.rewind();
path.addRoundRect(borderWidth, borderWidth, ((float) getWidth()) - borderWidth, ((float) getHeight()) - borderWidth, cornerRadius - borderWidth / 2, cornerRadius - borderWidth / 2, Path.Direction.CCW);
canvas.clipOutPath(path);
path.rewind();
path.addRoundRect(0f, 0f, ((float) getWidth()), ((float) getHeight()), cornerRadius, cornerRadius, Path.Direction.CCW);
canvas.drawPath(path, borderPaint);
}
}
I am trying to use these in a custom dialog to get user input with the following code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:elevation="5dp">
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="20dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#drawable/background_gradient"
android:padding="10dp">
<TextView
android:layout_width="300dp"
android:layout_height="wrap_content"
android:scaleType="center"
android:text="#string/app_name"
android:textAlignment="center"
android:fontFamily="#font/lato_bold"
android:textSize="36sp"
android:padding="10dp"
android:textColor="#android:color/white" />
<EditText
android:id="#+id/player_name_dialog_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="4dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="4dp"
android:hint="#string/player_name_hint"
android:textAlignment="center"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="40dp"
android:orientation="horizontal"
android:layout_gravity="center"
android:layout_marginTop="10dp">
<com.example.test.StyledButton
android:id="#+id/player_name_dialog_confirm_button"
android:layout_weight="1"
android:layout_height="match_parent"
android:layout_width="120dp"
android:scaleType="center"
android:layout_gravity="center"
app:startColor="#color/colorPrimaryDark"
app:centerColor="#color/colorPrimary"
app:endColor="#color/colorAccent"
app:borderWidth="2dp"
app:cornerRadius="20dp"
android:text="#string/cancel"
android:textColor="#android:color/white"
android:textSize="20sp"
android:fontFamily="#font/lato"
android:layout_marginHorizontal="10dp"
android:onClick="deletePlayerButtonClick"/>
<com.example.test.StyledButton
android:id="#+id/add_players_activity_delete_button"
android:layout_weight="1"
android:layout_height="match_parent"
android:layout_width="120dp"
android:scaleType="center"
android:layout_gravity="center"
app:startColor="#color/colorPrimaryDark"
app:centerColor="#color/colorPrimary"
app:endColor="#color/colorAccent"
app:borderWidth="2dp"
app:cornerRadius="20dp"
android:layout_marginHorizontal="10dp"
android:onClick="deletePlayerButtonClick"/>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
I have tried adding the android:text in the attrs.xml file but this doesn't show up and I don't understand why this may be.
Thanks in advance !

The text will not show as the custom view extends AppCompatImageButton. AppCompatImageButton only displays an image.
public class StyledButton extends AppCompatImageButton {
If you require a button that shows text consider having two custom views, one for image and the other for text.
StyledImageButton:
public class StyledImageButton extends AppCompatImageButton {
StyledButton
public class StyledButton extends AppCompatButton {
The rest of the code can remain the same.
NOTE: Android will not let you create duplicate attributes in attrs.xml. Create global attributes and reuse them. Like so:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="cornerRadius" format="dimension" />
<attr name="borderWidth" format="dimension" />
<attr name="startColor" format="color" />
<attr name="centerColor" format="color" />
<attr name="endColor" format="color" />
<declare-styleable name="StyledButton">
<attr name="cornerRadius" />
<attr name="borderWidth" />
<attr name="startColor" />
<attr name="centerColor" />
<attr name="endColor" />
</declare-styleable>
<declare-styleable name="StyledImageButton">
<attr name="cornerRadius" />
<attr name="borderWidth" />
<attr name="startColor" />
<attr name="centerColor" />
<attr name="endColor" />
</declare-styleable>
</resources>

Related

View.setBackgroundResource() is not setting the correct background resource

I am coding a "set pin" fragment for the second time and it's not working. Everything works great until I use switch blocks and View.OnTouchListener. I am trying to change the buttons background resource to a different drawable when pressed down and then back when finger is lifted.
My problem is that the background resource is not changing at all.
XML for layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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:background="#color/tertiary_dark"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="#style/Theme.Design.NoActionBar"
>
<View
android:id="#+id/divider3"
android:layout_width="364.059dp"
android:layout_height="2dp"
android:background="#color/secondary_accent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tableLayout" />
<TableLayout
android:id="#+id/tableLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="#+id/pin7"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:background="#drawable/button_1_background_idle"
android:text="7"
android:textColor="#color/primary_light"
android:textSize="22sp" />
<Button
android:id="#+id/pin8"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="8"
android:textColor="#color/primary_light"
android:textSize="22sp" />
<Button
android:id="#+id/pin9"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="9"
android:textColor="#color/primary_light"
android:textSize="22sp" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/pin4"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="4"
android:textColor="#color/primary_light"
android:textSize="22sp" />
<Button
android:id="#+id/pin5"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="5"
android:textColor="#color/primary_light"
android:textSize="22sp" />
<Button
android:id="#+id/pin6"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="6"
android:textColor="#color/primary_light"
android:textSize="22sp" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/pin1"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="1"
android:textColor="#color/primary_light"
android:textSize="22sp" />
<Button
android:id="#+id/pin2"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="2"
android:textColor="#color/primary_light"
android:textSize="22sp" />
<Button
android:id="#+id/pin3"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="3"
android:textColor="#color/primary_light"
android:textSize="22sp" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/pina"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="A"
android:textColor="#color/primary_light"
android:textSize="22sp" />
<Button
android:id="#+id/pin0"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="0"
android:textColor="#color/primary_light"
android:textSize="22sp" />
<Button
android:id="#+id/pinb"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="B"
android:textColor="#color/primary_light"
android:textSize="22sp" />
</TableRow>
</TableLayout>
<View
android:id="#+id/view"
android:layout_width="364.059dp"
android:layout_height="75dp"
android:layout_marginTop="104dp"
android:background="#color/primary_dark"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.489"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/slatebook"
android:text="1234567890ab"
android:textColor="#color/primary_light"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="#+id/view"
app:layout_constraintEnd_toEndOf="#+id/view"
app:layout_constraintStart_toStartOf="#+id/view"
app:layout_constraintTop_toTopOf="#+id/view" />
<View
android:id="#+id/divider"
android:layout_width="364.059dp"
android:layout_height="2dp"
android:background="#color/secondary_accent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/view" />
</androidx.constraintlayout.widget.ConstraintLayout>
Code for java class:
package com.example.portal;
import android.annotation.SuppressLint;
import android.graphics.Color;
import android.os.Bundle;
import android.system.StructUtsname;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import java.util.ArrayList;
public class FirstFragment extends Fragment {
#Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.login_layout, container, false);
}
#SuppressLint("ClickableViewAccessibility")
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
load();
}
#SuppressLint("ClickableViewAccessibility")
private void load() {
ArrayList<Button> pinbtns = new ArrayList<>();
ArrayList<Character> vals = new ArrayList<>();
pinbtns.add((Button) getActivity().findViewById(R.id.pin0));
pinbtns.add((Button) getActivity().findViewById(R.id.pin1));
pinbtns.add((Button) getActivity().findViewById(R.id.pin2));
pinbtns.add((Button) getActivity().findViewById(R.id.pin3));
pinbtns.add((Button) getActivity().findViewById(R.id.pin4));
pinbtns.add((Button) getActivity().findViewById(R.id.pin5));
pinbtns.add((Button) getActivity().findViewById(R.id.pin6));
pinbtns.add((Button) getActivity().findViewById(R.id.pin7));
pinbtns.add((Button) getActivity().findViewById(R.id.pin8));
pinbtns.add((Button) getActivity().findViewById(R.id.pin9));
pinbtns.add((Button) getActivity().findViewById(R.id.pina));
pinbtns.add((Button) getActivity().findViewById(R.id.pinb));
vals.add('0');
vals.add('1');
vals.add('2');
vals.add('3');
vals.add('4');
vals.add('5');
vals.add('6');
vals.add('7');
vals.add('8');
vals.add('9');
vals.add('a');
vals.add('b');
for (int r = 0; r < pinbtns.size(); r++) {
Button btn = pinbtns.get(r);
btn.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
btn.setBackgroundResource(R.drawable.button_1_background_pressed);
System.out.println("down");
return true;
case MotionEvent.ACTION_UP:
Thread t = new Thread(() -> {
try {
Thread.sleep(50);
} catch (Exception ig) {
ig.printStackTrace();
}
getActivity().runOnUiThread(() -> {
btn.setBackgroundResource(R.drawable.button_1_background_idle);
});
});
t.start();
System.out.println("up");
return true;
}
return false;
}
});
}
}
}
Code for drawables:
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#color/primary_dark"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<solid
android:color="#color/primary_accent"/>
</shape>
And the color resourcefile for good measure.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="primary_light">#dcdcdc </color>
<color name="primary_dark">#1c1d1f</color>
<color name="secondary_dark">#151515</color>
<color name="tertiary_dark">#323335</color>
<color name="secondary_light">#9ea09f</color>
<color name="primary_accent">#c41442</color>
<color name="secondary_accent">#711930</color>
</resources>
Just to clarify one more time. When I press a button (for example pin7) the system prints "down" to the console but the background does not change one bit. When I release I get "up" in the console. So it works as intended except for the background.
I have tried
changing the setBacgroundResource to setBackroundColor and same outcome.
I have spent 2 hours and am trying to find out why the setBackgroundResource() is not working. I added some modification on the shape and I noticed that the change only made on the dimensions except the Color. So I created a style to eliminate the Tinte I put the backgroundTint on #null and everything works correctly.
here is the style I added
<style name="NotTintedButton" parent="Widget.AppCompat.Button.Colored">
<item name="backgroundTint">#null</item>
</style>
And all you have to do is apply this style on each buttons. for example :
<Button
style="#style/NotTintedButton"
android:id="#+id/pin8"
android:layout_width="#dimen/button_1_width"
android:layout_height="#dimen/button_1_height"
android:layout_margin="#dimen/button_1_margin"
android:background="#color/primary_dark"
android:fontFamily="#font/slatebook"
android:padding="0dp"
android:text="8"
android:textColor="#color/primary_light"
android:textSize="22sp" />

Creating a fixed size circle view in android studio

So I have a bit of a frustrating one for me. What I would like to achieve is essentially a button that has two textviews in the center of it. One with a name and one with a number value to it... Like a counter...
I would like it to look like this:
There is a thin white border around it (which given it's colour isn't exactly visible... sorry).
What I'd like to do is have the value increment and decrement depending on how the button is pressed.
Now I have the following so far:
attrs.xml
<resources>
<declare-styleable name="ButtonCounter">
<attr name="backgroundColor" format="color"/>
<attr name="borderColor" format="color"/>
<attr name="borderSize" format="integer"/>
<attr name="labelNameColor" format="color"/>
<attr name="labelValueColor" format="color"/>
<attr name="labelName" format="string"></attr>
<attr name="labelValue" format="string"></attr>
</declare-styleable>
ButtonCounter.java
public class ButtonCounter extends View {
private int backgroundColor,
borderColor,
borderSize,
labelNameColor,
labelValueColor;
private String labelName,
labelValue;
private Paint paintCircle,
paintStroke;
public ButtonCounter(Context context, AttributeSet attrs) {
super(context);
paintCircle = new Paint();
paintStroke = new Paint();
TypedArray a = context.getTheme().obtainStyledAttributes(
attrs,
R.styleable.ButtonCounter
,
0,
0
);
try {
backgroundColor = a.getInteger(R.styleable.ButtonCounter_backgroundColor, 0);
borderColor = a.getInteger(R.styleable.ButtonCounter_borderColor, 0);
borderSize = a.getInteger(R.styleable.ButtonCounter_borderSize, 0);
labelNameColor = a.getInteger(R.styleable.ButtonCounter_labelNameColor,0);
labelValueColor = a.getInteger(R.styleable.ButtonCounter_labelValueColor, 0 );
labelName = a.getString(R.styleable.ButtonCounter_labelName);
labelValue = a.getString(R.styleable.ButtonCounter_labelValue);
} finally {
a.recycle();
}
}
#Override
protected void onDraw(Canvas canvas) {
paintCircle.setColor(backgroundColor);
paintCircle.setAntiAlias(true);
paintStroke.setColor(borderColor);
paintStroke.setAntiAlias(true);
int width = this.getMeasuredWidth();
int height = this.getMeasuredHeight();
int diameter = ((height > width) ? height : width);
int radius = diameter / 2;
canvas.drawCircle(diameter / 2, diameter / 2, radius - borderSize, paintCircle);
canvas.drawCircle(diameter / 2, diameter / 2, radius, paintStroke);
}
}
This doesn't do what I want it to already as it becomes way too big.
Any ideas on how I could start attempting this?
Thanks!
Hi If you want to achieve the same without using Java Class then see the below solution:
Create a drawable with any name lets circle_bg_xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#color/black" />
</shape>
Now in your layout use put two TextViews(or any view) inside LinearLayout and set that drawable as Layout background.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="100dp"
android:layout_height="100dp"
android:gravity="center"
android:background="#drawable/circle_bg">
<TextView
android:layout_width="wrap_content"
android:textColor="#color/white"
android:textSize="15sp"
android:layout_height="wrap_content"
android:text="Global"/>
<TextView
android:layout_width="wrap_content"
android:textColor="#color/white"
android:textSize="22sp"
android:layout_height="wrap_content"
android:text="0"/>
</LinearLayout>
Hope it will help you.
Thanks

XML TypedArray only Displaying first image

This is my first attempt with TypedArrays and I believe I've written my code correctly, but for some reason I am only able to see the first image in my array. I have a loop that should be displaying the images repeatedly.
My activity.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="wrap_content" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".HomeScreen"
android:background="#android:drawable/screen_background_dark_transparent"
android:clickable="true"
android:id="#+id/homescreen_view">
<Button
android:layout_width="100.0dp"
android:layout_height="25.0dp"
android:text="Help"
android:id="#+id/instructionsButton"
android:layout_alignParentTop="false"
android:layout_alignParentStart="true"
android:textColor="#05ffda"
android:background="#android:color/holo_purple"
android:longClickable="true" />
<ImageButton
android:layout_width="50dp"
android:layout_height="50dp"
android:scaleType="centerCrop"
android:id="#+id/soundEnable_button"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:longClickable="true"
android:nestedScrollingEnabled="true"/>
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="100dp"
android:layout_height="25dp"
android:text="Highscores"
android:id="#+id/highscores_button"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:background="#android:color/holo_purple"
android:textColor="#05ffda" />
<Button
style="?android:attr/buttonStyleSmall"
android:layout_width="100dp"
android:layout_height="30dp"
android:text="Play Game"
android:id="#+id/startGame_button"
android:background="#android:color/holo_purple"
android:textColor="#05ffda"
android:layout_marginTop="175dp"
android:singleLine="true"
android:layout_alignParentTop="false"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Arrays.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="musicIcon">
<item>#drawable/musicoff</item>
<item>#drawable/musicon1</item>
<item>#drawable/musicon2</item>
<item>#drawable/musicon3</item>
<item>#drawable/musicon4</item>
<item>#drawable/musicon5</item>
</array>
</resources>
and my activity.java
import android.content.res.TypedArray;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;
public class HomeScreen extends AppCompatActivity {
ImageButton musicEnable_ImageButton;
Handler musicIcon_animate = new Handler();
int ArrayPos = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home_screen);
final TypedArray musicIcons = getResources().obtainTypedArray(R.array.musicIcon);
for(ArrayPos =0;ArrayPos<5;ArrayPos++) {
musicIcons.getResourceId(ArrayPos, -1);
}
ArrayPos = 0;
musicEnable_ImageButton = (ImageButton) findViewById(R.id.soundEnable_button);
musicEnable_ImageButton.setImageResource(musicIcons.getResourceId(ArrayPos,-1));
musicIcons.recycle();
musicEnable_ImageButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
ArrayPos = 1;
Runnable runnable = new Runnable() {
#Override
public void run() {
musicEnable_ImageButton.setImageResource(musicIcons.getResourceId(ArrayPos,-1));
musicIcons.recycle();
if(ArrayPos < 5) {
ArrayPos++;
}
else{
ArrayPos = 1;
}
Log.d("test", "timer fired");
musicIcon_animate.postDelayed(this, 1);
}
};
musicIcon_animate.postDelayed(runnable, 1);
}
});
}
You can only see the first image because you are recycling your musicIcons TypedArray after you set the first image. TypedArray.recycle() removes all of the references to the resources in the array, making it an empty array. You want to do this, but only after you've gotten what you need from the array.
In your case, since you are using the resources over a period of time, I would suggest doing something like this:
List<Integer> musicIcons = new ArrayList<>();
final TypedArray typedArray = getResources().obtainTypedArray(R.array.musicIcon);
for(int i = 0; i < typedArray.length(); i++) {
musicIcons.add(typedArray.getResourceId(i, -1);
}
typedArray.recycle();
Then set the ImageView resource like this:
musicEnable_ImageButton.setBackgroundResource(musicIcons.get(ArrayPos));
But, I also noticed that it looks like you are just trying to animate the icon, in which case, you should look into using an AnimationDrawable. In this way you can just create a drawable XML file:
<animation-list android:id="#+id/selected" android:oneshot="true">
<item android:drawable="#drawable/musicoff" android:duration="50" />
<item android:drawable="#drawable/musicon1" android:duration="50" />
<item android:drawable="#drawable/musicon2" android:duration="50" />
<item android:drawable="#drawable/musicon3" android:duration="50" />
<item android:drawable="#drawable/musicon4" android:duration="50" />
<item android:drawable="#drawable/musicon5" android:duration="50" />
</animation-list>
Then set the image resource to this animation-list, and animate it:
musicEnable_ImageButton.setImageResource(R.id.sound_button);
AnimationDrawable frameAnimation = (AnimationDrawable) musicEnable_ImageButton.getBackground();
frameAnimation.start();
On API 21+ it is even easier, you can create an AnimatedStateListDrawable to wrap your animation-list (or lists). Then set android:button attribute of a RadioButton to the AnimatedStateListDrawable and watch it animate as you call setChecked().

Android: EditText in CustomView not behaving as expected when touched

I have a CustomView which contains a LinearLayout that holds an EditText & another custom view element. However, when I run my app and touch the EditText it does not behave as expected (doesn't appear to receive focus & the soft keyboard doesn't open). I've tried setting duplicateParentState="true" on both the EditText & the LinearLayout. I also attached an onTouchEventListener to the EditText that calls a simple toast & the toast did show up.
Here's the code for my CustomView.
form_field.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_marginBottom="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/grey_rounded_borders">
<EditText
android:id="#+id/edit_text"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:inputType="text"
android:padding="10dp"
android:textColor="#2d6169"
android:textSize="18sp"
android:background="#color/transparent" />
<RelativeLayout
android:layout_marginStart="5dp"
android:layout_marginEnd="10dp"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<com.example.app.ValidationIcon
android:id="#+id/validation_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
tools:ignore="ContentDescription" />
</RelativeLayout>
</LinearLayout>
FormField.java
package com.example.app;
import android.content.Context;
import android.content.res.TypedArray;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import java.util.ArrayList;
public class FormField extends LinearLayout {
private EditText editText;
private ValidationIcon validationIcon;
private Integer fieldInputType;
private String fieldInputHint;
public FormField(Context context)
{
super(context);
}
public FormField(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
TypedArray attrs = context.obtainStyledAttributes(attributeSet, R.styleable.FormField, 0, 0);
fieldInputType = attrs.getInt(
R.styleable.FormField_fieldInputType,
InputType.TYPE_TEXT_VARIATION_NORMAL
);
fieldInputHint = attrs.getString(
R.styleable.FormField_fieldInputHint
);
attrs.recycle();
inflate(getContext(), R.layout.form_field, this);
this.setFocusable(true);
this.setFocusableInTouchMode(true);
editText = (EditText)findViewById(R.id.edit_text);
editText.setInputType(fieldInputType);
editText.setHint(fieldInputHint);
editText.setFocusableInTouchMode(true);
validationIcon = (ValidationIcon)findViewById(R.id.validation_icon);
validationIcon.setValid(true);
ArrayList<View> touchables = new ArrayList<View>();
touchables.add(this);
touchables.add(editText);
addTouchables(touchables);
}
public FormField(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
}
registration_layout.xml
<RelativeLayout android:id="#+id/container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="20dp">
<RelativeLayout android:id="#+id/account_details"
android:layout_marginBottom="15dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.example.app.FormField
android:id="#+id/name_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="#string/name_field_hint" />
<com.example.app.FormField
android:id="#+id/email_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="#string/email_field_hint" />
<com.example.app.FormField
android:id="#+id/password_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="#string/password_field_hint" />
<com.example.app.FormField
android:id="#+id/re_password_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
custom:fieldInputHint="#string/re_password_field_hint" />
</RelativeLayout>
</RelativeLayout>
Min SDK Version is set at 14, target is set at 20. Any help would be greatly appreciated!
EDIT:
I got this logcat message today while testing long presses on my FormFields.
W/TextView﹕ TextView does not support text selection. Action mode cancelled.
I double checked my code and the EditText element is only ever cast as an EditText. If the EditText is being cast to a TextView that would explain my original issues but now I'm confused as to why or how it was cast as a TextView.
It looks like you are extending LinearLayout but never using it in your layout. From what you've posted, you aren't using the FormField at all and the only custom View I see is the ValidationIcon view. So hooking the touch events into EditText and ValidationIcon aren't occurring because you aren't using FormField in your layout.xml.
Rather than extending LinearLayout, why not just use the predefined methods and attributes to handle the behaviour you are trying to achieve. For example, displaying keyboard, requesting focus, and displaying hint:
<EditText
android:id="#+id/edit_text"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
**android:inputType="text"**
**android:hint="#styleable/FormField_fieldInputHint"**
android:padding="10dp"
android:textColor="#2d6169"
android:textSize="18sp"
android:background="#color/transparent" />
The keyboard should display when the edit text receives focus, if not you could programmatically do this by requesting focus and handling the IME manager call. For example, from the Activity/Fragment:
//call this from onViewCreated to grab focus and begin the flow
editText.requestFocus();
//set focus listener to handle keyboard display
editText.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);
} else {
InputMethodManager imm = (InputMethodManager)getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.showSoftInputFromWindow(myEditText.getWindowToken(), 0);
}
});
Make sure have not been setting inputType:'none' or '0X000000'
use this code for custom Edittext with title
custom_view.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:foregroundGravity="right"
app:layout_anchorGravity="right">
<LinearLayout
android:orientation="vertical"
android:id="#+id/search_closed_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center|right"
android:background="#color/white"
android:foregroundGravity="center"
android:gravity="right">
<TextView
android:id="#+id/txt_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center|left"
android:layout_marginStart="16dp"
android:layout_marginTop="14dp"
android:fontFamily="#font/intel"
android:foregroundGravity="center"
android:text="textview"
android:textColor="#color/title_color"
android:textSize="14dp"
android:textStyle="bold" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/lay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:clickable="true"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatEditText
android:id="#+id/edt_text"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#drawable/edit_txtbg"
android:fontFamily="#font/intel"
android:gravity="center|start"
android:paddingStart="24dp"
android:textColor="#color/text_color"
android:textColorHint="#color/txt_hint"
android:textSize="#dimen/text_nev"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#+id/img_add_patient"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</FrameLayout>
CustomEditText.kt
package com.mdppractice.custom
import android.content.Context
import android.text.InputType
import android.util.AttributeSet
import android.view.LayoutInflater
import android.widget.EditText
import android.widget.FrameLayout
import android.widget.TextView
import com.mdppractice.R
class CustomEditText(
context: Context,
attrs: AttributeSet,
) : FrameLayout(context, attrs) {
private var txt_title: TextView
private var edt_text: EditText
init {
LayoutInflater.from(context)
.inflate(R.layout.custom_view, this, true)
txt_title = findViewById(R.id.txt_title)
edt_text = findViewById(R.id.edt_text)
val a = context.obtainStyledAttributes(attrs, R.styleable.CustomEditText)
txt_title.text = a.getString(R.styleable.CustomEditText_title)
edt_text.hint = a.getString(R.styleable.CustomEditText_hint)
when(a.getString(R.styleable.CustomEditText_inputType)) {
"number" -> edt_text.inputType = InputType.TYPE_CLASS_PHONE
"textCapSentences" -> edt_text.inputType = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
"text" -> edt_text.inputType = InputType.TYPE_CLASS_TEXT
}
a.recycle()
}
fun setmInputType(type: Int) {
edt_text.setRawInputType(InputType.TYPE_CLASS_TEXT)
setmInputType(type)
}
fun setTitle(title: Int) {
txt_title.setText(title)
}
fun set_Text(title: Int) {
edt_text.setText(title)
}
fun getTitle(): String {
return txt_title.text.toString()
}
fun get_Text(): String {
return edt_text.text.toString()
}
}
main/../attr.xml
<declare-styleable name="CustomEditText">
<attr name="title" format="string"/>
<attr name="onCenter" format="boolean"/>
<attr name="hint" format="string"/>
<attr name="maxLength" format="integer"/>
<attr name="inputType" format="string"/>
</declare-styleable>
#drawable/edit_txtbg
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="#+id/listview_background_shape">
<stroke android:width="1dp" android:color="#color/button_bg_border" />
<padding android:left="0dp"
android:top="0dp"
android:right="0dp"
android:bottom="0dp" />
<corners android:radius="6dp"/>
<solid android:color="#color/button_bg" />
</shape>
use in layout
<com.mdppractice.custom.CustomEditText
android:id="#+id/edt_custom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="Patient ID/Phone"
android:autofillHints="#string/verified"
android:foregroundGravity="center"
android:hint="Please enter name"
app:inputType="textCapSentences"
android:textColor="#color/title_color"
android:textSize="14dp"
android:textStyle="bold" />
thanks you

R.styleable cannot be resolved

hai friends...my java file indicate this error:
R.styleable cannot be resolved....
my xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Gallery xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/videoGrdVw"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="auto_fit"
android:verticalSpacing="5dip"
android:horizontalSpacing="5dip"
android:columnWidth="80dip"
android:stretchMode="columnWidth"
android:gravity="center"/>
<ImageSwitcher
android:id="#+id/switcher"
android:layout_height="match_parent"
android:layout_width="match_parent">
</ImageSwitcher>
<resources>
<declare-styleable name="HelloGallery">
<attr name="android:galleryItemBackground" />
</declare-styleable>
</resources>
</LinearLayout>
source code:
private class VideoGalleryAdapter extends BaseAdapter
{
private int itemBackground;
public VideoGalleryAdapter(Context c)
{
_context = c;
TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
itemBackground = a.getResourceId(
R.styleable.Gallery1_android_galleryItemBackground, 0);
a.recycle();
}
create an xml file under values folder, with the name attributes.xml and copy below contents to it.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Gallery1">
<attr name="android:galleryItemBackground"/>
</declare-styleable>
</resources>
This should work.
According to this forum thread you need to change:
TypedArray a = obtainStyledAttributes(R.styleable.Gallery1);
to
TypedArray a = c.obtainStyledAttributes(R.styleable.Gallery1);
For me, this did the trick:
import android.R;

Categories