RecyclerView showing item only when editing the next item to be added - java

I'm currently building an activity in my app where products are added using a FAB. Clicking the FAB opens a new pop-up activity with startActivityForResult, and in it a form is filled and sent back via a Parcelable object.
The problem I'm facing right now is that after adding a product it is not displayed in the RecyclerView, but when I click the FAB again, the second I start editing any field inside the form (meaning any EditText, for example) for the next product, I see the previous one appearing in the background behind my pop-up form. When I finish the second product, it won't appear until I start editing the third one, etc.
I went through the XML and it seems OK to me... And tried reading several solutions (and my code again and again) but none of them were really helpful.
Relevant pieces of code (I put ... where I neglected some code that's irrelevant for this case):
From the main activity (in it the products are meant to be shown):
'''
public class EditOffersActivity extends AppCompatActivity {
...
private ArrayList<Offer> offers_list;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_products);
offers_list = new ArrayList<>();
...
RecyclerView rvOffers = findViewById(R.id.offers_RecyclerView);
OfferAdapter adapter = new OfferAdapter(offers_list);
rvOffers.setAdapter(adapter);
rvOffers.setLayoutManager( new LinearLayoutManager(this));
// Setting up the FAB so it leads to the Product Details Pop-up
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(EditOffersActivity.this, ProductDetailsPopupActivity.class);
startActivityForResult(intent, HTZ_ADD_OFFER); // HTZ_ADD_OFFER = 1
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Offer created_offer = data.getParcelableExtra("offer");
offers_list.add(created_offer);
}
}
'''
The Adapter:
'''
public class OfferAdapter extends android.support.v7.widget.RecyclerView.Adapter<OfferAdapter.OfferViewholder> {
private ArrayList<Offer> mOffers;
public OfferAdapter(ArrayList<Offer> offers) {
mOffers = offers;
}
#Override
public OfferViewholder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
Context context = viewGroup.getContext();
int layoutIdForListItem = R.layout.item_product;
LayoutInflater inflater = LayoutInflater.from(context);
View view = inflater.inflate(layoutIdForListItem, viewGroup, false);
OfferViewholder viewHolder = new OfferViewholder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(OfferViewholder holder, int position) {
Offer current_offer = mOffers.get(position);
... // a lot of binding code
}
#Override
public int getItemCount() {
return mOffers.size();
}
class OfferViewholder extends RecyclerView.ViewHolder {
TextView name_TextView;
TextView time_TextView;
...
public OfferViewholder(View itemView) {
super(itemView);
// Init all views
name_TextView = itemView.findViewById(R.id.product_item_name_TextView);
time_TextView = itemView.findViewById(R.id.product_item_time_TextView);
...
}
}
}
'''
And the bit from the popup activity that closes it after the user click 'finished':
'''
mPublishButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(p_photo_url == null) {
...
} else {
// Create offer from user input
Offer n_offer = new Offer (...)
);
...
// Return offer to EditOffersActivity
Intent resultIntent = new Intent();
resultIntent.putExtra("offer", n_offer); // Offer is Parcelable
setResult(HTZ_ADD_OFFER, resultIntent);
finish();
}
}
});
'''
And the RecyclerView's XML:
<android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/offers_RecyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
tools:itemCount="3"
tools:listitem="#layout/item_product"
tools:orientation="vertical"
tools:scrollbars="horizontal"
tools:spanCount="1">

you can use notifydatasetchanged as below code :
mPublishButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(p_photo_url == null) {
...
} else {
// Create offer from user input
Offer n_offer = new Offer (...)
);
...
// Return offer to EditOffersActivity
Intent resultIntent = new Intent();
resultIntent.putExtra("offer", n_offer); // Offer is Parcelable
setResult(HTZ_ADD_OFFER, resultIntent);
OfferAdapter.notifydatasetchanged();
finish();
}
}
});
OfferAdapter.notifydatasetchanged();// method will refresh the adapter which is set on your view. and the values will be refresh.
Don't forget to appreciate and like the answer.

Add a method on your adapter like this:
public void update(ArrayList<Offer> offers){
mOffers = offers;
}
Update your onActivityResult and notify adapter like this:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
Offer created_offer = data.getParcelableExtra("offer");
offers_list.add(created_offer);
adpater.update(offers_list);
adapter.notifydatasetchanged();
}

