how can i apply limit to recyclerview? - android

i want apply limit to recyclerview and only show 5 result in it and in the end of the list show a button for go to another place?!
my code in below;
adapter codes:
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.Holder> {
ArrayList<Products> ProductsList;
Context context;
public ProductAdapter(ArrayList<Products> productsList, Context context) {
ProductsList = productsList;
this.context = context;
}
#NonNull
#Override
public Holder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(context).inflate(R.layout.row_layout_horizental, parent, false);
return new Holder(v);
}
#Override
public void onBindViewHolder(#NonNull Holder holder, int position) {
Products products = ProductsList.get(position);
holder.txtName.setText(products.getName());
holder.txtPrice.setText(products.getPrice());
Picasso.get().load(Config.ip_value + "/images/" + products.getPhoto()).into(holder.imgV);
}
#Override
public int getItemCount() {
return ProductsList.size();
}
public class Holder extends RecyclerView.ViewHolder {
TextView txtName;
TextView txtPrice;
ImageView imgV;
public Holder(#NonNull View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.rowTxtProductName);
txtPrice = itemView.findViewById(R.id.rowTxtPrice);
imgV = itemView.findViewById(R.id.rowImgProduct);
}
}
}
i have some codes in main fragment but i dont think its necessary to put in this place but if you want to see them comment and i will put all in update text
thanks

You can either slice the list to contain only 5 items before passing it to RecyclerView or just change getItemCount method in Adapter to return 5
#Override
public int getItemCount() {
return ProductsList.size() > 5 ? 5 : ProductsList.size();
}

You can set limit as by using getItemCount() as
#Override
public int getItemCount() {
return 5;
}
by another place if u mean to other activity or fragment, then place
the button at the end of your recyclerview layout in your xml file.
for e.g : if using RelativeLayout,
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:id="#+id/recyclerview"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Next"
android:layout_alignParentBottom="true"
android:layout_below="#+id/recyclerview"
android:id="#+id/btn_next"/>
</RelativeLayout>
then on button click you can call the intent or similar to go to your page

