I need to call an Intent from the onBindViewHolder of the recycler adapter , on a click event from one of the views in the ViewHolder. I am unable to do so directly ..
public void onBindViewHolder(MyAdapter.MyViewHolder viewHolder, int i) {
viewHolder.button.setonClickListener(new View.onClickListener(
#Override
onClick(View v) {
Intent i=new Intent();
i.setAction("Intent.ACTION_CALL");
i.setData(Uri.parse("tel:1234567890"));
startActivity(i);
}
));
}
This did not work. It kept throwing error. I then created a public method in the Activity with the same code. Passed Activity context in the Adapter constructor. Then called the Method as follows from button click event.
((MyActivity)context).makePhoneCall("1234567890");
This did the trick. But i feel there should be a better method of doing this.
As i am primarily from C background, i am not sure.
So my question is there a better or more proper way to do this , according to Java programming conventions.
If you need to call another activity via Intent, you can use any view's Context:
v.getContext().startActivity(i);
I think this is a correct method.
Another way is to implement a listener in the recycleradapter and listen it in the activity.
So in the adapter:
public class RecyclerAdapter .... {
private MyClickListener listener;
public void onBindViewHolder(MyAdapter.MyViewHolder viewHolder, int i) {
viewHolder.button.setonClickListener(new View.onClickListener(
#Override
onClick(View v) {
listener.onClicked(true);
}
));
public void setMyClickListener(MyClickListener listener) {
this.listener = listener;
}
}
//create MyClickListener.class
public interface MyClickListener {
public void onClicked(boolean status);
}
In your Activity:
public class MainActivity ... implements MyClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
adapter.setMyClickListener(this);
}
#Override
onClick(boolean status) {
if (status){
Intent i=new Intent();
i.setAction("Intent.ACTION_CALL");
i.setData(Uri.parse("tel:1234567890"));
startActivity(i);
};
}
}
Try this
In your Adapter:
Activity mContext;
public FollowersAdapter(Activity mContext) {
this.mContext = mContext;
}
//And then your click in onBindViewHolder
holder.linear_user.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
System.out.println("linear click>>>>>>>>>>>>");
Intent ToImage = new Intent(mContext, UserData.class);
ToImage.putExtra("user_id", data.get(position).getFollower_id());
mContext.startActivity(ToImage);
}
});
Related
I would like to get data from the box which click on on the recycler view to go into a another activity to display.
I have tried to flow this video https://www.youtube.com/watch?v=7GPUpvcU1FE&t=399s&ab_channel=PracticalCoding i dont understand at 6:16.
Also https://www.youtube.com/watch?v=VQKq9RHMS_0&ab_channel=Stevdza-San i cannot get the data to pass to the new activity.
Main code
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_staff_home);
DB=new mainTextDBHelper(this);
recyclerView=findViewById(R.id.recyclerview);
Title=new ArrayList<>();
description=new ArrayList<>();
radiogroup=new ArrayList<>();
adapter=new recyclerviewAdapter(this,Title,description,radiogroup,listener);
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
displaydata();
setOnClickListner();
private void setOnClickListner() {
listener=new recyclerviewAdapter.RecyclerViewClickListener() {
#Override
public void onClick(View v, int position) {
Intent intent=new Intent(getApplicationContext(),cardviewclickon.class);
intent.putExtra("Title",Title.get(position));
startActivity(intent);
}
};
}
private void displaydata() {
Cursor cursor=DB.getdata();
if(cursor.getCount()==0){
Toast.makeText(staff_home.this,"No Entry Exists", Toast.LENGTH_SHORT).show();
return;
}else{
while(cursor.moveToNext())
{
Title.add(cursor.getString(1));
description.add(cursor.getString(2));
radiogroup.add(cursor.getString(3));
}
}
}
recyclerview Adapter code
public class recyclerviewAdapter extends RecyclerView.Adapter<recyclerviewAdapter.MyViewHolder>{
private Context context;
private ArrayList Title_id,description_id,radiogroup_id;
private RecyclerViewClickListener listener;
public recyclerviewAdapter(Context context, ArrayList title_id, ArrayList description_id, ArrayList radiogroup_id,RecyclerViewClickListener listener) {
this.context = context;
Title_id = title_id;
this.description_id = description_id;
this.radiogroup_id = radiogroup_id;
this.listener=listener;
}
#NonNull
#Override
public recyclerviewAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.userentry,parent,false);
return new MyViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull recyclerviewAdapter.MyViewHolder holder, int position) {
holder.Title_id.setText(String.valueOf(Title_id.get(position)));
holder.description_id.setText(String.valueOf(description_id.get(position)));
holder.radiogroup_id.setText(String.valueOf(radiogroup_id.get(position)));
holder.cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent=new Intent(context,cardviewclickon.class);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return Title_id.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView Title_id,description_id,radiogroup_id;
CardView cardView;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
Title_id=itemView.findViewById(R.id.textTitle);
description_id=itemView.findViewById(R.id.textdescription);
radiogroup_id=itemView.findViewById(R.id.textsrverity);
cardView=itemView.findViewById(R.id.card);
new View.OnClickListener() {
#Override
public void onClick(View view) {
listener.onClick(view,getAdapterPosition());
}
};
}
#Override
public void onClick(View view) {
listener.onClick(view,getAdapterPosition());
}
}
public interface RecyclerViewClickListener{
void onClick(View v,int position);
}
}
If you want to pass data from one activity to other you can use PutExtra() method of the Intent class As I can see you are doing everything pretty much well but you have to catch these extra from the class you are passing like:- I want to pass data from recyclerView to CardViewClass I can do it like:-
In RecyclerView.java file:-
public void sendDataAndOpen(String title) {
Intent intent = new Intent(getApplicationContext(), CardViewClass.class);
intent.putExtraString("Title",Title); // You can use putExtra to put any datatype
startActivity(intent);
}
In CardViewClass.java file (Lets catch our passing data):-
public void onCreate(...) {
....
String title = getIntent().getExtraString("Title") // You can also use ExtraPut and // Must use Same Id
// Use data as you want
.....
}
This is in Adapter.Java
public void onClick(View v) {
String name=listItemData.get(i).getName();
Intent intent = Intent(MainActivity.this, SecondActivity.class);
intent.putExtra("NAME", name);
}
I have now idea how to use MainActivity.this when I'm not in MainActivity class..
Try following code.
Solution 1
You have to pass context while you initialized Adapter in MainActivity.
In MainActivity.this:
XyzAdapter adapter = new XyzAdapter(MainActivity.this, .. ..)
In your Adapter:
private Context mContext;
public XyzAdapter(Context context .. ..){
mContext = context;
}
And then you can do like below:
public void onClick(View v) {
String name=listItemData.get(i).getName();
Intent intent = Intent(mContext, SecondActivity.class);
intent.putExtra("NAME", name);
mContext.startActivity(intent);
}
Solution 2
Another option is interface
Create one interface like below:
public interface AdapterInterface {
public void buttonPressed();
}
Now in your adapter:
AdapterInterface buttonListener;
public XyzAdapter(Context context, AdapterInterface buttonListener)
{
super(context,c,flags);
this.buttonListener = buttonListener;
}
public void onClick(View v) {
buttonListener.buttonPressed()
}
In your Activity:
AdapterInterface buttonListener;
public MainActivity extends AppCompactActivity implements AdapterInterface{
in onCreate
buttonListener = this;
XyzAdapter adapter = new XyzAdapter(MainActivity.this, buttonListener .. ..)
#Override
public void buttonPressed(){
// here you have to do once your click perform
}
You can have a member variable of type Activity in your Adapter class (e.g. private Activity mActivity;) and pass your MainActivity instance to your Adapter class in the constructor of your Adapter class and assign it to mActivity. Some thing like this:
public Adapter(Activity activity) {
this.mActivity = activity;
}
Then in your onClick method:
public void onClick(View v) {
String name=listItemData.get(i).getName();
Intent intent = new Intent(mActivity, SecondActivity.class);
intent.putExtra("NAME", name);
mActivity.startActivity(intent);
}
why can't I contact the second page
This is inside my Adapter
holder.btn_filter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (position == 1)
{
ShowMessages showMessages = new ShowMessages();
showMessages.message();
}
}}
Home Activity
public class ShowMessages extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_messages);
}
public void message()
{
Toast.makeText(this, "hola", Toast.LENGTH_SHORT).show();
//or set text or change adapter etc...
}
}
When called with message() inside adapter comes out of the application why ?
I see that ShowMessages is an activity here and when you try to instantiate an activity through new, the context is null. Always use intents to create new activities. If you want to trigger some method in the activity from the adapter, pass the activity to the adapter as the constructor argument, cache it in the adapter and then use it to call message().
Something like this would do:
ShowMessages.java - adapter initialization in activity:
MyAdapter adapter = new MyAdapter(this);
MyAdapter.java:
private Activity activity;
MyAdapter(ShowMessages activity) {
this.activity = activity;
}
And then in your adapter:
holder.btn_filter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (position == 1)
{
activity.message();
}
}}
Also, you are being memory efficient here, as you are not instantiating a new activity for every click at position 1.
I am new to development field. I am developing android application where in my activity_main layout I have many different items. On clicking one of the button the top layout is replaced with a new layout.
Now instead of defining the new layouts buttons, textview etc in my main class , I want to have a separate class which can initialize my buttons etc, and also in that class I can declare onClickListners.
In my main Activity I want:-
public void onCreate(){
button bb = (Button)findViewById(R.id.mybutton);
View CurrentContentView= getLayoutInflater().inflate(R.layout.activity_main, null, false);
bb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new MyNewViewInit(CurrentContentView);
}
});
}
In my MyNewViewInit() class :-
public class MyNewViewInit{
ImageButton backbutton;
ChipsMultiAutoCompleteTextview search;
ImageButton searchclear;
ImageButton modeTime;
ImageButton modeTag;
TextView modeTimeTxt;
TextView modeTagTxt;
ScrollView mainScroll;
ScrollView selectedScroll;
public MyNewViewInit(View v){
backbutton = (ImageButton)v.findViewById(R.id.backbutton);
search = (ChipsMultiAutoCompleteTextview)v.findViewById(R.id.search);
searchclear = (ImageButton)v.findViewById(R.id.searchclear);
modeTime = (ImageButton)v.findViewById(R.id.modeTime);
modeTag = (ImageButton)v.findViewById(R.id.modeTag);
modeTimeTxt = (TextView)v.findViewById(R.id.modeTimeTxt);
modeTagTxt = (TextView)v.findViewById(R.id.modeTagTxt);
mainScroll = (ScrollView)v.findViewById(R.id.HAT1);
selectedScroll = (ScrollView)v.findViewById(R.id.HAT2);
tag = new OtherHelper().arrayread();
mainHashTag.setVisibility(View.GONE);
selectedHashTag.setVisibility(View.GONE);
clickListners();
}
public void clickListners(){
backbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
searchclear.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
modeTime.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
modeTimeTxt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
modeTag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
modeTagTxt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
}
}
So when I try using this code the onclicklistners are not working.
What is the best way to do this.
Thanks
Write an Interface in your class,
class MyNewViewInit{
public interface ClickListenerInterface{
void onCLickSomething(Something something);
}
ClickListenerInterface mClickListener;
...
public MyNewViewInit(View v,ClickListenerInterface clickListener){
mClickListener = clickListener;
...
}
public void clickListners(){
...
backbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(mClickListener!=null){
mClickListener.onCLickSomething(v);
}else{
//throw an error that activity should implement ClickListenerInterface
}
}
});
}
}
In your Activity,
class MyActivity extends Activity implements ClickListenerInterface{
public void onCreate(){
bb.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new MyNewViewInit(CurrentContentView,this);
//if using Android Studio, then use the context menu to implement the interface
}
});
}
void onCLickSomething(Something something){
//do something with something
}
}
You can try do a abstract class extends Activity, like :
public abstract class MyInitActivity extends Activity
{
EditText editText;
TextView textView;
#Override
public void setContentView(int layoutResID)
{
super.setContentView(layoutResID);
editText = (EditText)findViewById(R.id.editText);
textView = (TextView)findViewById(R.id.textView);
}
}
and in your main activity you can extend your abstract class, like :
public class MainActivity extends MyInitActivity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/*********** Listener ************/
public void onButtonClick(View v)
{
textView.setText(editText.getText().toString());
}
}
you can also implement onClick() in the abstract class
i don't know if its a good practice , i prefer do the methods with view arguments and set this methods in the layout.xml file .
I had use this in one of code
STEP 1
Declare button in layout(XML file)
STEP 2
Declare all ur button like this--
Button btn1 = (Button)findViewById(R.id.btn1);
Button btn2 = (Button)findViewById(R.id.btn2);
Button btn3 = (Button)findViewById(R.id.btn3);
............so on
STEP 3
implement View.OnClickListener
Now after step 2 do this
btn1.setOnClickListener(this);
.
.
.
same way for all
STEP 4:
Use switch case inside Onclick
public void OnClick(View v)
{
case:R.id.btn1{
//ur command similarly use multiple case stmt for many button
}
}
I'm trying to build an App for Android Lollipop (5.0). There is a login fragment and when i press login button then app automatically crashes. I'm sharing my code and error message please guide me.
BaseActivity.java
public abstract class BaseActivity extends AppCompatActivity {
protected CoreApplication coreApplication;
#Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
coreApplication = (CoreApplication) getApplication();
}
}
BaseAuthenticatedActivity.java
public abstract class BaseAuthenticatedActivity extends BaseActivity {
#Override
protected final void onCreate(Bundle savedState) {
super.onCreate(savedState);
if (!coreApplication.getAuth().getUser().isLoggedIn()) {
startActivity(new Intent(this, LoginActivity.class));
finish();
return;
}
onCoreApplicationCreate(savedState);
}
protected abstract void onCoreApplicationCreate(Bundle savedState);
}
LoginActivity.java
public class LoginActivity extends BaseActivity implements View.OnClickListener, LoginFragment.CallBacks {
private static final int REQUEST_NARROW_LOGIN = 1;
private View loginButton;
#Override
protected void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.activity_login);
loginButton = findViewById(R.id.LoginJustChat);
if (loginButton != null) {
loginButton.setOnClickListener(this);
}
}
#Override
public void onClick(View view) {
if (view == loginButton)
startActivityForResult(new Intent(this, LoginNarrowActivity.class), REQUEST_NARROW_LOGIN);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK)
return;
if (requestCode == REQUEST_NARROW_LOGIN) {
finishLogin();
}
}
private void finishLogin() {
startActivity(new Intent(this, MainActivity.class));
finish();
}
#Override
public void onLoggedIn() {
finishLogin();
}
}
LoginNarrowActivity.java
public class LoginNarrowActivity extends BaseActivity implements LoginFragment.CallBacks {
#Override
protected void onCreate(Bundle savedState){
super.onCreate(savedState);
setContentView(R.layout.activity_login_narrow);
}
#Override
public void onLoggedIn() {
setResult(RESULT_OK);
finish();
}
}
MainActivity.java
public class MainActivity extends BaseAuthenticatedActivity {
#Override
protected void onCoreApplicationCreate(Bundle savedState) {
}
}
BaseFragment.java
public abstract class BaseFragment extends Fragment {
protected CoreApplication application;
#Override
public void onCreate(Bundle savedInstance) {
super.onCreate(savedInstance);
application = (CoreApplication) getActivity().getApplication();
}
}
LoginFragment.java
public class LoginFragment extends BaseFragment implements View.OnClickListener {
private Button loginButton;
private CallBacks callBacks;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup root, Bundle savedState) {
View view = inflater.inflate(R.layout.fragment_login, root, false);
loginButton = (Button) view.findViewById(R.id.fragment_login_loginButton);
loginButton.setOnClickListener(this);
return view;
}
#Override
public void onClick(View view) {
if (view == loginButton) {
application.getAuth().getUser().setIsLoggedIn(true);
callBacks.onLoggedIn();
}
}
// because onAttach(Activity activity) is deprecated
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof CallBacks) {
callBacks = (CallBacks) context;
} else {
throw new ClassCastException(context.toString()
+ " must implement MyListFragment.OnItemSelectedListener");
}
}
#Override
public void onDetach() {
super.onDetach();
callBacks = null;
}
public interface CallBacks {
void onLoggedIn();
}
}
Error:
java.lang.NullPointerException: Attempt to invoke interface method
'void
com.example.usama.demoapp.fragments.LoginFragment$CallBacks.onLoggedIn()'
on a null object reference
Please guide me with this.
Welcome to Android !
You got a NullPointerException. It's a very common [and lovely; since it's rather easy to debug] exception in Java. Check your LoginFragment. The following method will cause this exception to raise.
#Override
public void onClick(View view) {
if (view == loginButton) {
application.getAuth().getUser().setIsLoggedIn(true);
callBacks.onLoggedIn();
}
}
A couple of notes in order to diagnose this error:
When you declare a class member with initializing it, in this casecallBacks, Java automatically initialize it to null.
Invoking any method on a null reference will result in NPE.
Okay, let's narrow down to your specific case. You declared a class member called callBacks but never initialized it, as well as, I can see no methods that assign something to it. Therefore, that class member always remains null and thereby any subsequent method invocation on it leads us to NPE.
As a solution, you should add a setter method to your LoginFragment class in which you set that callBacks. In other side supply this object where you first create an instance of this fragment.
Update #1
when i pass Activity instead of Context as parameter in onAttach method it works. but i want to know why it is causing the error?
The why is simple. Since your activity already implemented that interface, so passing it to your LoginFragment as context will result in the condition if (context instanceof CallBacks) becoming true. However, passing bare context won't result in establishment of that if statement.
can u please tell me how i can define setter?
It's pretty simple! Just as other regular method, declare a method like this:
public void setOnLoginListener(Callbacks listener){
this.callbacks = listener;
}
Update #2
where i need to define setOnLoginListener method
Inside the LoginFragment class.
and where should i call it
In your main activity where you first instantiate LoginFragment class.
with what parameters?
Your activity, which implements that Java interface.
You can avoid setting onClickListener for the button by having adding android:onClink="login" in your xml file and a function that looks like this in your java file:
public void login(View view) {
application.getAuth().getUser().setIsLoggedIn(true);
callBacks.onLoggedIn();
}
You can try writing a public setter for the callBacks object in LoginFragment and setting it from the activity instead, like this, supposing you defined your fragment in the activity's layout file:
public class LoginNarrowActivity extends BaseActivity implements LoginFragment.CallBacks {
#Override
protected void onCreate(Bundle savedState){
super.onCreate(savedState);
setContentView(R.layout.activity_login_narrow);
LoginFragment loginFragment = (LoginFragment)getSupportFragmentManager().findFragmentById(R.id.your_fragment_id);
loginFragment.setCallBacks(this);
}
Actually the error was here in onAttach(Context context) when i pass Activity like this onAttach(Activity activity) then it worked. But i want to know why it is causing the error? and onAttach(Activity activity) is deprecated in android 5.0