after adding to ArrayList You Have to notify changes to Adaptor by calling RecyclerViewAdapter's notifydatasetchanged()
like:
adapter.notifydatasetchanged()

Related

How to pass data from a activity to a recycler view adapter in android

I'm trying to design a page where address are stored in recycler view -> cardview.
When the user clicks the add address button from the Activity A the user is navigated to the add address page in Activity B. Here the user can input customer name, address line 1 and address line two.
And once save button is clicked in Activity B, a cardview should be created under the add address button in the Activity A.
This design is just like the amazon mobile app add address option.
Could anyone give me an example hoe to pass the saved data from activity to recycler adapter. I know how to pass data from recycler adapter to activity with putExtra etc..
Kindly help me. Million Thanks in advance!
Code In Activity A(Where the Add address button is available and where the recycler view is present)
public class ProfileManageAdressFragment extends AppCompatActivity {
RecyclerView recyclerView;
ProfileManageAddressRecyclerAdapter adapter;
ArrayList<ProfileManageAddressGetterSetter> reviews;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_profile_manage_adress);
Button addAddress = findViewById(R.id.addNewAddress);
reviews = new ArrayList<>();
addAddress.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(), "Clicked", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(ProfileManageAdressFragment.this, AddNewAddress.class);
startActivity(intent);
}
});
}
}
Piece of Code that is responsible for adding a card view in Activity A. Kindly let me know how to invoke this below code on button click in Activity
reviews.add(new ProfileManageAddressGetterSetter("Customer Name", "address line 1", "address line 2"));
recyclerView = findViewById(R.id.addressRecyclerView);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(ProfileManageAdressFragment.this));
adapter = new ProfileManageAddressRecyclerAdapter(this, reviews);
recyclerView.setAdapter(adapter);
Code in the Recycler adapter
public class ProfileManageAddressRecyclerAdapter extends RecyclerView.Adapter<ProfileManageAddressRecyclerAdapter.ViewHolder> {
private ArrayList<ProfileManageAddressGetterSetter> mDataset = new ArrayList<>();
private Context context;
public static class ViewHolder extends RecyclerView.ViewHolder {
private TextView customer_name, address_one, address_two;
private Button edit, remove;
public ViewHolder(View v) {
super(v);
customer_name = (TextView) v.findViewById(R.id.customerName);
address_one = (TextView) v.findViewById(R.id.addressLineOne);
address_two = v.findViewById(R.id.addressLineTwo);
}
}
public ProfileManageAddressRecyclerAdapter(View.OnClickListener profileManageAdressFragment, ArrayList<ProfileManageAddressGetterSetter> dataset) {
mDataset.clear();
mDataset.addAll(dataset);
}
#Override
public ProfileManageAddressRecyclerAdapter.ViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_manage_address, parent, false);
ProfileManageAddressRecyclerAdapter.ViewHolder vh = new ProfileManageAddressRecyclerAdapter.ViewHolder(view);
return vh;
}
#Override
public void onBindViewHolder(#NonNull ProfileManageAddressRecyclerAdapter.ViewHolder holder, int position) {
ProfileManageAddressGetterSetter profileManageAddressGetterSetter = mDataset.get(position);
holder.address_one.setText(profileManageAddressGetterSetter.getAddress_line_1());
holder.address_two.setText(profileManageAddressGetterSetter.getGetAddress_line_2());
holder.customer_name.setText(profileManageAddressGetterSetter.getContractor_name());
}
#Override
public int getItemCount() {
return mDataset.size();
}
}
enter image description here - After trying the call from adapter using intent as mentioned above ended up with a 0.
Code in the Activity B
public class AddNewAddress extends AppCompatActivity {
private EditText customer_name, address_one, address_two;
private TextView cancel;
private Button add_address;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_new_address);
customer_name = findViewById(R.id.customerName);
address_one = findViewById(R.id.addressOne);
address_two = findViewById(R.id.addressTwo);
add_address = findViewById(R.id.addAddress);
cancel = findViewById(R.id.completeCancel);
String cancel_text = "Cancel";
SpannableString spanableObject = new SpannableString(cancel_text);
ClickableSpan clickableSpan = new ClickableSpan() {
#Override
public void onClick(View widget) {
Toast.makeText(AddNewAddress.this, "Clicked", Toast.LENGTH_SHORT).show();
}
#Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(Color.BLUE);
}
};
spanableObject.setSpan(clickableSpan, 0, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
cancel.setText(spanableObject);
cancel.setMovementMethod(LinkMovementMethod.getInstance());
final ProfileManageAdressFragment profileManageAdressFragment = new ProfileManageAdressFragment();
add_address.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(AddNewAddress.this, ProfileManageAdressFragment.class);
startActivity(intent);
}
});
}
private void setFragment(android.support.v4.app.Fragment fragment) {
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.main_frame, fragment).commit();
}
}
Update 1:
Kindly check my updated Recycler adapter. When I run this 0 is displayed in the text area as shown in the attached image. I'm new to android. Kindly help with example.
I finally achieved my goal with the use of ActivityResult. Now I'm able to pass data from Activity to Cardview.
Solution: When button is clicked in Activity A, I start the activity with startResultActivity(). Later, when the Activity B i triggered. The end-user inputs the data and that data is passed with the use of putExtra() and once the save button is clicked in Activity B next setResult() in Activity B and finish().
Finally i define onActivityResult() in Activity A to get the result. Works well!!
I would create a global variable and then store all the data in that variable and simply just call that variable in adapter.
declare a global variable and assign null value to it:
public static String checking = null;
a then store data in when you need it:
checking = check.getText().toString();
then call it in your adapter class.
first make interface listener inside listener make function with parameter like this
interface YourRecycleViewClickListener {
fun onItemClickListener(param1:View, param2: String)
}
now extend your activity
class YourActivity:YourRecycleViewClickListener{
override fun onItemClickListener(param1:View, param2: String) {
//do any thing
}
}
third step make interface constract in your recycle adapter
class YourAdapter(
private val listener: YourRecycleViewClickListener){
holder.constraintLayout.setOnClickListener{
listener.onItemClickListener(param1,param2)
}
}
this is by kotlin lang
and by java is same but change syntax
that all to do