You can set limit query in your ProductsList API.
if you are using retrofit2
you can define limit parametr in your API interface, if that option has in your backend server,
#GET("products")
Call<Products> getProducts(#Query("limit") int limit);
and define method in your activity class where you pass setAdapter, like below
public void getProducts(int limit){
Call<Products> call = yourAPI.getProducts(limit);
call.enqueue(new Callback<Products>() {
#Override
public void onResponse(Call<Products> call, Response<Products> response) {
if (response.isSuccessful() && response.body() != null) {
ArrayList<Products> products = response.body();
if (products == null) products = new ArrayList<>();
productsAdapter.setData(products); // setData needs to be defined in your adapter
} else {
Toast.makeText(yourActivity.this, "Server Error", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<Products> call, Throwable t) {
if(t.getMessage() != null) Log.e("ErrorTag", t.getMessage());
Toast.makeText(yourActivity.this, "Server Error", Toast.LENGTH_SHORT).show();
}
});
Don't forget to define new method called setData,
public void setData(ArrayList<Products> productsList) {
this.ProductsList.addAll(productsList);
notifyDataSetChanged();
};
And to get other 5 products I don't advise you to create next or prev button,
better add code below in your onBindViewHolder method of your adapter to make load another 5 more products when user scrolls to the last item,
if (position == (ProductsList.size() - 1)){
if (context instanceof YourActivity){
YourActivity activity = (YourActivity) context;
activity.getProducts(ProductsList.size());
}
}

Related

adapter.notifyItemChanged(position) has no effect

For each item of the list ("itemList")
ArrayList<Item> itemList = new ArrayList<>();
shown by "recyclerView" that is controlled by "itemAdapter", its quantity is displayed, as well as a plus and minus button which allows the user to respectively increase and decrease the quantity.
In the set-up of "itemAdapter" these buttons are given functionality by:
itemAdapter.setOnItemClickListener(new ItemAdapter.OnItemClickListener() {
#Override
public void onPlusClick(int position) {
itemList.get(position).setQuantity(itemList.get(position).getQuantity() + 1);
itemAdapter.notifyItemChanged(position);
Log.d(TAG, "onPlusClick: position = " + position + " quantity = " + itemList.get(position).getQuantity());
}
#Override
public void onMinusClick(int position) {
itemList.get(position).setQuantity(itemList.get(position).getQuantity() - 1);
if (itemList.get(position).getQuantity() < 1) {
itemList.get(position).setQuantity(1);
}
itemAdapter.notifyItemChanged(position);
Log.d(TAG, "onMinusClick: position = " + position + " quantity = " + itemList.get(position).getQuantity());
}
})
The display of the quantity is set up in the onBindViewHolder() of the adapter class ItemAdapter with:
holder.textviewQuantity.setText(String.valueOf(currentItem.getQuantity()));
And this is the code for the adapter class
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class ItemAdapter extends RecyclerView.Adapter<ItemAdapter.ItemListHolder> {
private ArrayList<Item> mItemList;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onPlusClick(int position);
void onMinusClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
#NonNull
#Override
public ItemListHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new ItemListHolder(v, mListener);
}
#Override
public void onBindViewHolder(#NonNull ItemListHolder holder, int position) {
Item currentItem = mItemList.get(position);
holder.imageviewCategoryIcon.setImageResource(Main.getIconID(currentItem.getCategoryNumber()));
holder.textviewItemName.setText(currentItem.getItemName());
holder.textviewQuantity.setText(String.valueOf(currentItem.getQuantity()));
}
}
#Override
public int getItemCount() {
return mItemList.size();
}
public static class ItemListHolder extends RecyclerView.ViewHolder {
CardView cardviewItem;
ImageView imageviewCategoryIcon;
TextView textviewItemName;
Button buttonPlus;
Button buttonMinus;
TextView textviewQuantity;
public ItemListHolder(#NonNull View view, OnItemClickListener listener) {
super(view);
cardviewItem = view.findViewById(R.id.cardview_item);
imageviewCategoryIcon = view.findViewById(R.id.imageview_category_icon);
textviewItemName = view.findViewById(R.id.textview_item_name);
buttonPlus = view.findViewById(R.id.button_plus);
buttonMinus = view.findViewById(R.id.button_minus);
buttonPlus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null) {
int position = getBindingAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onPlusClick(position);
}
}
}
});
buttonMinus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null) {
int position = getBindingAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onMinusClick(position);
}
}
}
});
}
}
public ItemAdapter(ArrayList<Item> itemList) {
mItemList = itemList;
}
}
When the app starts up, the list of items is displayed, with each item showing the correct quantity.
But when the user clicks a plus or minus button, the quantity displayed doesn't change, though the logs clearly indicate the correct position in "itemList" has been chosen, and that the quantity of the corresponding item has indeed changed correctly.
It looks like itemAdapter.notifyItemChanged(position) has no effect. I also tried itemAdapter.notifyDataSetChanged(), but with no effect either. The recycler display is not being refreshed with the data changes.
What could be wrong?
PS: my very unworkable workaround is to run the whole recycler set-up each time that plus or minus button is clicked. Works fine if the list of items is no longer than the screen, but of course, resets to the top of the list if you press a button of an item that was found scrolling down.
This is an answer by the author.
The problem could ultimately be narrowed down to itemAdapter.notifyDataSetChanged() stalling when the entire "itemList" has been changed, like with a for loop. Also itemAdapter.notifyItemChanged() then become irresponsive. As workaround, I have everywhere replaced itemAdapter.notifyDataSetChanged() with setUpRecycler(), an own-defined method that sets up the whole RecyclerView again. Inevitably, the view will go to the top of the list, but that's a quirk I'm (gladly) prepared to accept. itemAdapter.notifyItemChanged() works fine then.

How to infinite scroll load more with Recycleview?

