INTRODUCTION
I'm practicing with canvas-graphics on android. For this I created an app where I can write a line with the finger, and erase it.
When I click the color palette, a dialog window appears with some colors. So I have 2 layouts:
1- The main layout
2- The palette layout
QUESTION
First I got the color palette in the main activity, and for each color button I have an onClick which calls to a method on main Activity.
The thing is that now I'm not able to do this onClick functionality. I think that it has something to do with that now I start this layout as a view instead as a layout, so the onClick functionality of each button doesn't work
This is palette.xml layout's button example:
<ImageButton
android:layout_width="#dimen/large_brush"
android:layout_height="#dimen/large_brush"
android:background="#FF660000"
android:onClick="paintClicked"
android:tag="#FF660000" />
When I click on each button, it starts the paintClicked method an passes the color tag.
So, how do I have to initiate the palette layout when i click on the palette button, to be able to have the information passing from this layout to the main activity?
UPDATE -- Current method to call palette.xml
final Dialog paletteDialog = new Dialog(this);
paletteDialog.setTitle("Colores:");
paletteDialog.setContentView(R.layout.palette);
LinearLayout paletteLayout = (LinearLayout) paletteDialog.findViewById(R.id.paint_colors);
bnColor = (ImageButton) paletteLayout.getChildAt(0);
bnColor.setImageDrawable(getResources().getDrawable(R.drawable.button_pressed));
paletteDialog.show();
Logcat:
java.lang.NoSuchMethodException: paintClicked [class android.view.View]
This is the paintClicked method reference:
public void paintClicked(View view){
I suggest you look at DialogFragment (if you aren't using it already). You can create a simple callback interface so that when a color is clicked, it calls back to the enclosing Activity with this information. Make the enclosing Activity implement the interface (enforced by the onAttach lifecycle method below) and have the dialog fragment call it when a color is picked.
public class ColorPickerDialog extends DialogFragment implements View.OnClickListener {
// Define a callback interface
public interface OnColorSelectedListener {
public void onColorSelected(int color);
}
private OnColorSelectedListener listener;
#Override
public void onAttach(Activity activity) {
if (!(activity instanceof OnColorSelectedListener)) {
throw new IllegalStateException("Activity must implement OnColorSelectedListener!");
}
listener = (OnColorSelectedListener) activity;
}
#Override
public void onDetach() {
listener = null;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(getActivity());
View view = inflater.inflate(R.layout.palette, container, false);
// call view.findViewById(...) for all your color buttons and
// set the OnClickListener
view.findViewById(...).setOnClickListener(this);
...
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Colores:");
builder.setView(view);
return builder.create();
}
#Override
public void onClick(View v) {
/*
* Determine the color from the view that was clicked. You can use a
* switch statement on v.getId() if they all have IDs, but there are
* other possibilities as well.
*/
int color = ...;
listener.onColorSelected(color);
dismiss();
}
}
android:onClick only works if the Context which expanded the view contains the function ("paintClicked" here).
So if you didn't expand this layout with your main Activity it could the reason it doesn't work.
It might be better for you to set Ids to the ImageButtons and use some findViewById(R.id.btnX).setOnClickListener(myListener); after displaying the buttons.
Related
I need suggestion,
I am new in android, I am trying to implement emojis like facebook in my feed
using this link
FBReaction I am able to show the emojis on click of my Like button But I am not able to remove it from my view once the emojis got selected.
Here is my code in Adapter file to show emojis view
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_row_social, parent, false);
RelativeLayout rl = (RelativeLayout)view.findViewById(R.id.btReaction);
final CardView root = (CardView)view.findViewById(R.id.card_view);
rl.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ReactionView rvl = new ReactionView(mContext);
root.addView(rvl);
}
});
return new ViewHolder(view);
}
ReactionView rvl = new ReactionView(mContext);
root.addView(rvl);
Above line is used to show the emojis view.
RelativeLayout rl is my layout on click of this layout I am showing my emojis list. like below
same as above I have multiple feeds where I have like button, on click of those button I am able to show emojis view but couldn't remove it once it is selected.
I have a different class (ReactionView) to show the emojis List which is available in Git Repo
now My problem is how I remove the view once the emojis got selected.
You need to modify the custom view ReactionView class a little bit, if you notice the onTouchEvent() of that class it registers different MotionEvent's, and particularity, when the MotionEvent.ACTION_UP event is triggered, this means that the user has left their finger of the ReactionView emojis, at this time you need to remove the ReactionView from your layout.
So as you can remove your view when the onDeselect() is over, so to that, there is a couple of methods:
Method 1:
Remove the focus from the ReactionView, and implement OnFocusChangeListener on the ReactionView
public class ReactionView extends View {
...
private void onDeselect() {
deselectAnimation.prepare();
startAnimation(deselectAnimation);
// Hide the view and remove the focus from it.
setVisibility(GONE);
setFocusableInTouchMode(false);
setFocusable(false);
setFocusableInTouchMode(true);
}
In activity
rvl.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus)
root.removeView(rvl);
}
});
Method 2:
Create a listener to the ReactionView, trigger its callback in onDeselect() and implement it on your activity
public class ReactionView extends View {
...
public interface DismissListener {
void onDismiss();
}
public void setOnDismissListener(DismissListener onDismissListener) {
mOnDismissListener = onDismissListener;
}
DismissListener mOnDismissListener;
private void onDeselect() {
deselectAnimation.prepare();
startAnimation(deselectAnimation);
if (mOnDismissListener != null)
mOnDismissListener.onDismiss();
}
In activity
rvl.setOnDismissListener(new ReactionView.DismissListener() {
#Override
public void onDismiss(int selectedIndex) {
root.removeView(rvl);
}
});
You can make this with a listener.
In your ReactionView class add :
interface ReactionListener{
public void onReactionClicked();
}
Then add to the constructor of ReactionView (Context context, ReactionListener: listener). I assume you want to hide this view when the user is clicking on an emoji, so where you set click listener for that, also call listener.onReactionClicked()
Then in your adapter create the listener object and remove the view:
private ReactionListener reactionListener = new ReactionView.ReactionListener(){
#override
public void onReactionClicked(){
root.removeView(rvl);
}
The problem is MainActivity starts with a setContentView with a layout.xml. We can add buttons or anything to the layout and code in in the MainActivity class but when I try to code the buttons of another layout in the same Activity the app forces stop . Whats wrong ?
Ok I found out that is because of the context.
When you try to change other activity you have to use layoutinflater. Example below
LayoutInflater inflater = getLayoutInflater();
View myLayout = inflater.inflate(R.layout.my_layout, null);
To work with widgets inside it like buttons or anything .
Button b = mylayout.findViewById(R.id.button);
b.setText("Successfully changed");
Now you can use myLayout as your changed layout.
Please sent me your Activities
What the text of problem ?
You may write next code to go to another activity
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(getApplicationContext(),nameActivity.class));
}
});
Where button is name of your button
See that you xml-file doesnt have any mistakes
You are getting a crash because you are trying to access the layout when it is not inflated. In other words, you must call setContentView() on an Activity, or inflater.inflate() on a Fragment to instantiate the view and make the elements accessible for manipulation. So if you want to add buttons to another Activity, you would need to call its onCreate() and setContentView() before you can add buttons to it.
EDIT: In response to comments...
In order to access/manipulate/modify elements in a layout at runtime, they must first be instantiated, which happens when the view is inflated. So to add a button to an Activity at runtime, you would do it in the onCreate() method after calling setContentView() like this:
Keep in mind this is the onCreate() of your SECOND activity...not your main Activity. So your main activity would start this Activity, then the button would get created during the setup of the second Activity.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_second_activity;
Button button = new Button(this);
button.setText("Your New Button");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("NEW BUTTON", "I just clicked my new button!");
}
});
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.layout_in_your_second_activity);
relativeLayout.addView(button);
}
If you are using a Fragment to display your UI, you can't access your UI elements until you have inflated your layout, which happens in the onCreateView() method. So you would do something like this in your Fragment code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.your_fragment_layout, container, false);
RelativeLayout relativeLayout = (RelativeLayout) view.findViewById(R.id.container_layout_that_holds_button);
//You would get your context from an onAttach() Override
Button button = new Button(context);
button.setText("Your New Button");
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("NEW BUTTON", "I just clicked my new button!");
}
});
relativeLayout.addView(button);
return view;
}
You're likely getting a NullPointerException when you try to manipulate your layouts before they are created. Keep in mind that even if you have an XML file with layouts specified within, the actual objects for those elements won't be created until the system decides it needs them, which happens when you actually try to display the view.
public class Home extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.home,null);
}}
This is the whole code for fragment tab 1..
I have a program with two TabFragments , and I want to declare an image button and button intent in fragment tab 1 and 2, but I can't do it , and the findviewbyid did not work..
What can I do to declare buttons intent ??
To handle button clicks (and view clicks in general) View.OnClickListener interface is used. All you have to do is override its onClick method and assign it to a view by calling setOnClickListener().
You can also find a thorough tutorial here.
UPD: Your method should look like this:
public View onCreateView(.....) {
// assign inflated view to a variable
View v = inflater.inflate(R.layout_services, null);
// set your listener
v.findViewById(R.id.imageButton).setOnClickListener(.....);
// return the view in the end
return v;
}
The problem is that you're instantly returning the inflated view and the code below wouldn't run at all, this is why there's that error.
UPD2: Now the problem is that startActivity method is receiving Context as a first parameter, so you should pass your activity there by calling getActivity() (instead of passing Services.this). You can read more here.
UPD3: You don't seem to understand what your code does. Your findViewById call is useless because it's not getting assigned to a variable, and your setOnClickListener is getting applied to the entire fragment view. Here's what that part should look like:
ImageButton button = (ImageButton) v.findViewById(R.id.imageButton);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Activity activity = getActivity();
Intent intent = new Intent(activity, Admin.class);
activity.startActivity(intent);
}
});
I'd recommend to learn how all those methods work (at least have a look at the reference, to begin with: here and here) before trying to actually write an application. Good luck with it.
I have an activity over which contains imageview added dynamically on clicking a button. Over the activity i am inflating a dialogue box on click of the dynamically added image . Inside the dialog box i have a button to delete that image which is popping up that dialog .
My problem is how to access that imageview instance which is behind the dialog , so that i could delete it .
//Popping up the dialog on click of the imageview
imageView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
customPotraitDialog = new CustomPotraitDialog(potrait);
customPotraitDialog.show();
//This i am doing on click of the button inside the dialog
dismiss();
View parent = (View) v.getParent();
RelativeLayout view = (RelativeLayout) parent.findViewById(R.layout.potrait);
deleteFromPotrait(view);
Potrait is my layout of the from where the dialog is popping up. It returning the view as null.
Pass instance of your activity to the dialog then onClick() deleteFromPotrait(view) method that is public in your activity like the following:
calling dialog
customPotraitDialog = new CustomPotraitDialog(potrait, context);
inside your dialog constructor:
public CustomPotraitDialog(potrait, context)
{
this.potrait = potrait;
this.context = context;
}
onClick():
((YourActivityName) context).deleteFromPotrait(view);
I have a custom dialog (extends Dialog) whose contentview is a custom viewgroup. The viewgroup has a few edittext children, but I am handling the drawing and clicking of buttons myself in the viewgroup's dispatchDraw and onTouch methods (I'm trying to avoid inflating as many views as possible). Specifically: this view has no button children that I could set to be the dismiss button for the dialog. I want to dismiss the dialog from within the onTouch method of the viewgroup, but beyond simulating a press of the back key, I cannot figure out how to do this.
activity code:
public class My_Activity extends Activity {
...
public void onCreate(Bundle savedInstanceState) {
...
//if there's no Class_That_Im_Editing in the database, prompt the user to make a new one by adding information to the editviews in this custom dialog and clicking the area where I draw the ok button
my_dialog = new Custom_Dialog(this, R.style.CustomDlg, new Class_That_Im_Editing());
}
}
dialog code:
public class Custom_Dialog extends Dialog {
...
public void onCreate(Bundle savedInstanceState) {
...
setContentView(new Custom_ViewGroup(context, Class_That_Im_Editing));
}
}
viewgroup code:
public class Custom_ViewGroup extends ViewGroup implements OnTouchListener {
//this class has some edittext children but _no_ buttons
...
public boolean onTouch(View view, MotionEvent event) {
if ( logic checking if the user has clicked the button area ) {
//??? what do I put here to dismiss the dialog
}
}
}
The only other approach I can think of is using the dismissDialog(int) method, which means overriding the onCreateDialog and onPrepareDialog event handlers. But how can I call dismissDialog from within a view's onTouch method?
Maybe I need to set up a listener of some kind? If so, what would be the skeleton code to do this?
So the problem was telling a dialog to dismiss() when I wasn't in the scope where the dialog existed. Here's my solution:
Create the OnTouchListener in the same scope as the dialog - in this case, inside my main activity. Then pass it when you initialize the dialog, which in turn needs to pass it to the viewgroup.
It will look something like this:
activity code:
public class My_Activity extends Activity {
public Custom_Dialog my_dialog;
...
public void onCreate(Bundle savedInstanceState) {
OnTouchListener otl_custom_dialog = new OnTouchListener() {
public boolean onTouch(View view, MotionEvent event) {
if ( logic checking if the user has clicked the button area ) {
//notice I can still access any _public_ variable within the viewgroup class
//by using my_dialog.my_custom_viewgroup.public_variable
...
//I can now call dismiss() from within this scope
my_dialog.dismiss();
}
...
}
}
...
//if there's no Class_That_Im_Editing in the database, prompt the user to make a new one by adding information to the editviews in this custom dialog and clicking the area where I draw the ok button
my_dialog = new Custom_Dialog(this, R.style.CustomDlg, new Class_That_Im_Editing(), otl_custom_dialog);
my_dialog.show();
}
}
dialog code:
public class Custom_Dialog extends Dialog {
Custom_ViewGroup my_custom_viewgroup;
OnTouchListener otl_custom_dialog;
...
public void onCreate(Bundle savedInstanceState) {
...
setContentView(new Custom_ViewGroup(context, class_that_im_editing, otl_custom_dialog));
}
}
viewgroup code:
public class Custom_ViewGroup extends ViewGroup implements OnTouchListener {
public Custom_ViewGroup(Context context, Class_That_Im_Editing class_that_im_editing, OnTouchListener otl_custom_dialog) {
...
this.setOnTouchListener(otl_custom_dialog);
}
}
I have tested this method and it works fine. Hope this helps someone else out there!