RecyclerView - Get the selected position and pass the position to another activity where the same list will appear with that specific item selected

I have declared a ViewModel.class for the RecyclerView an Adapter and I have parsed to the MainActivity and to another Activity so I have the same adapter for both activities.
I can show the parsed data in both activities but the problem it is I cannot take the data of the selected item to MainActivity and then to set to that btnSearch for a click so then I can share between activities the data from the selected item.
Every time when the app is open the first item is selected. What I am trying to achieve is.
Get the item position to the MainActivity so when I click for a button search the data of the selectedItem will going to intent.putExtra and then get the data at another Activity.
If I click the second item and go to another Activity the same item will be selected.
Here is what I have tried so far.
The SearchEngineAdapter.class
public class SearchEngineAdapter extends RecyclerView.Adapter<SearchEngineAdapter.ViewHolder> {
private int selectedItem = 0;
private static RecyclerViewClickListener itemListener;
private Context context;
ArrayList<SearchEngine> arrayList = new ArrayList<>();
public SearchEngineAdapter(Context context, ArrayList<SearchEngine> arrayList, int selectedItem) {
this.context = context;
this.arrayList = arrayList;
this.selectedItem = selectedItem;
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int i) {
holder.tvIcon.setImageResource(arrayList.get(i).getIcon());
holder.tvId.setText(arrayList.get(i).getId());
holder.tvSearchUrl.setText(arrayList.get(i).getUrl());
final String url = holder.tvSearchUrl.getText().toString();
SharedPreferences sp = context.getSharedPreferences("SavedSelected", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sp.edit();
editor.putInt("selected", selectedItem);
editor.apply();
sp = context.getSharedPreferences("SavedSelected", Context.MODE_PRIVATE);
int myIntValue = sp.getInt("selected", -1);
Log.d("Selected", "SharedPreferences" + myIntValue);
if (selectedItem == i) {
holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
Intent intent = new Intent("search_engines");
intent.putExtra("url", url);
intent.putExtra("selected", selectedItem);
LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
} else {
holder.tvIcon.setBackgroundColor(Color.parseColor("#00000000"));
}
holder.tvIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent("search_engines");
intent.putExtra("url", url);
int PreviousSelectedItem = selectedItem;
selectedItem = i;
intent.putExtra("selected", selectedItem);
holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
notifyItemChanged(PreviousSelectedItem);
notifyDataSetChanged();
}
});
}
// ... Other necessary functions.
}
Now the MainActivity.class
RecyclerView paramRecyclerView;
SearchEngineAdapter sEngineAdapter;
paramRecyclerView = findViewById(R.id.lvEngines);
paramRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
paramRecyclerView.setHasFixedSize(true);
Intent intent = getIntent();
int intValue = intent.getIntExtra("selected", 0);
sEngineAdapter = new SearchEngineAdapter(context, arrayList, intValue);
paramRecyclerView.setAdapter(sEngineAdapter);
// Calling network APIs to populate the arrayList.
The onResume function of the MainActivity looks like the following.
protected void onResume() {
super.onResume();
searchPlugin.setText("");
getChangeColor();
}
This is the click handler defined in MainActivity which send me to another Activity.
btnSearch.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String newEntry = searchPlugin.getText().toString();
AddHistory(newEntry);
getFragmentRefreshListener().onRefresh();
Intent intent = new Intent(MainActivity.this, ActivitySearchEngine.class);
intent.putExtra("url", url );
intent.putExtra("name", newEntry);
intent.putExtra("selected", selectedItem2);
startActivity(intent);
}
});
And the other activity which is ActivitySearchEngine.class
public class ActivitySearchEngine extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {
public String selectedName;
public int selectedID;
public String selectedSearchUrl;
RecyclerView mListView;
RecyclerView paramRecyclerView;
SearchEngineAdapter sEngineAdapter;
ArrayList<SearchEngine> arrayList = new ArrayList<>();
final Context context = this;
int selectedItem;
#SuppressLint("SetJavaScriptEnabled")
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_result);
// Variables initialization
// Setting up adapter
paramRecyclerView.setAdapter(sEngineAdapter);
sEngineAdapter.notifyDataSetChanged();
// Calling network APIs to populate the arrayList here
Intent receivedIntent = getIntent();
selectedName = receivedIntent.getStringExtra("name");
selectedID = receivedIntent.getIntExtra("id", 1); //NOTE: -1 is just the default value
selectedSearchUrl = receivedIntent.getStringExtra("url");
// Loading the url in a WebView for searching
}
}
I could share the selected item position between these two activities. However, I am not sure how to achieve the behavior of the item is being selected in the RecyclerView of the second activity as well. If I select another item in the RecyclerView of the second activity, the change should be reflected in the first (i.e. MainActivity) as well when I get back to it.
Any help would be appreciated.
There was a lot of changes in the question and hence the last update of this answer below is the final version.
As far as I could understand about the problem, I can see you are very close to the solution if I had understood correctly. The SearchEngineAdapter already has a selectedItem variable in it which can be used for highlighting the item selected in ActivitySearchEngine as well. You just have to modify the adapter a little bit like the following. I am rewriting the adapter here.
public class SearchEngineAdapter extends RecyclerView.Adapter<SearchEngineAdapter.ViewHolder> {
private int selectedItem = 0;
private static RecyclerViewClickListener itemListener;
private Context context;
ArrayList<SearchEngine> arrayList = new ArrayList<>();
// Added another argument to be passed in the constructor
public SearchEngineAdapter(Context context, ArrayList<SearchEngine> arrayList, int selectedItem) {
this.context = context;
this.arrayList = arrayList;
this.selectedItem = selectedItem;
}
#NonNull
#Override
public SearchEngineAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(context).inflate(R.layout.s_engine_item, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int i) {
if (selectedItem == i) {
holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
} else {
holder.tvIcon.setBackgroundColor(Color.parseColor("#00000000"));
}
holder.tvIcon.setImageResource(arrayList.get(i).getIcon());
holder.tvId.setText(arrayList.get(i).getId());
holder.tvSearchUrl.setText(arrayList.get(i).getUrl());
holder.tvIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int PreviousSelectedItem = selectedItem;
selectedItem = i;
holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
notifyItemChanged(PreviousSelectedItem);
notifyDataSetChanged();
}
});
}
#Override
public int getItemCount() {
return arrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView tvId, tvSearchUrl;
ImageView tvIcon;
public ViewHolder(#NonNull View itemView) {
super(itemView);
tvId = itemView.findViewById(R.id.ivEngineText);
tvIcon = itemView.findViewById(R.id.ivEngine);
tvSearchUrl = itemView.findViewById(R.id.ivSearchUrl);
}
}
}
Check that, I just have modified the constructor of your adapter, taking another extra variable which is selectedItem. Just pass the selected item position when you are initializing the adapter in both activities. In the default case, you can pass -1, I think you get the idea.
You have passed the selected item position to the ActivitySearchEngine as well. Which can be used for initializing for the desired behavior. Hope that helps!
Update 1:
I would like to suggest you put the following code to your onResume function in the ActivitySearchEngine class. You might consider removing the lines from the onCreate function of your code as well.
#Override
public void onResume() {
super.onResume();
Intent receivedIntent = getIntent();
selectedName = receivedIntent.getStringExtra("name");
selectedID = receivedIntent.getIntExtra("id", 1); // NOTE: -1 is just the default value
selectedSearchUrl = receivedIntent.getStringExtra("url");
sEngineAdapter = new SearchEngineAdapter(context, arrayList, selectedID);
paramRecyclerView.setAdapter(sEngineAdapter);
}
Update 2:
The RecyclerView in your MainActivity is getting reloaded as you are setting the adapter again to the RecyclerView in the onResume function. Moreover, you are trying to get data from intent which is not available here I think because you have not set any data to be sent to the MainActivity when you return back from the ActivitySearchEngine. Hence, the RecyclerView is reloading again with a fresh set of data.
You might remove the code associated with your RecyclerView from the onResume function of the MainActivity to remove this complication as I think this is not necessary. So the updated onResume function will look like the following.
protected void onResume() {
super.onResume();
searchPlugin.setText("");
getChangeColor();
}
Update 3:
Take a public static variable in your MainAcitivity and declare it as a global variable like the following.
// Setting 0 as you wanted to put the first item at the first time
// If you do not want that, then initialize with -1
public static int selectedItem = 0;
Now inside your onCreate function, remove the lines for getting the intent.
paramRecyclerView = findViewById(R.id.lvEngines);
paramRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
paramRecyclerView.setHasFixedSize(true);
// Remove the following
// Intent intent = getIntent();
// int intValue = intent.getIntExtra("selected", 0);
// Move the adapter setup to the onResume
// sEngineAdapter = new SearchEngineAdapter(context, arrayList, selectedItem);
// paramRecyclerView.setAdapter(sEngineAdapter);
// Calling network APIs to populate the arrayList.
Modify the onResume function in the MainActivity to set up the adapter there.
protected void onResume() {
super.onResume();
searchPlugin.setText("");
getChangeColor();
// Set the adapter here
sEngineAdapter = new SearchEngineAdapter(context, arrayList, selectedItem);
paramRecyclerView.setAdapter(sEngineAdapter);
}
Modify the onClickListener in your adapter like the following. Just add a new line there.
holder.tvIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent("search_engines");
intent.putExtra("url", url);
int PreviousSelectedItem = selectedItem;
selectedItem = i;
// Set the static value in the MainActivity
// This can be accessed from all other classes
MainActivity.selectedItem = i;
intent.putExtra("selected", selectedItem);
holder.tvIcon.setBackgroundColor(Color.parseColor("#30000000"));
notifyItemChanged(PreviousSelectedItem);
notifyDataSetChanged();
}
});
Hope that helps!