How to infinite scroll load more with Recycleview
how can i display result like infinite means when user scroll dynamic data automatically fetch and show. so loading time consume and application will work fine.
File Name: MainActivity.java //Main Java file that i want to show load more
package com.ejobbox.ejobbox;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import java.util.ArrayList;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ProgressBar progressBar;
private LinearLayoutManager mLayoutManager;
private RecyclerViewAdapter adapter;
private ArrayList<Model> list;
private String baseURL="http://mywebsite.com/";
public static List<WPPost> mListPost;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView= findViewById(R.id.recycler_view);
progressBar=findViewById(R.id.progressbar);
mLayoutManager=new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(mLayoutManager);
list=new ArrayList<Model>();
// call retrofit
getRetrofit();
adapter=new RecyclerViewAdapter(list,MainActivity.this);
recyclerView.setAdapter(adapter);
}
private void getRetrofit(){
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(baseURL)
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitArrayApi service = retrofit.create(RetrofitArrayApi.class);
Call<List<WPPost>> call= service.getPostInfo();
call.enqueue(new Callback<List<WPPost>>() {
#Override
public void onResponse(Call<List<WPPost>> call, Response<List<WPPost>> response) {
Log.e("mainactivty","response"+ response.body());
progressBar.setVisibility(View.GONE);
for(int i=0; i<response.body().size();i++){
Log.e ("main","Title"+ response.body().get(i).getTitle().getRendered()+" "+
response.body().get(i).getId());
String tempdetails=response.body().get(i).getExcerpt().getRendered().toString();
tempdetails=tempdetails.replace("<p>","");
tempdetails=tempdetails.replace("</p>","");
String linkdetail=response.body().get(i).getLink().toString();
String date=response.body().get(i).getDate().toString();
list.add(new Model(Model.IMAGE_TYPE, response.body().get(i).getTitle().getRendered(),
tempdetails,date,
response.body().get(i).getLinks().getWpFeaturedmedia().get(0).getHref(),linkdetail) );
}
adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<List<WPPost>> call, Throwable t) {
}
});
}
}
(This is RecyclearViewAdapter that i have define recyclear view Adapter.)
File Name: RecyclearViewAdapter.java //Recyclear View Adapter File
package com.ejobbox.ejobbox;
import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
public class RecyclerViewAdapter extends RecyclerView.Adapter{
private ArrayList<Model> dataset;
private Context mContext;
public RecyclerViewAdapter(ArrayList<Model> mlist, Context context) {
this.dataset=mlist;
this.mContext=context;
}
public static class ImageTypeViewHolder extends RecyclerView.ViewHolder{
TextView title,subtitle,link,date;
ImageView imageView;
public ImageTypeViewHolder(View itemView){
super(itemView);
this.title=(TextView)itemView.findViewById(R.id.title);
this.link=(TextView)itemView.findViewById(R.id.link);
this.subtitle=(TextView) itemView.findViewById(R.id.subtitle);
this.imageView=(ImageView) itemView.findViewById(R.id.icon);
this.date=(TextView)itemView.findViewById(R.id.date);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.postdetails,parent,false);
return new ImageTypeViewHolder(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
final Model object=dataset.get(position);
((ImageTypeViewHolder) holder).title.setText(object.title);
((ImageTypeViewHolder) holder).subtitle.setText(object.subtitle);
//((ImageTypeViewHolder) holder).link.setText(object.link);
((ImageTypeViewHolder) holder).date.setText((CharSequence) object.date);
((ImageTypeViewHolder) holder).title.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent=new Intent(mContext, WPPostDetails.class);
intent.putExtra("itemPosition",position);
intent.putExtra("link",object.link.toString());
mContext.startActivity(intent);
}
});
}
#Override
public int getItemCount() { return dataset.size();}
}
Do not use infinite scroll it does not work as expected.
You can use this
recyclerView.addOnScrollListener(new OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
if (isLastItemDisplaying())
{
scrollCount=scrollCount+10;
L.v("scroll count",""+recyclerView.getAdapter().getItemCount());
loadMoreItems(scrollCount);
}
}
});
private boolean isLastItemDisplaying()
{
if (storiesList.getAdapter().getItemCount()!=0) {
int last_visible_count=manager.findFirstCompletelyVisibleItemPosition();
if (last_visible_count!=RecyclerView.NO_POSITION && last_visible_count==storiesList.getAdapter().getItemCount()-1) {
return true;
}
}
return false;
}
Inside this loadMoreItems method call your api. Make sure to send this scroll count to your server on each api call .And in sql query you have to do this
EX:
For example on first time your count is 0;
SELECT * FROM posts LIMIT 0,10
On Scroll your scrollCount value will get increased by 10 (you can use your value scroll count values will fetch next 10 rows)
SELECT * FROM posts LIMIT 10,10
You only have to add your new data to the last position of list movies and everything will work fine. For this-
Create a new List of List<Model> newList and add your updated data to it. Now add newList into list and notify to adapter. Just like below-
List<Model> newList = new ArrayList<>();
// your code..
recyclerView.addOnScrollListener(new EndlessScrollListener(mLayoutManager) {
#Override
public void onLoadMore(int page, int totalItemsCount) {
loadingMore=true;
getRetrofit();
int currentSize = adapter.getItemCount();
list.addAll(newList);
adapter.notifyItemRangeInserted(currentSize, list.size() - 2);
}
});
And here you can find the EndlessScrollListener class.
please look at my other related answers to more details-
How to load more items in a ListView using AsyncTask or any other method
Continious scrolling in recyclerview by Json request and adding new item with previous
Hope it will help.
Here is example for Simple Implementation of Endless Scrolling RecyclerView using a Simple Library compiled from the various sources.
Add this line in build.gradle
implementation 'com.hereshem.lib:awesomelib:2.0.1'
Create RecyclerView Layout in Activity with
<com.hereshem.lib.recycler.MyRecyclerView
android:id="#+id/recycler"
app:layoutManager="LinearLayoutManager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Create a ViewHolder by passing the class that supports
public static class EVHolder extends MyViewHolder<Events> {
TextView date, title, summary;
public EVHolder(View v) {
super(v);
date = v.findViewById(R.id.date);
title = v.findViewById(R.id.title);
summary = v.findViewById(R.id.summary);
}
#Override
public void bindView(Events c) {
date.setText(c.date);
title.setText(c.title);
summary.setText(c.summary);
}
}
Create Items List variable and adapters with very few lines by passing items, class and layout in the adapter
List<Events> items = new ArrayList<>();
MyRecyclerView recycler = findViewById(R.id.recycler);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(this, items, EVHolder.class, R.layout.row_event);
recycler.setAdapter(adapter);
ClickListener and LoadMore Listener can be added with following lines
recycler.setOnItemClickListener(new MyRecyclerView.OnItemClickListener() {
#Override
public void onItemClick(int position) {
Toast.makeText(MainActivity.this, "Recycler Item Clicked " + position, Toast.LENGTH_SHORT).show();
}
});
recycler.setOnLoadMoreListener(new MyRecyclerView.OnLoadMoreListener() {
#Override
public void onLoadMore() {
loadData();
}
});
loadData();
After the data is loaded this must be called
recycler.loadComplete();
When no LoadMore is required LoadMore layout can be hidden by calling
recycler.hideLoadMore();
More example can be found here
Hope this helps :)

