I want a button in my Settings screen. This exact question has been asked here. But unfortunately has no answers. :(
In order to get to this, I created a custom preference like this -
public class CustomPreference extends Preference {
private LinearLayout mWidgetContainer;
private View mRowView;
public CustomPreference(Context context) {
super(context);
}
public CustomPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected View onCreateView(ViewGroup parent) {
LayoutInflater viewInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mRowView = viewInflater.inflate(R.layout.preferences_row_view, parent, false);
mWidgetContainer = (LinearLayout) mRowView.findViewById(android.R.id.widget_frame);
Button button = new Button(getContext());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
button.setLayoutParams(params);
button.setBackgroundResource(R.drawable.listview_row_bg);
button.setTextSize(14);
button.setPadding(5, 5, 5, 5);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getContext(), BuyScreenActivity.class);
getContext().startActivity(intent);
}
});
button.setTypeface(null, Typeface.BOLD);
button.setText("Buy now");
mWidgetContainer.addView(button);
return mRowView;
}
}
This does work. But it behaves strange. As you can see on click of that button I'm taking the user to Activity called BuyScreenActivity. The strange part is when I press back on BuyScreenActivity, I come back to my Settings screen but onDestroy and onStop of BuyScreenActivity is not called at all. Why would it behave that way?
If I scroll down the settings screen, onStop & onDestroy will then be called. Why does this have to behave that way?
I don't know why that is happening exactly, but if it bothers you, just override onBackPressed() in BuyScreenActivity.java:
#Override
public void onBackPressed() {
startActivity(new Intent(getContext(), SettingsACtivity.class));
}
Note that I'm assuming that you're only getting to BuyScreen through Settings.
If you're not, then it's easy enough to put the name of the previous activity into the intent data, and switch that to get to the desired activity.
Related
I am trying to add specific behaviour to Button's onClick, so when they are clicked they have the custom behaviour on top of the specific action for each button.
I have recently started developing for Android and have little experience on the inner quirks of events and UI classes.
WHat I tried, the buttom performs the custom behaviour I write in the extended class, but then doesn't perform the onClick action I assigned to the button specifically.
This is the custom Button I'm trying to do.
public class CooldownButton extends Button implements View.OnClickListener
{
Timer cooldown;
public CooldownButton(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public CooldownButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CooldownButton(Context context)
{
super(context);
}
#Override
public void onClick(View v)
{
cooldown= new Timer();
cooldown.schedule(cooldownRun(),0,500);
setEnabled(false);
//performClick();
}
private TimerTask cooldownRun()
{
return new TimerTask()
{
#Override
public void run()
{
cooldown.cancel();
cooldown.purge();
setEnabled(true);
}
};
}
}
Then I use it on xml layouts like this:
<CooldownButton android:id="#+id/btnNext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onBtnNextClick" />
OnBtnNextClick is never called.
public void onBtnNextClick(View v)
{
if(v.getId() == R.id.btnNext)
{
//Do something
}
}
From what I am seeing you are disabling the button setEnabled(false); and then you want to perform some action on a next click onBtnNextClick(View v). You cannot click a button a second time if it has been disabled when it was first clicked.
I found a solution after following one of the comments indications.
It is not exactly the way I wanted to solve the issue but it gets close.
I scrapped the idea of making the click behaviour in a java class.
Instead I write a click listener in the MainActivity and then set the listener to all buttons I want to have this special click behaviour.
Button nextButton = (Button) layout.findViewById(R.id.btnNext);
nextButton.setOnClickListener(buttonClickListener);
The listener is as follows:
public View.OnClickListener buttonClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
final Button btn = (Button) v;
btn.setEnabled(false);
new Thread(new Runnable() {
#Override
public void run() {
try {Thread.sleep(1000); }
catch (InterruptedException e) {e.printStackTrace();}
MainActivity.this.runOnUiThread(new Runnable()
{
#Override
public void run(){ btn.setEnabled(true); }
});
}
}).start();
switch (v.getId()) {
case R.id.btnNext:
doSomething();
break;
//case R.id.foobar:
//break;
}
}
};
I made a Bitmap button that has an animation effect on a layout
but it cannot find the id of the layout and it says it indicates Null point
Here is my source below
public class BitmapButton extends Button{
public BitmapButton(Context context) {
super(context);
init();
}
public BitmapButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
setBackgroundResource(R.drawable.background_selector);
setOnClickListener(new OnClickListener() {
boolean selected=true;
Animation anim;
LinearLayout layout_search = (LinearLayout)findViewById(R.id.layout_search);
#Override
public void onClick(View v) {
if(selected) {
setSelected(true);
anim = AnimationUtils.loadAnimation(getContext(), R.anim.translate_down);
***layout_search.startAnimation(anim);***
layout_search.setVisibility(View.VISIBLE);
selected =!selected;
}
else{
setSelected(false);
anim = AnimationUtils.loadAnimation(getContext(), R.anim.translate_up);
layout_search.startAnimation(anim);
layout_search.setVisibility(View.GONE);
selected =!selected;
}
}
});
}
}
=========================================================================
layout_search.startAnimation(anim);
from here it gets wrong saying
java.lang.NullPointerException: Attempt to invoke virtual method void android.widget.LinearLayout.startAnimation(android.view.animation.Animation) on a null object reference
I know findViewById method in Button Class is different from the one in the MainActivity but I just dont know then, how I can find the LinearLayout linear_search?? with this problem I can make the anim effection on this button.
plz let me know...
public class BitmapButton extends Button{
public BitmapButton(Context context) {
super(context);
init();
}
public BitmapButton(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init(){
setBackgroundResource(R.drawable.background_selector);
setOnClickListener(new OnClickListener() {
boolean selected=true;
Animation anim;
// _____________ just commented out this line ______________
// LinearLayout layout_search = (LinearLayout)v.findViewById(R.id.layout_search);
#Override
public void onClick(View v) {
// i simply add this line here and add view v before findViewById
LinearLayout layout_search = (LinearLayout)v.findViewById(R.id.layout_search);
if(selected) {
setSelected(true);
anim = AnimationUtils.loadAnimation(getContext(), R.anim.translate_down);
***layout_search.startAnimation(anim);***
layout_search.setVisibility(View.VISIBLE);
selected =!selected;
}
else{
setSelected(false);
anim = AnimationUtils.loadAnimation(getContext(), R.anim.translate_up);
layout_search.startAnimation(anim);
layout_search.setVisibility(View.GONE);
selected =!selected;
}
}
});
}
}
LinearLayout layout_search = (LinearLayout)findViewById(R.id.layout_search);
From documentation:
Look for a child view with the given id. If this view has the given id, return this view.
You trying to search layout inside button. Try to use getParent().findViewById
if you want to start animation on parent of button.
The application is a step sequencer application with 16 radio groups with 8 buttons in each group. It works perfectly except once a group has a button selected I cant turn it off unless I use the clear button I have created to clear all radiogroups. What I would like to add is some code that says when a selected radio button is selected again it simply turns off like a toggle. I tried using toggles but then other issues arose with that method. Below are two attempts but both simply stops me using the button
final RadioGroup radioGroup1 = (RadioGroup) findViewById(R.id.RadioGroup1);
RadioButton D1 = (RadioButton) findViewById(R.id.RadioButtonD1);
Button D1 = (Button) findViewById(R.id.RadioButtonD1);
D1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick (View v){
PdBase.sendFloat("D1", 74);
int selectedTypeId = radioGroup1.getCheckedRadioButtonId();
RadioButton D1 = (RadioButton) findViewById(selectedTypeId);
if (D1 != null) // This will be null if none of the radio buttons are selected
radioGroup1.clearCheck();
PdBase.sendFloat("D1", 0);
}
});
RadioButton lC1 = (RadioButton) findViewById(R.id.RadioButtonlowC1);
lC1.setOnClickListener(new View.OnClickListener() {
public void onClick (View v) {
int selectedTypeId = radioGroup1.getCheckedRadioButtonId();
RadioButton lC1 = (RadioButton) findViewById(R.id.RadioButtonlowC1);
if (selectedTypeId == -1) {
PdBase.sendFloat("lC1", 72);
}
else if (selectedTypeId == R.id.RadioButtonlowC1) {
radioGroup1.clearCheck();
PdBase.sendFloat("lC1", 0);
}
}
});
I recently had the same need - to have a radio group where the selected item could be deselected by tapping it again. I found that I couldn't accomplish that using listeners but I was able to do it using a custom RadioButton, like so...
public class ToggleableRadioButton extends RadioButton {
// Implement necessary constructors
#Override
public void toggle() {
if(isChecked()) {
if(getParent() instanceof RadioGroup) {
((RadioGroup)getParent()).clearCheck();
}
} else {
setChecked(true);
}
}
}
Notice that the button is toggled in different ways depending on its current state - i.e., calling setChecked(true) on the button vs. calling clearCheck() on the group. If setChecked() is used in both cases, a button that was just deselected cannot be immediately re-selected - the logic in RadioGroup seems to immediately deselect it.
To use this button, just replace your <RadioButton> tags with <your.package.ToggleableRadioButton> in your layout XML.
I just used the answer from #spaaarky21
and my full code look like this and it is working fine!
Java Class
public class ToggleableRadioButton extends RadioButton {
public ToggleableRadioButton(Context context) {
super(context);
}
public ToggleableRadioButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ToggleableRadioButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ToggleableRadioButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
public void toggle() {
if(isChecked()) {
if(getParent() instanceof RadioGroup) {
((RadioGroup)getParent()).clearCheck();
}
} else {
setChecked(true);
}
}
}
And for the XML layout
<com.smart_dent.adapters.ToggleableRadioButton android:id="#+id/tejido_blando_perfil_convexo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/tejido_blando_convexo_label" />
In this case you just need to change the package, I this is easy to find, it is just at the top of the Java Class Flie (if you created it from Android Studio)
It actually can be done with listeners but with an OnTouchListener, which will trigger before the button's state has changed, instead of the usual OnClickListener. The following works for me:
View.OnTouchListener radioButtonOnTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (((RadioButton) v).isChecked()) {
// If the button was already checked, uncheck them all
radioGroup.clearCheck();
// Prevent the system from re-checking it
return true;
}
return false;
}
};
radioButton1.setOnTouchListener(radioButtonOnTouchListener);
radioButton2.setOnTouchListener(radioButtonOnTouchListener);
Where radioGroup is the parent of radioButton1 and radioButton2
Edit from #spaaarky21 answer
#Override
public void toggle() {
if (isChecked()) {
if (getParent() instanceof RadioGroup) {
((RadioGroup) getParent()).clearCheck();
}
// add else here when a single radioButton without radioGroup
else {
setChecked(false);
}
} else {
setChecked(true);
}
}
This is also doing the job:
public final class ToggleAbleRadioButton extends AppCompatRadioButton {
public ToggleAbleRadioButton(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
#Override public void toggle() {
setChecked(!isChecked());
}
}
You can use a boolean to toggle the button on and off.
Add a boolean somewhere in your code:
var radioButton1IsSelected = false
Then setup the onClickListener for the button:
radioButton1.setOnClickListener {
radioButton1IsSelected = !radioButton1IsSelected
radioButton1.isChecked = radioButton1IsSelected
}
I am creating a PreferenceActivity by using the PreferenceScreen xml. I wants to open a new preference screen when click on the label(title) of a CheckBoxPreference and when the user click on check box of this CheckBoxPreference then normal preference functionality will work.
So how can I do it?
For Example: Change a user profile(by click on radio buttons) and changing its properties(by clicking on label of this radio button) in android
I think it's hard to do with a default preference. But you can try extending the original onBindView method, according to the documentation: This is a good place to grab references to custom Views in the layout and set properties on them. So, this is an example for CheckBoxPreference to be clickable on text.
public class MyCheckBoxPreference extends CheckBoxPreference {
static final String TAG = "MyCheckBoxPreference";
public MyCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MyCheckBoxPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyCheckBoxPreference(Context context) {
super(context);
}
#Override
protected void onBindView(View v) {
super.onBindView(v);
((ViewGroup) v).getChildAt(1).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "onClick " + getKey());
}
});
}
}
I need to start a new activity once the user clicks in a button which is rendered in a FrameLayout. It renders the button which I want the user to click, but of course it's not doing anything right now.
The code of the class is the following, but I can't call the startActivity(intent).
public class TopBarView extends FrameLayout {
private ImageView mLogoImage;
private Button mInfoButton;
public TopBarView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public TopBarView(Context context) {
super(context);
init();
}
public TopBarView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.top_bar, null);
mLogoImage = (ImageView) view.findViewById(R.id.imageLogo);
mInfoButton = (Button) view.findViewById(R.id.infoButton);
mInfoButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
// We load & render the view for the information screen
// Intent i = new Intent();
// i.setClass(getContext(), MeerActivity.class);
// startActivity(i);
}
});
addView(view);
}
}
Thanks a lot in advance!
Change :
public void onClick(View v) {
// We load & render the view for the information screen
// Intent i = new Intent();
// i.setClass(getContext(), MeerActivity.class);
// startActivity(i);
}
To :
public void onClick(View v) {
// We load & render the view for the information screen
Intent i = new Intent();
i.setClass(v.getContext(), MeerActivity.class);
v.getContext().startActivity(i);
}
Note : Might be better to assign the onclicklistener via the activity you are using so the TopBarView is a bit more reusable in case you ever want to use something other than MeerActivity as a target. No biggy tho.