OnClickListener in RecyclerView (ImageView)

I am trying to do this. In the CardView of a RecyclerView, if you tap on the image, a new activity must open with a bigger version of the image. Like tapping on the image of the profile pic of Whatsapp.
So a I thought I will do it with a OnClicklisterner on the Image.
I get this error message while running it:
error: incompatible types: cannot be converted to Activity
Some help would really be appreciated, I am still new to Android and Java, and I am a bit stuck.
Here is the code I've tried so far:
#Override
public void onBindViewHolder(final MyViewTwoHolder holder, int position) {
holder.tvBrand.setText((CharSequence) modelTwoArrayList.get(position).getBrand());
holder.tvImage.setImageResource(Integer.parseInt(String.valueOf(modelTwoArrayList.get(position).getImage())));
holder.tvImage.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, modelTwoArrayList.get(position).getImage());
Intent i = new Intent(view.getContext(), DetailsActivity.class);
view.getContext().startActivity(i, options.toBundle());
}
});
The position in this line gives me the problem:
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, modelTwoArrayList.get(position).getImage());
Thank you for your time in advance.
My code now:
#Override
public void onBindViewHolder(final MyViewTwoHolder holder, int position) {
holder.tvBrand.setText((CharSequence) modelTwoArrayList.get(position).getBrand());
holder.tvImage.setImageResource(Integer.parseInt(String.valueOf(modelTwoArrayList.get(position).getImage())));
holder.tvImage.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation((Activity) ctx, holder.tvImage, "imageAnimation");
Intent i = new Intent(ctx, DetailsActivity.class);
i.putExtra("image_url", String.valueOf(holder.tvImage));
ctx.startActivity(i, options.toBundle());
}
});
And my DetailsActivity:
public class DetailsActivity extends AppCompatActivity {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.details_activity);
getIncomingIntent();
}
private void getIncomingIntent(){
String imageUrl = getIntent().getStringExtra("imageAnimation");
setImage(imageUrl);
}
private void setImage(String imageUrl){
ImageView image = findViewById(R.id.beer_logo);
}}
1) Make sure that your first parameter this is reference of Activity.
2) Make sure that your second parameter modelTwoArrayList.get(position).getImage() is ImageView of list. It seems that this is not so. It must be like this holder.tvImage
3) Provide third string parameter "imageAnimation"
All in all your code will be look something like this
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(MyActivity.this, holder.tvImage, "imageAnimation");
Intent i = new Intent(MyActivity.this, DetailsActivity.class);
MyActivity.this.startActivity(i, options.toBundle());
You are having problem because ActivityOptions.makeSceneTransitionAnimation is expecting an Activity but when you do this you are giving it your Adapter.
To solve the problem change the constructor of your adapter to take the activity in
MyAdapter(Context context,Arg1,Arg2){
this.myActivityContext = context;
... other stuffs
}
Then when you initialise adapter in your Activity
MyAdapter myAdapter = new MyAdapter(this,arg1,arg2)
Then
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(myActivityContext, modelTwoArrayList.get(position).getImage());