Android: Implementing mopub native ads in recyclerview gives incorrect item positions and IndexOutOfBoundsException

In my android app I'm trying to implement mopub native ads. Before using these native ads my app was functioning correctly as expected. Now it gives outofbound exceptions and incorrect items when list item is clicked. I'm using recyclerview and using infinite scrolling, it gets item from my api and displays item correctly, but when clicking on item it gives incorrect item.
Here is my recyclerview adapter below.
package com.example.adapters;
import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.MyApplication;
import com.example.R;
import com.example.events.ErrorLoadingFeed;
import com.example.events.FeedLoaded;
import com.example.events.LoadMoreFeed;
import com.example.model.Post;
import com.example.model.Pagination;
import com.example.ui.InfoActivity;
import com.example.utils.MyAppConstants;
import com.google.gson.Gson;
import com.squareup.picasso.Picasso;
import java.util.List;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Header;
import retrofit.client.Response;
/**
* Created by starwar on 08/09/15.
*/
public class PostRecycleAdapter extends RecyclerView.Adapter<com.example.adapters.PostRecycleAdapter.PostViewHolder> implements Callback<List<Post>> {
private Context mContext;
private List<Post> mPosts;
// Allows to remember the last item shown on screen
private int lastPosition = -1;
// Pagination
private Pagination mPagination;
public PostRecycleAdapter(Context context, List<Post> posts) {
mContext = context;
mPosts = posts;
}
#Override
public PostViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
PostViewHolder viewHolder = new PostViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(PostViewHolder holder, int position) {
holder.bindPost(mPosts.get(position));
// Here you apply the animation when the view is bound
setAnimation(holder.mPostName, position);
//check for last item
if ((position >= getItemCount() - 1)) {
// Loading next set of list items on scroll
if (mPagination != null && !mPagination.getOutOfRange() && mPagination.getNextPage() != null){
MyApplication.bus.post(new LoadMoreFeed(mPagination));
}
}
}
#Override
public int getItemCount() {
return mPosts == null ? 0 : mPosts.size();
}
/**
* Here is the key method to apply the animation
*/
private void setAnimation(View viewToAnimate, int position)
{
// If the bound view wasn't previously displayed on screen, it's animated
if (position > lastPosition)
{
Animation animation = AnimationUtils.loadAnimation(mContext, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
lastPosition = position;
}
}
public class PostViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView mPostName;
public ImageView mAnchorImage;
public PostViewHolder(View itemView) {
super(itemView);
mPostName = (TextView) itemView.findViewById(R.id.postName);
mAnchorImage = (ImageView) itemView.findViewById(R.id.anchorImage);
itemView.setOnClickListener(this);
}
public void bindPost(Post post) {
mPostName.setText(post.getName());
String postImage = post.getPostImage();
Picasso.with(mContext)
.load(postImage)
.placeholder(R.drawable.avatar_empty)
.into(mAnchorImage);
}
#Override
public void onClick(View view) {
int position = getAdapterPosition(); // gets item position
Post post = mPosts.get(position);
int postId = post.getId();
String postName = post.getName();
Intent intent = new Intent(mContext, InfoActivity.class);
intent.putExtra(MyAppConstants.POST_ID, postId);
intent.putExtra(MyAppConstants.POST_NAME, postName);
mContext.startActivity(intent);
}
}
#Override
public void success(List<Post> posts, Response response) {
if (mPosts == null) {
mPosts = posts;
} else {
mPosts.addAll(posts);
}
notifyDataSetChanged();
List<Header> headerList = response.getHeaders();
for(Header header : headerList) {
if ("X-Pagination".equals(header.getName())) {
Gson gson = new Gson();
mPagination = gson.fromJson(header.getValue(), Pagination.class);
}
}
MyApplication.bus.post(new FeedLoaded(mPagination));
}
#Override
public void failure(RetrofitError error) {
Log.d("Call", " : Failed => " + error);
MyApplication.bus.post(new ErrorLoadingFeed(error));
}
public void clearData() {
if (mPosts != null) {
mPosts.clear();
notifyDataSetChanged();
}
}
public List<Post> getPosts() {
return mPosts;
}
}
And I'm using guide given here to show ads
https://dev.twitter.com/mopub/native/native-android-sdk-integration
Please help. what I can/should do to resolve this.
Thanks in advance.
I know this is an old question, but I was looking for the answer for a couple of hours. Probably I'll save someone's time with this solution.
If you will look carefully documentation here: https://github.com/mopub/mopub-android-sdk/wiki/Native-Ads-with-Recycler-View you will find this:
If you register any data observers on your original Adapter, you should instead register them on the MoPubRecyclerAdapter so they will receive messages with the adjusted position of content items. If you do not do this, the positions you receive for insertion and removal messages may be inaccurate. Be sure to check isAd(position) and use MoPubRecyclerAdapter#getOriginalPosition if you need the position of the item in your local adapter.
So, to get real position, it is necessary to use MoPubRecyclerAdapter.getOriginalPosition(position_in_your_adapter) method.

