I wanna create a button class which extends Button.And when I click my custom button ,it will show a circle shape above it and then the circle shape dispears.The code likes:
public class MyButton extends Button {
public GlowButton(Context context) {
super(context);
}
public GlowButton(Context context,AttributeSet attrs) {
super(context, attrs);
}
#Override
public boolean performClick() {
//Add the code for show the shape
return super.performClick();
}
}
Is this possible ? And How can i create the shape above the button?
thanks in advance!!
I believe what you can do is load an image from a drawable, where your shape has already been created. Put the shape above the button in the layout (XML) file using an imageview, and then change the visibility of that imageview to invisible on default. When the button is clicked, change the visibility to visible.
Related
I'm using custom checkbox for rtl support using rightDrawable property.
public class SRCheckBox extends AppCompatCheckBox {
public SRCheckBox(Context context) {
super(context);
init(context);
}
private void init(Context context) {
if (isRTL()) {
this.setButtonDrawable(null);
int[] attrs = {android.R.attr.listChoiceIndicatorMultiple};
TypedArray ta = context.getTheme().obtainStyledAttributes(attrs);
Drawable rightDrawable = ta.getDrawable(0);
this.setCompoundDrawablesWithIntrinsicBounds(null, null, rightDrawable, null);
}
}
}
but here is the problem that I'm facing with: please looke at this gif
As you can see touch animation is affecting on left side (on text) instead of
animating on the checkbox itself.
I've also tried in XML:
<CheckBox
android:id="#+id/fastDecodeCB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:button="#null" // this is causing the problem
android:drawableRight="?android:attr/listChoiceIndicatorMultiple" />
but it looks the same. any suggestions?
You are setting the checkbox button to null effectively removing it and setting a right drawable. The right drawable responds to the clicks, but the checkbox doesn't really know that the drawable is the button (you told it there is no button), so it just does what you see.
Try the following for the init method in your custom view.
private void init(Context context) {
if (isRTL()) {
// This will flip the text and the button drawable. This could also be set in XML.
setLayoutDirection(LAYOUT_DIRECTION_RTL);
int[] attrs = {android.R.attr.listChoiceIndicatorMultiple};
TypedArray ta = context.getTheme().obtainStyledAttributes(attrs);
Drawable rightDrawable = ta.getDrawable(0);
this.setButtonDrawable(rightDrawable);
ta.recycle(); // Remember to do this.
}
}
I am in the process of making a custom view that is essentially an ImageButton with added logic so it also have the behavior of a RadioButton. All I want to do is have it built into the view that when the user clicks the button the image is changed, an internal boolean is marked true to note it is selected, and an interface method is called to let the RadioGroup it is a part of to unselect all the other views within it. I don't want to impact the existing behavior of the base ImageButton whatsoever.
I've only made one other custom view before and that was by following a tutorial almost exactly to the letter and since there are so many different methods inhereted from View that deal with clicks/touches (i.e. onTouch, onClick, motion event, etc.) taking it all in has left me a bit confused. I am fine writing the interface itself, its the modification of ImageButton where I'm not too sure how to attack it.
So, I ask you all: What method/methods do I need to override to add this simple functionality, while not impacting the current behavior of ImageButton, nor screwing up the ability to set an onTouchListener for the button that will perform additional actions on click without compromising this built in radio button logic? If I need to override something that will mess with the default behavior I mentioned, what do I need to put in the new method to restore that functionality?
This is what I have so far:
public class RadioImageButton extends AppCompatImageButton implements RadioCheckable {
//Default constructor
public RadioImageButton(Context context) {
super(context);
initView();
}
//Constructor with defined attributes
public RadioImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
parseAttributes();
initView();
}
//Constructor with defined attributes and attributes taken from style defaults that aren't defined
public RadioImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//=========================================================================
// Setup
//=========================================================================
private void initView()
{
}
private void parseAttributes()
{
}
}
The approach I would like to take would be something like:
...All other code I already showed
mChecked = false;
#Overide
void onClick(...)
{
mChecked = true;
setImageSource(R.example.checked_image); // Or I can use a selector resource
*Call to Radio Interface*;
mOnTouchListener.onTouch(v, event); //Handle user onTouchListener
}
...
and leave all the other code alone, though I'm sure it isn't quite that simple.
I thought a good start would be trying to find the source code for the default ImageButton class and set mine up to be a near replica so I can understand how it works and then modify from there, but all I could really find was this:
https://android.googlesource.com/platform/frameworks/base/+/android-7.0.0_r35/core/java/android/widget/ImageButton.java
and there is no way that is the actual source because pressing Ctrl+O shows many more functions that ImageButton defines that are not inherited from another class; regardless, that link is not at all helpful as its basically a giant comment with little to no code.
Thanks for any suggestions that will help me accomplish this in the most straightforward way.
EDIT: #pskink - Looking through the code you provided, it seems like it is trying to generate a matrix in order to transform the provided drawable (src) so that it fits into a new rectangle (dst) while maintaining the aspect ratio and positioning (hence ScaleToFit.CENTER). I would assume the destination rectangle would be the bounds of the view the drawable is contained in, which in this case is the RadioButton, but while stepping through the override of the "draw()" method it doesn't quite seem to be doing that, though I'm not quite sure how cavas.concat(matrix) is resolved so I'm not positive. Regardless it doesn't seem to work as intended or I am somehow using it wrong.
While maybe not the most robust method, it seems like the most straightforward, yet effective way to handle what I wanted to do was to leverage the Matrix class and its powerful scaling/transformation tools, specifically "setRectToRect()". Creating a custom view that extends RadioButton instead of ImageButton allowed me to make use of the existing RadioGroup, while manipulating characteristics of the button's drawables in the new classes Constructor achieved the behavior I was looking for.
Custom RadioButton class:
public class RadioImageButton extends android.support.v7.widget.AppCompatRadioButton {
int stateDrawable; //Resource ID for RadioButton selector Drawable
D scaledDrawable; //Post-scaling drawable
public RadioImageButtonTwo(Context context) {
super(context);
initView();
}
public RadioImageButtonTwo(Context context, AttributeSet attrs) {
super(context, attrs);
parseAttributes(attrs);
initView();
}
private void parseAttributes(AttributeSet attrs)
{
TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs,R.styleable.RadioImageButtonTwo);
try {
// Obtain selector drawable from attributes
stateDrawable = styledAttrs.getResourceId(R.styleable.RadioImageButtonTwo_button_sDrawable, R.drawable.test_draw2);
} finally {
styledAttrs.recycle(); //Required for public shared view
}
}
private void initView()
{
scaledDrawable = new D(getResources(),stateDrawable); // Create scaled drawable
setBackground(scaledDrawable); // Apply scaled drawable
setButtonDrawable(android.R.color.transparent); // "Disable" button graphic
}
}
See more on setting up a custom view here: https://developer.android.com/training/custom-views/create-view#customattr
Custom drawable class "D" that includes fitCenter scaling thanks to #pskink:
class D extends StateListDrawable {
private Rect bounds = new Rect();
private RectF src = new RectF();
private RectF dst = new RectF();
private Matrix matrix = new Matrix();
public D(Resources r, int resId) {
try {
XmlResourceParser parser = r.getXml(resId);
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG && parser.getName().equals("selector")) {
inflate(r, parser, Xml.asAttributeSet(parser));
break;
}
}
} catch (XmlPullParserException | IOException e) {
e.printStackTrace();
}
}
#Override
public void draw(Canvas canvas) {
Drawable current = getCurrent();
bounds.set(0, 0, current.getIntrinsicWidth(), current.getIntrinsicHeight());
current.setBounds(bounds);
src.set(bounds);
dst.set(getBounds());
matrix.setRectToRect(src, dst, Matrix.ScaleToFit.CENTER);
canvas.concat(matrix);
super.draw(canvas);
}
}
Note that for whatever reason setting the button drawable itself to this custom drawable breaks the scaling, so changing the background to the custom drawable and setting the button drawable to transparent was the only way this worked. This custom drawable could easily be expanded upon to have more scaling type options and another view attribute could be defined to allow the user to choose the scaling type through XML.
This custom ImageView that mimics the (pointed out by pskink aswell) could also prove helpful in this task, as it too utilizes the Matrix class to implement multiple types of image scaling: https://github.com/yqritc/Android-ScalableImageView
I'm using android 2.0. I have a view (just a sipmle linearlayout with an image as background), which contains 3 imagebuttons. When I touch any part of this view, my buttons are not touchable any more. As they are disabled! How can I disable the touchability of the background? I just want to be able to touch the buttons even if I put my finger on the other parts of the view. Is that possible?
The code sample:
public class myView extends LinearView {
public myView(Context context) {
super(context);
}
public setView(Context context) {
setBackgroundDrawable(backImg);
setOrientation(LinearLayout.HORIZONTAL);
setGravity(Gravity.CENTER);
setScrollContainer(false);
ImageButton imgBtn0 = new ImageButton(context);
imgBtn0.setBackgroundColor(Color.TRANSPARENT);
imgBtn0.setBackgroundDrawable(imgBtnD0);
imgBtn0.setDrawingCacheEnabled(true);
imgBtn0.setOnTouchListener(new TouchListener(context, id0));
...
addView(imgBtn0, 0);
addView(imgBtn1, 1);
addView(imgBtn2, 2);
}
}
you can disable the touch of the linearlayout using android:clicable="false" but how will you figure out which image button to be clicked if the user clicks in the background?
I am new for android. I want to add image button in onDraw. I wonder if I can do like this. I don't have compile error. But simulator says, "Unfortunately MyApp has stopped."
My second question is how can I add button at x, y location in screen?
There is no location parameters in addView.
protected class MyLayout extends LinearLayout {
ImageButton button;
public MyLayout(Context context) {
super(context);
setWillNotDraw(false);
button = new ImageButton(context);
button.setImageBitmap(buttonBitmap); // buttonBitmap is loaded in onCreate
}
public void onDraw(Canvas canvas) {
addView(button);
}
}
I would not be adding a button to a custom linearlayout in the onDraw() override function. onDraw is called periodically (for example when the element is resized). So you will be adding the same button EACH time onDraw() is called. And you will get an error if you add the same item more than once.
What exactly are you trying to do? If you want to just add a button to a linear layout, you can do so without extending a layout.
How I can put an image over an activity (something like the image below) but with the buttons and other widgets under this image receiving the touch events?
image http://images.macworld.com/appguide/images/android/558/2908791394402692/5582908791394402692_1.jpg
You can create a transparent Activity like this How do I create a transparent Activity on Android? and make a Layout with a fullscreen ImageView
I solve the problem override the draw function.
public class TutorialLinearLayout extends LinearLayout {
public TutorialLinearLayout(Context context) {
super(context);
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
Bitmap tutorial = BitmapFactory.decodeResource(getResources(), R.drawable.tutorial);
canvas.drawBitmap(tutorial, 0, 0, null);
tutorial.recycle();
}
}