How to create an interface to get info from a Fragment to an Android Activity?

Over the past days I've desperately been trying to build an android app with a simple fragment (which I use twice). I want to pass the contents of the fragments' EditText-boxes to a new activity. I just can't figure out how to get those contents from the fragments. What I have so far is this:
I've got my edit_text_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<EditText
android:id="#+id/my_edit_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="my hint" />
</LinearLayout>
and the corresponding MyEditTextFragment.java:
public class MyEditTextFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.edit_text_fragment, container, false);
return view;
}
}
I then use this fragment twice in my main.xml like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="#+id/detailfragment_placeholder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
class="com.example.fragmenttester5.MyEditTextFragment" />
<fragment
android:id="#+id/detailfragment_placeholder2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
class="com.example.fragmenttester5.MyEditTextFragment" />
<Button
android:id="#+id/submit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Submit all of it" />
</LinearLayout>
and in my MainActivity I hooked up the button to a new activity:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button submitButton = (Button) findViewById(R.id.submit_button);
submitButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v){
Intent intent = new Intent(MainActivity.this, OtherActivity.class);
intent.putExtra("result1", "the_result_from_the_first_editText");
intent.putExtra("result2", "the_result_from_the_second_editText");
startActivity(intent);
}
});
}
}
I think I now need to define some kind of interface in the Fragment, but I can't find how. I read a couple examples and tutorials (like this one), but they make no sense to me at all. I don't understand the code given and I just don't understand how to adjust it for my use case.
So my question; can anybody help me to get the contents of the fragment from within the activity? Examples would be very very welcome since I'm just banging my head against the wall here..
You are right, that's kind of a standard way to pass data from a Fragment to an activity.
Basically you define a Listener interface which the Activity implements, and the Activity registers itself as a Listener with the Fragment.
Here's a simple example:
Fragment
class MyFragment extends Fragment {
interface Listener {
public void somethingHappenedInFragment(Object... anyDataYouWantToPassToActivity);
}
private Listener mListener;
public void setListener(Listener listener) {
mListener = listener;
}
// ... your code ...
// Now here you pass the data to the activity
mListener.somethingHappenedInFragment(some, data);
// ... more of your code
}
Activity
public MyActivity extends Activity implements MyFragment.Listener {
// ... your code ...
// creating the Fragment
MyFragment f = new MyFragment();
// register activity as listener
f.setListener(this);
// ... more of your code
// implementation of MyFragment.Listener interface
#Override
public void somethingHappenedInFragment(Object... anyDataYouWantToPassToActivity) {
// here you have the data passed from the fragment.
for (Object o : anyDataYouWantToPassToActivity {
System.out.println(o.toString();
}
}
}
On a high level, there are two tasks that you commonly need to solve with Fragments. The first is communicating data from an Activity to a Fragment. The second is communicating data from a Fragment to an Activity.
An Activity knows which Fragments it contains since it creates them, so it's easy to communicate that way - just call methods on the Fragment itself. But the inverse is not true; Fragments might be attached to any number of random Activities, so it doesn't know anything about it's parent.
The solution is to implement an interface that the Activity implements and the Fragment knows how to communicate with. That way, your Fragment has something it knows how to talk with. There are specific code examples for how to do it here: http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity
(In particular, check out the "Creating event callbacks to the activity" code examples).
So you'd create an Interface to talk with the Activity if the event happened in the Fragment. For situations like this, you can simply make an accessible method in the Fragment that the Activity can call. So
public class MyEditTextFragment extends Fragment {
private EditText mEditText;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.edit_text_fragment, container, false);
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mEditText = (EditText) getView().findViewById(R.id.my_edit_text);
}
public Editable getText() {
return mEditText.getText();
}
}
Then
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MyEditTextFragment fragment1 = (MyEditTextFragment)
getFragmentManager().findFragmentById(R.id.detailfragment_placeholder);
final MyEditTextFragment fragment2 = (MyEditTextFragment)
getFragmentManager().findFragmentById(R.id.detailfragment_placeholder2);
Button submitButton = (Button) findViewById(R.id.submit_button);
submitButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v){
String firstResult = fragment1.getText().toString();
String secondResult = fragment2.getText().toString();
Intent intent = new Intent(MainActivity.this, OtherActivity.class);
intent.putExtra("result1", firstResult);
intent.putExtra("result2", secondResult);
startActivity(intent);
}
});
}
}
This assumes that you assigned the Fragment tags in your FragmentTransaction. Be sure to check for null Fragments (omitted for brevity)
Activity will be received data from updateDetail() method in Fragment
//// Activity
public class RssfeedActivity extends Activity implements MyListFragment.OnItemSelectedListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rssfeed);
Button btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d("Annv - Fragment", "onClick here");
}
});
}
// if the wizard generated an onCreateOptionsMenu you can delete
// it, not needed for this tutorial
#Override
public void onRssItemSelected(String link) {
// DetailFragment fragment = (DetailFragment) getFragmentManager()
// .findFragmentById(R.id.detailFragment);
// if (fragment != null && fragment.isInLayout()) {
// fragment.setText(link);
// }
// Intent start = new Intent(this, RssfeedSecondActivity.class);
// startActivity(start);
DetailFragment fragment = (DetailFragment) getFragmentManager()
.findFragmentById(R.id.detailFragment);
if (fragment != null && fragment.isInLayout()) {
fragment.setText(link);
}
}
}
/// Fragment
public class MyListFragment extends Fragment {
private OnItemSelectedListener listener;
private OnItemStartActivityListener listenerStartAct;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_rsslist_overview,
container, false);
Button button = (Button) view.findViewById(R.id.button1);
Log.d("Annv - Fragment", "run on " + getActivity().toString());
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateDetail();
}
});
return view;
}
public interface OnItemSelectedListener {
public void onRssItemSelected(String link);
}
public interface OnItemStartActivityListener {
public void onRssStartActivity(String link);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof OnItemSelectedListener) {
Log.d("Annv - Fragment", "activity " + activity.getLocalClassName());
listener = (OnItemSelectedListener) activity;
} else if (activity instanceof OnItemStartActivityListener) {
Log.d("Annv - Fragment", "activity " + activity.getLocalClassName());
listenerStartAct = (OnItemStartActivityListener) activity;
} else {
throw new ClassCastException(activity.toString()
+ " must implemenet MyListFragment.OnItemSelectedListener");
}
}
// May also be triggered from the Activity
public void updateDetail() {
// create fake data
// String newTime = String.valueOf(System.currentTimeMillis());
// // Send data to Activity
// listenerStartAct.onRssItemSelected(newTime);
if (getActivity() instanceof OnItemSelectedListener) {
listener.onRssItemSelected("start start");
} else {
String newTime = String.valueOf(System.currentTimeMillis());
listenerStartAct.onRssStartActivity(newTime);
}
}
}