How to extract all the editText's data from a ListView when one single button (save) is pressed

This is the first question I am posting. Here is my question and below given is the debugged code from android studio.
Here, I have tried to extract the data by taking the data from the adapter into the mainActvity, but I failed as the app is crashing on Clicking the save button. Here the data is nothing but and object.
MainActivity :
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
ArrayList<ListItem_Elements> testsList;
int n=5;//No. of tests
Button btn_save;
CustomAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView)findViewById(R.id.listView);
btn_save= (Button)findViewById(R.id.btn_save);
//CustomAdapter adapter;
Resources res=getResources();//Takes the resource permission required to show ListView
testsList= new ArrayList<ListItem_Elements>();
testsList = SetList();
adapter= new CustomAdapter(this, testsList, res);
listView.setAdapter(adapter);
btn_save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(testsList!=null)
saveValues();
}
});
}
public ArrayList<ListItem_Elements> SetList() {
/*Enter the Test names*/
ArrayList<ListItem_Elements>tests_Array= new ArrayList<ListItem_Elements>();
for(int i=0;i<5;i++) {
ListItem_Elements e = new ListItem_Elements();
e.setTest("XYZ");
e.setResult(null);
tests_Array.add(e);
}
return tests_Array;
}
ArrayList<ListItem_Elements>ar= new ArrayList<>();
public void saveValues() {
if(adapter.extractedArray!=null) {
ar = adapter.extractedArray;
Toast.makeText(MainActivity.this, ar.size(), Toast.LENGTH_SHORT).show();
}
}
}
--------------------------------------------------------------------------------
CustomAdapter :
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.TextView;
import java.util.ArrayList;
public class CustomAdapter extends BaseAdapter {
private Activity activity;
public static ArrayList<ListItem_Elements> extractedArray= new ArrayList<ListItem_Elements>();
private ArrayList<ListItem_Elements> array;
//Declaration of ArrayList which will be used to recieve the ArrayList that has to be putup into the ListView
private LayoutInflater inflater; //To Instantiates a layout XML file into its corresponding View
Resources res;
//protected String bridgeValue;
CustomAdapter(Activity a, ArrayList<ListItem_Elements> b, Resources resLocal) {
activity = a;
array= b;
res = resLocal;
//Initialization of inflater to link the layout of list items
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public CustomAdapter() {
}
#Override
public int getCount() {
return array.size();
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
// keeping references for views we use view holder
public static class ViewHolder {
/*Declaration of elements of layout of list items in the class for future use of putting up
data onto the List View*/
TextView textView;
EditText editText;
}
#Override
//Here views were bound to a position
public View getView(int position, View convertView, ViewGroup parent) {
View vi = convertView;
ViewHolder holder;
// if a view is null(which is for the first item) then create view
if (convertView == null) {
vi = inflater.inflate(R.layout.layout_items, null);
// Taking XML files that define the layout of items, and converting them into View objects.
holder = new ViewHolder();//Stores the elements of the layout of list items
/*Initializing the elements of the layout of list item*/
holder.textView = (TextView) vi.findViewById(R.id.textView);
holder.editText = (EditText) vi.findViewById(R.id.editText);
vi.setTag(holder);
//Stores the view(layout of list item) into vi
}
//else if it already exists, reuse it(for all the next items). Inflate is costly process.
else {
holder = (ViewHolder) vi.getTag();
//Restores the already exisiting view in the 'vi'
}
/*Setting the arrayList data onto the different elements of the layout of list item*/
try {
holder.textView.setText(array.get(position).getTest());
if(holder.editText.getText()!=null) {
ListItem_Elements obj = new ListItem_Elements();
obj.setTest(array.get(position).getTest());
obj.setResult(holder.editText.getText().toString());
extractedArray.add(position, obj);
}
}
catch (Exception e) {
e.getMessage();
}
return vi;//Returns the view stored in vi i.e contents of layout of list items
}
}
--------------------------------------------------------------------------------
public class ListItem_Elements {
String test;
String result;
ListItem_Elements() {
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
You are missing some necessary code. EditText has a method called addTextChangedListener() which accepts a TextWatcher implementation. This implementation would be responsible for updating the data in the adapter.
final ListItem_Elements item = array.get(position);
holder.textView.setText(item.getTest());
holder.editText.setText(item.getResult());
holder.editText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
item.setResult(s.toString());
}
// omitted empty impls for beforeTextChanged() and afterTextChanged(), you need to add them
});
Now, everytime the user updates the EditText, your adapter value will be updated. Then you just get the array values:
public void saveValues() {
// testLists in the activity and array in the adapter are references
// to the same list. So testLists already has the updated results
}
And take out this whole block of code:
holder.textView.setText(array.get(position).getTest());
if(holder.editText.getText()!=null) {
ListItem_Elements obj = new ListItem_Elements();
obj.setTest(array.get(position).getTest());
obj.setResult(holder.editText.getText().toString());
extractedArray.add(position, obj);
}
It doesn't do the right thing.
you are filling the listView with value from an ArrayList. Why you don't just get values from the your ArrayList ??
public void saveValues() {
if(tests_Array!=null) {
//and here you get values from your list
//by a simple for instruction
Toast.makeText(MainActivity.this, tests_Array.size(), Toast.LENGTH_SHORT).show();
}
}

How to show an AlertDialog from a Button Clicked in a ListView row?

I am populating a ListView with a Base Adapter in such a way that all except the last item will be checkboxes and the last item will be a TextView with a button.
Here are the XML files.
Final Item:
<?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="horizontal" >
<TextView
android:id="#+id/tv_newitem"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="3"
android:text="#string/new_account_text"
/>
<Button
android:id="#+id/b_newitem"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="2"
android:text="#string/add_button_text"
android:onClick="showNewAccountDialog"
/>
</LinearLayout>
Checkboxes:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
>
<CheckBox
android:focusable="true"
android:id="#+id/account_item_cb"
android:layout_height="wrap_content"
android:layout_width="match_parent"
></CheckBox>
</LinearLayout>
Here is the Class file for the base adapter:
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
public class AccountListAdapter extends BaseAdapter{
private static final int TYPE_ACCOUNT = 0;
private static final int TYPE_NEW_ACCOUNT = 1;
private static final int TYPE_MAX_COUNT = 2;
private LayoutInflater mInflator;
private ArrayList<String> mStrings;
private ArrayList<String> mSelectedStrings;
public AccountListAdapter(Context context, ArrayList<String> array)
{
mInflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mStrings = array;
mSelectedStrings = new ArrayList<String>();
}
public void addNewAccount(final String accountName)
{
mStrings.add(mStrings.size()-2, accountName);
notifyDataSetChanged();
}
#Override
public int getCount()
{
return mStrings.size();
}
#Override
public String getItem(int position)
{
return mStrings.get(position);
}
#Override
public long getItemId(int position)
{
return position;
}
#Override
public int getViewTypeCount()
{
return TYPE_MAX_COUNT;
}
#Override
public int getItemViewType(int position)
{
return position == mStrings.size()-1 ? TYPE_NEW_ACCOUNT : TYPE_ACCOUNT;
}
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
int type = getItemViewType(position);
System.out.println(position + ": " + type);
switch (type) {
case TYPE_ACCOUNT:
convertView = mInflator.inflate(R.layout.account_item, null);
CheckBox tv = (CheckBox) convertView.findViewById(R.id.account_item_cb);
tv.setText(getItem(position));
tv.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// TODO Auto-generated method stub
if (isChecked)
{
mSelectedStrings.add(buttonView.getText().toString());
}else {
mSelectedStrings.remove(buttonView.getText().toString());
}
}
});
break;
case TYPE_NEW_ACCOUNT:
convertView = mInflator.inflate(R.layout.list_new_item_add_button, null);
break;
default:
break;
}
return convertView;
}
public ArrayList<String> getSelectedStrings()
{
return mSelectedStrings;
}
}
There is an Activity calls which Populates this base adapter will an Array list of String. I am trying to show a dialog box to the user when the Add button is clicked. But I am not able to show it. I tried:
Adding android:onClick=method in the XML file and writing corresponding method in the main activity file, but Eclipse cannot find the function. I think it is looking for the function in the base adapter class. But the problem is I can't write code to show a AlertBox in the Base Adapter class because getSupportFragmentManager cannot be accessed from there.
Adding onClickListener to Button using findViewById, but Eclipse gives me NullPointerException here. I think this is because the button is placed in the ListView and not the Activity directly.
Can someone help me here?
Thanks!
Check this, follow the examples to implement an interface in the activity and pass it to your adapter when you create it.
All you need is to place the open dialog code in the interface method in the activity and call it in the adapter when you click the button.
Place this somewhere in your activity: (this could also be done by making the activity implement the interface)
public interface DialogCreatorInterface{
public void showDialog();
}
DialogCreatorInterface dialogCreatorInterface = new DialogCreatorInterface() {
#Override
public void showDialog() {
//Create and show the dialog code
}
};
Change the adapter constructor to include the interface:
AccountListAdapter(Context context, ArrayList<String> array, DialogCreatorInterface dialogCreatorInterface)
Add this under your TYPE_NEW_ACCOUNT in the getView method:
Button button = (Button) convertView.findViewById(R.id.b_newitem);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//Call open AlerDialog in activity via the interface
dialogCreatorInterface.showDialog();
}
});
You need to implement
OnItemClickListener
#Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3)

Categories

Resources