Beginner Android: ListView to affect the next class

I am a beginner programmer so please bear with me. I am trying to create an app where the item in the list view affects what will be displayed in the next activity. So far, I have the list activity:
public class Primary extends ListActivity{
private static final String[] items = {"Item1", "Item2", "Item3", "item4", "Item5"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items));
TextView heading =(TextView)findViewById(R.id.listViewHeading);
heading.setText("Primary");
}
public void onListItemClick(ListView parent, View v, int position, long id){
}
and for the second activity, I have this:
public class ImageActivity extends Activity{
TextView heading;
ImageView image;
TextView text;
public static final String[] headings={"heading 1", "heading 2", "heading 3", "heading 4", "heading 5",};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_activity);
heading = (TextView)findViewById(R.id.adHeading);
image = (ImageView)findViewById(R.id.adImage);
text =(TextView)findViewById(R.id.adText);
addInfo();
}
private void addInfo() {
heading.setText(headings[x]);
image.setImageResource(images[x]);
text.setText(text[x]);
}
How can i make it so that the heading, image, and text change based on what item in the list view was selected?
In the listview Activity.
Intent i = new Intent(this, ImageActivity.class);
i.putExtra("data", data);
startActivity(i);
The next Acitivty onCreate() method.
final String data = getIntent().getStringExtra("data");
I think u want to set the heading, image and text in second activity, related to first activity's selected index in list.
just do 1 thing, put following code in 1st activity
public void onListItemClick(ListView parent, View v, int position, long id)
{
Intent intent = new Intent(this.getApplicationContext(), ImageActivity.class);
intent.putExtra("pos", position);
startActivity(intent);
}
so, now u r passing the position of item selected in list.
now, put following code in next activity
private void addInfo()
{
Bundle ext = getIntent().getExtras();
if(ext != null)
{
int pos= ext.getInteger("pos");
// ext.getInt("pos");
heading.setText(headings[pos]);
// hey, frend, you don't have any array for selecting image-name and text
// image.setImageResource(images[x]);
// text.setText(text[x]);
}
}
Use the "extras" feature that are part of an Intent.
When you call start ImageActivity from Primary, you can use a 'extras' to pass information between the two.
See this link for details.
I'll give you a basic example here. When the list item is clicked, put the data that you want ImageActivity to have into the intent using "putExtra".
Intent intent = new Intent(getBaseContext(), ImageActivity.class);
String data = "somedata";
intent.putExtra("DATA", data);
startActivity(intent)
Then, in ImageActivity onCreate, retrieve the data like this:
Bundle extras = getIntent().getExtras();
if(extras !=null) {
String data= extras.getString("DATA"); // matches the tag used in putExtra
}
Once you have retrieved the data, set the necessary views.
use below code
public void onListItemClick(ListView parent, View v, int position, long id)
{
Intent intent = new Intent(Primary.this, ImageActivity.class);
intent.putExtra("selected value", item[position]);
startActivity(intent);
}
in ImageActivity class:in oncreate (or you can put item variable as global)
String item = getIntent().getStringExtra("Selected value");

Categories