issue due to getAdapterPosition - android

I have an array which contains values like {seat 1,seat 1,seat 1,seat 2, seat 2, seat 3, seat 4,seat 4,seat 4}. ie Left side of image
I need to group them according to its seat values ie. Right side of image.
For given environment seat list array will be: {"1", "-1", "-1", "2", "-1", "3", "4", "-1", "-1"}
currently i am using recyclerview and checking this with below condition:
if(seat_list.get(holder.getAdapterPosition()).equals("-1"))
{
Log.d("aaa", "if :" + seat_list.get(holder.getAdapterPosition()) );
}
else
{
Log.d("aaa", "else :" + seat_list.get(holder.getAdapterPosition()) );
holder.ll_header.setVisibility(View.VISIBLE);
holder.tv_seat_num.setText(seat_list.get(holder.getAdapterPosition()));
}
With above code list is getting destroyed on scrolling the recyclerview.
i already sorted but i want to give common header or heading to all orders with same seat

First of all, I don't think your data ready to be displayed. So it`d be better to prepare it.
And it is better to have some typed data model, that contains info about seats and orders. OOP, you know ?
To keep example simple, I prepare and map data within activity, but it's not very good idea for real world projects.
So, from your description, we have some array, where items could be duplicated and their position in array - it is orderId. So, in other way we want to have some grouped structure with key-value pair, where key -> № of Seat, and value -> collection of orderIds. But it will be much better to have a class, that represent such relations and have info about things described above.
With data like that, it will be not very big problem to just display them in recyclerView.
At the begining, I wanted to place just couple methods here, but after I realized that it may be confused without full code list.
So, here you go all stuff.
This is result of what you will get with listed below code:
= = = = = time to see some code = = = = =
Activity -> (with only RecyclerView in xml layout)
public class SeatsActivity extends AppCompatActivity {
RecyclerView recycler;
SeatsAdapter seatsAdapter;
final String[] orders =
{ "seat 1", "seat 1", "seat 1", "seat 2", "seat 2", "seat 3", "seat 4", "seat 4", "seat 4" };
#Override protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_seats);
setTitle("Seats example");
recycler = (RecyclerView) findViewById(R.id.recycler);
recycler.setLayoutManager(new LinearLayoutManager(this));
final Map<String, List<Integer>> groupedOrders = groupData(orders);
final List<SeatItem> seats = mapToSeatsItems(groupedOrders);
bindToRecycler(seats);
}
private void bindToRecycler(List<SeatItem> seatItems) {
seatsAdapter = new SeatsAdapter(seatItems);
recycler.setAdapter(seatsAdapter);
}
private Map<String, List<Integer>> groupData(final String[] items) {
final Map<String, List<Integer>> grouped = new LinkedHashMap<>();
for (int i = 0; i < items.length ; i++) {
// I took it from your description. I image that orderId is the place of the seat in array
final Integer orderId = i+1;
final String headerKey = items[i];
if (!grouped.containsKey(headerKey)){
List<Integer> list = new ArrayList<>();
list.add(orderId);
grouped.put(headerKey, list);
} else {
List<Integer> list = grouped.get(headerKey);
list.add(orderId);
}
}
return grouped;
}
private List<SeatItem> mapToSeatsItems(Map<String, List<Integer>> groupOrders) {
final List<SeatItem> list = new ArrayList<>(groupOrders.size());
for (String key : groupOrders.keySet()) {
final SeatItem item = new SeatItem(key, groupOrders.get(key));
list.add(item);
}
return list;
}
}
Then SeatItem, that represent data model (POJO, Bean, whatever)
public class SeatItem {
public SeatItem(String header, List<Integer> orderIds) {
this.header = header;
this.orderIds = orderIds;
}
final String header;
final List<Integer> orderIds;
public String getHeader() {
return header;
}
public List<Integer> getOrderIds() {
return orderIds;
}
}
SeatsAdapter ->
public class SeatsAdapter extends
RecyclerView.Adapter<RecyclerView.ViewHolder> {
final List<SeatItem> dataList;
public SeatsAdapter(final List<SeatItem> items){
dataList = items;
}
#Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup
parent, int viewType) {
final View view =
LayoutInflater.from(parent.getContext()).inflate(R.layout.item_seat, parent,
false);
return new SeatsViewHolder(view);
}
#Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int
position) {
final SeatsViewHolder seatsViewHolder = (SeatsViewHolder) holder;
final SeatItem item = dataList.get(holder.getAdapterPosition());
final StringBuilder contentBuilder = new StringBuilder();
for (int i = 0; i < item.getOrderIds().size(); i++) {
// here is not production ready, but for just example will be ok
contentBuilder
.append("order Id: ")
.append(item.getOrderIds().get(i));
if (i + 1 != item.getOrderIds().size()){
contentBuilder.append("\n");
}
}
seatsViewHolder.tvHeader.setText(item.getHeader());
seatsViewHolder.tvContent.setText(contentBuilder);
}
#Override public int getItemCount() { return dataList.size(); }
private static class SeatsViewHolder extends RecyclerView.ViewHolder {
final TextView tvHeader;
final TextView tvContent;
SeatsViewHolder(View itemView) {
super(itemView);
tvHeader = (TextView) itemView.findViewById(R.id.tvHeader);
tvContent = (TextView) itemView.findViewById(R.id.tvContent);
}
}
}
And the last one - item xml, that will be displayed by recycler
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="#+id/tvHeader"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="header! "
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:padding="8dp"
android:background="#cccccc"
/>
<TextView
android:id="#+id/tvContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="content ! ! ! "
android:layout_gravity="top"
android:gravity="top"
android:textAppearance="#style/TextAppearance.AppCompat.Medium"
android:padding="8dp"
/>
</LinearLayout>

You can sort using Collections.sort method

Related

Show values of same key in one TextView in Recyclerview

I have the following JSON which I'm parsing in GSON and Retrofit. I want to display the values of the same id in one TextView. What's happening right now is that all the values are added to the array and they are being displayed in separate TextViews. I want to show all values which have the same id to be displayed in one TextView. For eg. id: 240 ab values should be in one TextView. Currently, all ab values are in separate TextView.
This is how the data is currently displaying:
This is how I want the data to be:
JSON::
{
"abc": {
"1": {
"1": {
"ab": "some content",
"id": "240",
"key": "value"
},
"2": {
"ab": "some content",
"id": "240",
"key": "value"
},
"3": {
"ab": "some content",
"id": "240",
"key": "value"
}
},
"2": {
"1": {
"ab": "more content",
"id": "241",
"key": "value"
},
"2": {
"ab": "more content 1",
"id": "241",
"key": "value"
},
"3": {
"ab": "more content 2",
"id": "241",
"key": "value"
}
}
}
}
POJOContent::
public class POJOContent {
#SerializedName("ab")
public String content;
#SerializedName("id")
public String id;
#SerializedName("key")
public String key;
#Override
public String toString() {
return content;
}
//getters and setters
}
MyContentWrapper::
public class MyContentWrapper {
public Map<Integer, MyMap> abc;
}
MyMap::
public class MyMap extends HashMap<Integer, POJOContent> {
#Override
public POJOContent put(Integer key, POJOContent value) {
if(null==value.getContent() || value.getContent().isBlank()) {
return null;
}
// Added only if content = "ab" is not blank.
return super.put(key, value);
}
}
Callback:
Callback<MyContentWrapper> myCallback = new Callback<MyContentWrapper>() {
#Override
public void onResponse(Call<MyContentWrapper> call, Response<MyContentWrapper> response) {
if (response.isSuccessful()) {
Log.d("Callback", " Message: " + response.raw());
Log.d("Callback", " Message: " + response.body().abc.values());
MyContentWrapper contentWrapper = response.body();
List<POJOContent> pojo = new ArrayList<>();
for (Map.Entry<Integer, MyMap> entry : contentWrapper.abc.entrySet()) {
Integer key = entry.getKey();
MyMap map = entry.getValue();
if (!map.isEmpty()){
Log.d("Callback", " Key: " + key);
Log.d("Callback", " Value: " + map.values());
pojo.addAll(map.values());
}
}
MyContentViewAdapter adapter = new MyContentViewAdapter(pojo);
recyclerView.setAdapter(adapter);
} else {
Log.d("Callback", "Code: " + response.code() + " Message: " + response.message());
}
}
#Override
public void onFailure(Call<MyContentWrapper> call, Throwable t) {
t.printStackTrace();
}
};
RecyclerAdapter::
public class MyContentViewAdapter extends RecyclerView.Adapter<MyContentViewAdapter.ViewHolder> {
private List<POJOContent> data;
private MyClickListener clickListener;
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView text;
private LinearLayout itemLayout;
public ViewHolder(View v) {
super(v);
text = (TextView) v.findViewById(R.id.text_content);
}
}
public MyContentViewAdapter(List<POJOContent> data) {
this.data = data;
Log.d("Recyclerview Data", data.toString());
}
#Override
public MyContentViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_content_card, parent, false);
return new MyContentViewAdapter.ViewHolder(v);
}
#Override
public void onBindViewHolder(MyContentViewAdapter.ViewHolder holder, int position) {
POJOContent pojo = data.get(position);
Log.d("Recyclerview", pojo.getContent());
holder.text.setText(pojo.getContent());
holder.itemView.setTag(pojo.getContent());
}
public void setOnItemClickListener(MyClickListener clickListener) {
this.clickListener = clickListener;
}
#Override
public int getItemCount() {
return data.size();
}
}
EDIT:
I added nested RecyclerView inside ViewHolder, so the content and value fields will be displayed dynamically. I'm Adding full code of 2 Adapter and
2 ViewHolder classes, 2 xml layouts and screenshot
I'm pretty sure it will run really smoothly with very large list too.
Everything under ID(240,241) is another recyclerView.
The idea is that list's size, for adapter to populate itself, should be as many as the number of distinct ids, so that only that many Viewholders are inflated.
List<List<POJOContent>> listOfPojoLists = new ArrayList<>();
for (Map.Entry<Integer, MyMap> entry : contentWrapper.abc.entrySet()) {
Integer key = entry.getKey();
MyMap map = entry.getValue();
if (!map.isEmpty()){
Log.d("Callback", " Key: " + key);
Log.d("Callback", " Value: " + map.values());
listOfPojoLists.add(new ArrayList<>(map.values()));
}
}
MyContentViewAdapter adapter = new MyContentViewAdapter(listOfPojoLists);
recyclerView.setAdapter(adapter);
MyContentViewAdapter.java
public class MyContentViewAdapter extends RecyclerView.Adapter<MyContentViewAdapter.ViewHolder> {
private List<List<POJOContent>> data;
private MyClickListener clickListener;
MyContentViewAdapter(List<List<POJOContent>> data) {
this.data = data;
}
#Override
public MyContentViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_content_card, parent, false);
return new MyContentViewAdapter.ViewHolder(v);
}
#Override
public void onBindViewHolder(MyContentViewAdapter.ViewHolder holder, int position) {
holder.bind(data.get(position));
}
public void setOnItemClickListener(MyClickListener clickListener) {
this.clickListener = clickListener;
}
#Override
public int getItemCount() {
return data.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
private TextView textId;
private InnerListAdapter innerAdapter;
// inside constructor we are initializing inner recyclerView and inner Adapter.
// there will only be 3 - 5 instances of them ever created(using this
// particular viewHolder layouts), no more.
// might be slightly more if u use layouts with lower height
ViewHolder(View v) {
super(v);
textId = v.findViewById(R.id.tv_Id);
RecyclerView innerRecycler = v.findViewById(R.id.rv_inner_list);
// I added DividerItemDecoration so it would be clear that there are actually different viewHolders
// displayed by recyclerView
innerRecycler.addItemDecoration(new DividerItemDecoration(v.getContext(), DividerItemDecoration.VERTICAL));
innerAdapter = new InnerListAdapter();
innerRecycler.setAdapter(innerAdapter);
}
/* We just submit new list for our inner adapter
so it will handle rebinding values to its viewHolders */
void bind(List<POJOContent> pojoList){
textId.setText(pojoList.get(0).id);
innerAdapter.setNewItems(pojoList);
}
}
}
InnerListAdapter.java
public class InnerListAdapter extends RecyclerView.Adapter<InnerListAdapter.InnerViewHolder> {
private List<POJOContent> items = new ArrayList<>();
#NonNull
#Override
public InnerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new InnerViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_inner_list, parent, false));
}
#Override
public void onBindViewHolder(#NonNull InnerViewHolder holder, int position) {
holder.bind(items.get(position));
}
#Override
public int getItemCount() {
return items.size();
}
void setNewItems(List<POJOContent> newItems){
items.clear();
items.addAll(newItems);
notifyDataSetChanged();
}
class InnerViewHolder extends RecyclerView.ViewHolder{
TextView tv_value;
TextView tv_content;
InnerViewHolder(#NonNull View itemView) {
super(itemView);
tv_value = itemView.findViewById(R.id.tv_value);
tv_content = itemView.findViewById(R.id.tv_content);
}
void bind(POJOContent pojoContent){
tv_value.setText(pojoContent.getKey());
tv_content.setText(pojoContent.getContent());
}
}
}
fragment_content_card.xml layout for main recyclerView viewholder
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:padding="8dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tv_Id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:textSize="32sp"
android:textColor="#color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="ID" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_inner_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_Id" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
item_inner_list.xml layout for inner recylerVoews' viewholder
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/tv_value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:textColor="#color/black"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="value" />
<TextView
android:id="#+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="8dp"
android:textColor="#color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tv_value"
tools:text="content" />
</androidx.constraintlayout.widget.ConstraintLayout>
create another pojo class for RV List Items with content and keys list
public class POJOListItem {
public String id;
public List<String> contents = new ArrayList<>();
public List<String> keys = new ArrayList<>();
}
then validate and map MyContentWrapper object to List<POJOListItem>, check the list if it contains the id, if it has the same id then add them to the contents and keys list or create a new item and add it. based on the list size dynamically add item in a container layout inside the view holder.
Check out this small demo project https://github.com/toxic-charger/SO-63045236
Tested with 50000+ items no performance issus
Based on your question, you have separate issues to tackle:
1 - Define better the data you have. You currently have POJOContent but you want to display something like a POJOContentGroup, so before getting to the view part you pre-process your data and map it from MyContentWrapper to List<POJOContentGroup>.
data class POJOContentGroup(val id: String, val contentList: List<POJOContent>) (This is in Kotlin for brevity)
2 - Having the previous defined, now you have a simple task: Display a list of POJOContentGroup. Create your recycler view based on that, similar to what you've done initially, with the difference that the item layout will be a TextView for the id and a RecyclerView for the contentList, which is the one you currently have.
As per my understanding of problem description, you are trying to construct array like this
[
"some content"+"some content"+"some content", // id = 240
"more content"+"more content 1"+"more content 2" // id = 241
]
and you want to show these 2 values in list of TextView
but the array you constructed will be,
[
"some content",
"some content",
"some content",
"more content",
"more content 1",
"more content 2"
]
and hence each entry is displayed in separate TextView
To debug further, please check value of pojo list after
pojo.addAll(map.values())
// may be if you want to group entries with comma delimiter, use
// pojo.addAll(TextUtils.join(", ", map.values()))
Hi its late but i would say create one class ListItem
class ListItem {
private var item: HashMap<Int, POJOContent>? = null
}
and overwrite toString in your POJOContent to return the values you want to display on text view like
#Override
public String toString() {
return value + "\n" + content;
}
Then use List in your adapter
Then in bind
//take care of null checks and you can use System.getProperty("line.separator"); in place of line saperator also don't forgate to set maxLine property of your text view to eome higher value
void bind(ListItem item){
Array<POJOContent> contents = item.values().toArray()
tv_value.setText(contents[0].getKey());
tv_content.setText(contents.toString().replace("[","").replace("]","").replace(",","\n"));
}
I think nested-expandable-recyclerview should be the right choice to achieve your goal, which will also increase your user experience. By default can open the nested recycler with your child data of the JSON.

How can I make sticky headers in RecyclerView? (with or without external lib)

I'm using room db and I've a table from where I get a list of LiveData.
In that table there is a column of Date where I store current date. Current date is selected by default, but user can also change the date when inserting data in the database.
I want to show this data in a recyclerview in this manner
https://imgur.com/RYegFpG
I want to section this data according to the month and year as header and all entries of that month year below it.
For example, user inserted data in October 2019, I want this "October 2019" as a header in recyclerview and all entries of this month below it. Just like this all months entries should be shown with same manner as every next month becomes header and the entries of that month below it.
I've tried to achieve this by doing
if (!thisDate.equals(dBDate))
{
holder.transMonthWrapper.setVisibility(View.VISIBLE);
if (IEList.getType().equalsIgnoreCase("income"))
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.GREEN);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.GREEN);
}
else
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.RED);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.RED);
}
thisDate = dBDate;
holder.tvTransMonth.setText(thisDate);
}
else
{
holder.transMonthWrapper.setVisibility(View.GONE);
if (IEList.getType().equalsIgnoreCase("income"))
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.GREEN);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.GREEN);
}
else
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.RED);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.RED);
}
}
But the problem in this code is that when user change the month from settings and put some entries into database and that year's month entries are already present in the recyclerview. It creates another header of that existing month in recyclerview. But I want this to put those entries in existing month header, not to create new header of that month.
What will be the best approach to achieve this without using external libraries, because I don't want to be dependent on external libraries in this case.
I'm fairly new in programming.
Updated
In activity
public void getTransactionData()
{
adapter = new TransactionAdapter();
recyclerView.setAdapter(adapter);
incomeExpenseModel = ViewModelProviders.of(AllTransaction.this).get(IncomeExpenseViewModel.class);
incomeExpenseModel.getIncomeExpenseData().observe(this, new Observer<List<IncomeExpense>>() {
#Override
public void onChanged(List<IncomeExpense> incomeExpenses) {
adapter.setIncomeExpenseList(incomeExpenses);
}
});
In recyclerAdapter
public void onBindViewHolder(#NonNull TransactionViewHolder holder, int position) {
IncomeExpense IEList = incomeExpenseList.get(position);
preferences = context.getSharedPreferences(settingPref, Context.MODE_PRIVATE);
String dateFormat = preferences.getString("Date_Format", "MM.dd.yy");
int lastIndex = incomeExpenseList.size() - 1;
IncomeExpense IELastIndex = incomeExpenseList.get(lastIndex);
String dateFrmDb= IELastIndex.getDate();
DateFormat df=new SimpleDateFormat(dateFormat);
Date d;
try {
d = df.parse(dateFrmDb);
df=new SimpleDateFormat("MMMM yyyy");
if (d != null) {
dBDate = df.format(d);
}
} catch (ParseException e) {
Toast.makeText(context, "Error" +e, Toast.LENGTH_SHORT).show();
}
if (!thisDate.equals(dBDate))
{
holder.transMonthWrapper.setVisibility(View.VISIBLE);
if (IEList.getType().equalsIgnoreCase("income"))
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.GREEN);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.GREEN);
}
else
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.RED);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.RED);
}
thisDate = dBDate;
holder.tvTransMonth.setText(thisDate);
}
else
{
holder.transMonthWrapper.setVisibility(View.GONE);
if (IEList.getType().equalsIgnoreCase("income"))
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.GREEN);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.GREEN);
}
else
{
String amount = ""+IEList.getAmount();
holder.tvTransAmount.setText(amount);
holder.tvTransAmount.setTextColor(Color.RED);
holder.tvTransCategory.setText(IEList.getCategory());
holder.tvTransCategory.setTextColor(Color.RED);
}
}
}
#Override
public int getItemCount() {
return incomeExpenseList.size();
}
public void setIncomeExpenseList(List<IncomeExpense> incomeExpenseList)
{
this.incomeExpenseList = incomeExpenseList;
notifyDataSetChanged();
}
You don't need to use any third party libraries. You can make use of ExpandableListView without actually making it "expand and collapse" to do the exact same thing which you need. See my answer for this post. The advantage here is that you can deal with this as easily as you deal with an ExpandableListView, with no custom code. You only need to add one line to what is otherwise a standard ExpandableListView adapter.
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
...
((ExpandableListView) parent).expandGroup(groupPosition);
...
}
Your section headers, you can set as a group view and the list items as children. Your data structure need to be updated before being passed on to the adapter. It need to be a grouped data, not a plain list which you have to pass to the expandable adapter(for example an array of classes, each instance that contain a String property for group header and an ArrayList of IncomeExpense objects). And when you update the data, make the update in the corresponding group, instead of the entire data.
Parent recyclerview
<FrameLayout 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"
tools:context=".fragments.PhotoFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:clipToPadding="false"
android:paddingBottom="170dp">
</androidx.recyclerview.widget.RecyclerView>
</FrameLayout>
Its adapter
public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.ViewHolder> {
private static final String TAG = "PhotoAdapter";
private Map<String, List<Photo>> photoMap;
private Context context;
private PhotoCategoryAdapter photoCategoryAdapter;
private List<String> keysList;
public PhotoAdapter(Map<String, List<Photo>> photoMap, Context context, List<String> keysList) {
this.photoMap = photoMap;
this.context = context;
this.keysList = keysList;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_photo, parent, false));
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
String date = keysList.get(position);
holder.lblTakenDate.setText(date);
List<Photo> photoList = photoMap.get(date);
String size = ("( "+ photoList.size() + " )");
holder.lblCountPhotos.setText(size);
setRecyclerView(holder, context, photoList);
}
#Override
public int getItemCount() {
return photoMap.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.rv_photo_category) RecyclerView recyclerView;
#BindView(R.id.lbl_taken_date_photo) TextView lblTakenDate;
#BindView(R.id.lbl_count_images_photo) TextView lblCountPhotos;
public ViewHolder(#NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
Reyclerview inside recyclerview
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp">
<TextView
android:id="#+id/lbl_taken_date_photo"
android:textColor="#android:color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:textSize="14dp"
android:hint="23-Aug-2018" />
<TextView
android:id="#+id/lbl_count_images_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_toRightOf="#id/lbl_taken_date_photo"
android:hint="(2)"
android:textSize="12sp" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/rv_photo_category"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/lbl_taken_date_photo"
android:layout_marginTop="10dp"
android:background="#color/light_grey" />
</RelativeLayout>
Its adapter
public class PhotoCategoryAdapter extends RecyclerView.Adapter<PhotoCategoryAdapter.ViewHolder> {
private static final String TAG = "PhotoCategoryAdapter";
private List<Photo> photoList;
private Context context;
public PhotoCategoryAdapter(List<Photo> photoList, Context context) {
this.photoList = photoList;
this.context = context;
}
#NonNull
#Override
public PhotoCategoryAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.row_category_photo, parent, false));
}
#Override
public void onBindViewHolder(#NonNull PhotoCategoryAdapter.ViewHolder holder, int position) {
Photo photo = photoList.get(position);
RequestOptions myOptions = new RequestOptions() .format(DecodeFormat.PREFER_ARGB_8888).
fitCenter().override(100, 100).placeholderOf(R.drawable.ic_image);
Glide.with(context)
.applyDefaultRequestOptions(myOptions)
.asBitmap()
.load(photo.getImage())
.diskCacheStrategy(DiskCacheStrategy.RESOURCE)
.into(holder.imgVImages);
}
#Override
public int getItemCount() {
return photoList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.imgv_images_category_photo)
ImageView imgVImages;
#BindView(R.id.imgv_selected_icon_photo) ImageView imgVSelectedPhoto;
public ViewHolder(#NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
}
Row of inner recyclerview
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_margin="5dp"
android:layout_width="80dp"
android:layout_height="80dp">
<ImageView
android:id="#+id/imgv_images_category_photo"
android:scaleType="fitXY"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="#+id/imgv_selected_icon_photo"
android:visibility="gone"
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_margin="10dp"
android:src="#drawable/ic_select"
android:layout_alignParentEnd="true"/>
</RelativeLayout>
Activity or fragment from where you will send data to adapter
public class PhotoFragment extends Fragment {
#BindView(R.id.rv_photo) RecyclerView recyclerView;
private PhotoAdapter photoAdapter;
private ArrayList<Photo> photoList;
private ArrayList<String> keyList;
private Map<String,List<Photo>> map;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_photo, container, false);
ButterKnife.bind(this, view);
init();
setRecyclerViewAdapter();
new PhotoAsync(getContext()).execute();
return view;
}
private void init(){
map = new HashMap<>();
keyList = new ArrayList<>();
photoList = new ArrayList<>();
}
//set layout manager to recyclerView
private void setRecyclerViewAdapter() {
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
}
//get list of images
#RequiresApi(api = Build.VERSION_CODES.Q)
private List<Photo> getAllImages(){
Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Images.ImageColumns.DATA, MediaStore.Images.ImageColumns.DATE_TAKEN};
Cursor c = null;
ArrayList<Photo> photoList = new ArrayList<>();
if (u != null) {
c = getContext().getContentResolver().query(u, projection, null, null, null); }
if ((c != null) && (c.moveToFirst())) {
do {
Photo photo = new Photo();
String path = c.getString(c.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATA));
String takenDate = c.getString(c.getColumnIndexOrThrow(MediaStore.Images.ImageColumns.DATE_TAKEN));
long millisecond = Long.parseLong(takenDate);
String date = DateFormat.format("dd-MMM-yyyy", new Date(millisecond)).toString();
try{
photo.setImage(path);
photo.setDate(date);
photoList.add(photo);
}
catch(Exception e)
{ }
}
while (c.moveToNext());
}
//reverse photoList
Collections.reverse(photoList);
return photoList;
}
public class PhotoAsync extends AsyncTask<Void, Void, Void> {
private Context context;
public PhotoAsync(Context context) {
this.context = context;
}
#RequiresApi(api = Build.VERSION_CODES.Q)
#Override
protected Void doInBackground(Void... params) {
getPhotoList();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
photoAdapter = new PhotoAdapter(map, context, keyList);
recyclerView.setAdapter(photoAdapter);
photoAdapter.notifyDataSetChanged();
}
#Override
protected void onPreExecute() {
}
}
#RequiresApi(api = Build.VERSION_CODES.Q)
private void getPhotoList(){
photoList.addAll(getAllImages());
for (Photo string : photoList) {
if (!keyList.contains(string.getDate()))
keyList.add(string.getDate());
else;
}
for (String s : keyList){
ArrayList<Photo> photos = new ArrayList<>();
for (Photo s1 : photoList) {
if (s1.getDate().equals(s))
photos.add(s1);
else;
}
map.put(s, photos);
}
}
}
Here is the logic which you have to apply
1. Find all the common dates from the data list
for example you data list is :
List<Model> dataList = new ArrayList<>();
dataList.add(new Model("23/10/19"));
dataList.add(new Model("23/10/19"));
dataList.add(new Model("23/09/19"));
dataList.add(new Model("23/10/19"));
dataList.add(new Model("27/09/19"));
dataList.add(new Model("23/10/19"));
List<String> commonList = new ArrayList<>();
for(Model m : dataList){
if(!commonList.contains(model.getDate()))
commonList.add(m.getDate());
else
Log.d("Dates", commonList);
}
Above function will help in getting all common dates
//Here map store date with data which has common date
Map<String, List<Model>> map = new HashMap<>();
List<Model> objectsofCommonDate = new ArrayList();
for(String date: commonList){
objectsofCommonDate.clear();
for(Model model : dataList){
if(model.getData.contains(date))
objectsofCommonDate.add(model);
else
\\do nothing
}
map.put(data, objectsOfCommonDate);
}
and pass map to main recyclerview adapter along with commonDateList;
First in you setIncomeExpenseList function clear your previous list.
Then reAssign new list that contains full data from DB.
Change notifyDataSetChanged() to notify() or notifyAll().
public void setIncomeExpenseList(List<IncomeExpense> incomeExpenseList)
{
this.incomeExpenceList.clear();
this.incomeExpenseList = incomeExpenseList;
notify();
}

How to add child item to last item from RecyclerView?

Actually i'm trying to make an app that take restaurant orders and i'm having some issues after adding child item to my order.
I have a recyclerView where i have different type's of food when i press on one of them i add it to recyclerView that work's something like a notebook, then i have an button that open an AlertDialog in which there is another recyclerView with variant's.
Example: i press on PIZZA from food recyclerView it's add it to the notebook after i press on variant's and i can add "WITH PEPERONI" or "LARGE" or both.
I have followed this guide ( here github project from the guide) for making the recyclerView with child item.
Now the issue is how can i add the child item to the last parent item?
like i'm adding parent item using this:
dummyParentDataItem = new ItemPTERM();
dummyParentDataItem.setButton_name(filteredList.get(position).getDeskS());
dummyParentDataItem.setQuant( Integer.parseInt(filteredList.get(position).getQuant()));
dummyChildDataItems = new ArrayList<>();
dummyParentDataItem.setChildDataItems(dummyChildDataItems);
itemCassas.add(dummyParentDataItem);
And this when i add a child from variant's recyclerView
dummyChildDataItem = new DummyChildDataItem();
dummyChildDataItem.setChildName(tipo.toString());
dummyChildDataItems.add(dummyChildDataItem);
dummyParentDataItem.setChildDataItems(dummyChildDataItems);
itemCassas.add(dummyParentDataItem);
but obviously the app crash because that don't know which is the last paren't item to which add the child.
When i try to put both parent and child when i'm adding food from recyclerView with:
dummyParentDataItem = new ItemPTERM();
dummyParentDataItem.setButton_name(filteredList.get(position).getDeskS());
dummyParentDataItem.setQuant( Integer.parseInt(filteredList.get(position).getQuant()));
dummyChildDataItems = new ArrayList<>();
dummyChildDataItem = new DummyChildDataItem();
dummyChildDataItem.setChildName("WITH PEPERONI");
dummyChildDataItems.add(dummyChildDataItem);
dummyParentDataItem.setChildDataItems(dummyChildDataItems);
itemCassas.add(dummyParentDataItem);
that obviously works but i have to add the child in a separate method to the last parent.
How can i do it? any suggestion?
Here is also my adapter code:
public class AdapterPTERM extends RecyclerView.Adapter<AdapterPTERM.ExampleViewHolder> {
private ArrayList<ItemPTERM> mExampleList;
#NonNull
#Override
public ExampleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_pterm,parent,false);
return new ExampleViewHolder(v);
}
AdapterPTERM(ArrayList<ItemPTERM> exampleList){
mExampleList = exampleList;
}
#Override
public void onBindViewHolder(#NonNull ExampleViewHolder holder, int position) {
ItemPTERM item = mExampleList.get(position);
holder.desc.setText(item.getBtnName());
holder.qta.setText(String.valueOf(item.getQuant()));
int noOfChildTextViews = holder.linearLayout_childItems.getChildCount();
int noOfChild = item.getChildDataItems().size();
if (noOfChild < noOfChildTextViews) {
for (int index = noOfChild; index < noOfChildTextViews; index++) {
TextView currentTextView = (TextView) holder.linearLayout_childItems.getChildAt(index);
currentTextView.setVisibility(View.GONE);
}
}
for (int textViewIndex = 0; textViewIndex < noOfChild; textViewIndex++) {
TextView currentTextView = (TextView) holder.linearLayout_childItems.getChildAt(textViewIndex);
currentTextView.setText(item.getChildDataItems().get(textViewIndex).getChildName());
}
if(position % 2 == 0 ){
holder.itemView.setBackgroundColor(Color.parseColor("#C0C0C0"));
}else if(position % 2 == 1){
holder.itemView.setBackgroundColor(Color.parseColor("#D3D3D3"));
}
}
#Override
public int getItemCount() {
return mExampleList.size();
}
public class ExampleViewHolder extends RecyclerView.ViewHolder {
public TextView desc;
public TextView qta;
private LinearLayout linearLayout_childItems;
private Context context;
ExampleViewHolder(View itemView) {
super(itemView);
desc = itemView.findViewById(R.id.Desc);
qta = itemView.findViewById(R.id.Qta);
linearLayout_childItems = itemView.findViewById(R.id.ll_child_items);
context = itemView.getContext();
int intMaxNoOfChild = 0;
for (int index = 0; index < mExampleList.size(); index++) {
int intMaxSizeTemp = mExampleList.get(index).getChildDataItems().size();
if (intMaxSizeTemp > intMaxNoOfChild) intMaxNoOfChild = intMaxSizeTemp;
}
for (int indexView = 0; indexView < intMaxNoOfChild; indexView++) {
TextView textView = new TextView(context);
textView.setId(indexView);
textView.setPadding(0, 20, 0, 20);
textView.setGravity(Gravity.CENTER);
textView.setBackground(ContextCompat.getDrawable(context, R.drawable.background_sub_module_text));
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
linearLayout_childItems.addView(textView, layoutParams);
}
}
}
public void removeItem(int position) {
mExampleList.remove(position);
notifyItemRemoved(position);
}
}
Here is a screenshot of my activity
To display data in a RecylerView, you provide a list of items to its adapter.
To add a new element you just need to add the item to the list and call notifyDataSetChange() on the adapter.
For example you can create a new method in you adapter, like that:
public void addItem(ItemPTERM item){
mExampleList.add(item);
notifyDataSetChange();
}
EDIT
So what you can do is to allow your item to have a list of 'variants'.
For example if you select 'Pizza' and want to had 'big' and 'pepperoni', your item will be the pizza and 'big'and 'pepperoni' part of the variants list.
Food {
String name;
List<Variant> variants;
//... Other attributes
public void setVariant(Variant variant){
if (variants == null) // We want to initialise the array only when necessary
variants = new ArrayList<>();
variants.add(variant);
}
#Nullable
public List<Variant> getVariants(){
return variants;
}
}
Variant{
String name;
//... Other attributes
}
When you select a variant you add it to the appropriate Food object.
Approach 1
Then in your adapter, in the onBindViewHolder you can dynamically add the variants to the item;
This way is not the most optimised but should work:
Item layout
<!-- Food Views-->
...
<!-- Container for the variants -->
<LinearLayout
android:id="#+id/variants_list"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content"/>
</LinearLayout>
Variant layout
<?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/variant_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/variant_other_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Adapter
final LayoutInflater mInflater;
List<Food> mFoods;
public FoodAdapter(Context context, ...){
//...
mInflater = LayoutInflater.from(context);
}
#Override
public void onBindViewHolder(#NonNull ExampleViewHolder holder, int position) {
Food food = mFood.get(position);
// Display food attributes
//...
// Clear the container to set fresh info
holder.variantsContainer.removeAllViews();
List<Variant> variants = food.getVariants();
if (variants != null && variants.size() > 0){
// Display the variants when necessary
for(Variant v : variants){
View vView = mInflater.inflate(R.layout.variant_layout);
TextView nameTV = vView.findViewById(R.id.variant_name);
nameTV.setText(v.getName());
// Set other fields values
// ...
holder.variantsContainer.addView(vView);
}
}
}
Approach 2
Another way to do it is to have a list of food object containing a list of variant as above, but to not use this list directly in the adapter.
Instead the adapter will use it's own list which will be both Food and Variant objects mix together. Your adapter should then be able to display 2 kinds of objects. This way is more flexible but you have to recreate the entire adapter list every time you change something.
For instance:
Let say you have 3 Food objects in the list. The first one has 1 variant, the second one none and the third one 2.
Then your adapter will get a list like that:
List<Object> items;
items will contain:
{food1, variant1a, food2, food3, variant3a, variant3b}
And then your adapter will have to use two different layout to display either the Food or the Variant object.
#NonNull
#Override
public ExampleViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == 0) { // if food
View vFood = mInflater.inflate(R.layout.food_layout, parent, false);
return new FoodViewHolder(vFood);
} else { // variant
View vVariant = mInflater.inflate(R.layout.variant_layout, parent, false);
return new VariantViewHolder(vVariant;
}
}
#Override
public int getItemViewType(int position) {
return (mItems.get(position) instanceof Food) ? 0 : 1;
}

Put data in Gson and display it in a listview

It's my first time face to face with Gson. My question will be a long one, hope you'll understand and I there are more problems wich got me stuck for about 1 week.
So, I have a ListView where I get selected items from another Activtity. Under this ListView I have a Button where the seller save items to FireBase, bought by customer.
Now the problem is, each time when seller save bought items to FireBase I want to enumerate(like an increment) each customer and give a customer number. And show the number of customer in TextView in top of the page where number 1 is in the picture. But next day enumeration have to starts from 1. So every day has to starts from 1.
In this ListView, I am counting selected items and calculate sum of prices.
But second problem is I have no idea how to send customer number, counted items and sum of items to another ListView with a card view. I want to put it inside of Gson. I tried something, but I'm completely lost. And my code looks really messy in this moment. Hope you'll understand.
Here is the code where I get selected items and display counted items and sum of items with Toast :
int totalPrice = 0;
for(VanzatorProduse v : Util.getInstance().getVanzatorProduse())
{
int vPrice = Integer.parseInt(v.getPret());
totalPrice = totalPrice + vPrice;
}
Toast.makeText(getApplicationContext(), "Selected products : " + listaProdusePreview.getAdapter().getCount() +"\n"+"Total sum : " + totalPrice , Toast.LENGTH_LONG).show();
Intent sumaProduse = new Intent(FormCumparareActivity.this, VanzatorActivity.class);
sumaProduse.putExtra("sumaProduse", totalPrice);
startActivity(sumaProduse);
String produseSelectate = String.valueOf(listaProdusePreview.getAdapter().getCount());
Intent intent = new Intent(FormCumparareActivity.this, VanzatorActivity.class);
intent.putExtra("produseSelectate", produseSelectate);
startActivity(intent);
Util.getInstance().getVanzatorProduse().removeAll(Util.getInstance().getVanzatorProduse());
Object class for customer number, counted items and sum of items :
public class Card {
private Integer numarCumparator;
private String listaProduse;
private Integer sumaProduse;
public Card(Integer numarCumparator, String listaProduse, Integer sumaProduse) {
this.numarCumparator = numarCumparator;
this.listaProduse = listaProduse;
this.sumaProduse = sumaProduse;
}
public Integer getNumarCumparator() {
return numarCumparator;
}
public void setNumarCumparator(Integer numarCumparator) {
this.numarCumparator = numarCumparator;
}
public String getListaProduse() {
return listaProduse;
}
public void setListaProduse(String listaProduse) {
this.listaProduse = listaProduse;
}
public Integer getSumaProduse() {
return sumaProduse;
}
public void setSumaProduse(Integer sumaProduse) {
this.sumaProduse = sumaProduse;
}
Here is code for listview adapter :
public class CardArrayAdapter extends ArrayAdapter<Card> {
private static final String TAG = "CardArrayAdapter";
private List<Card> cardList = new ArrayList<Card>();
static class CardViewHolder {
TextView line1;
TextView line2;
TextView line3;
}
public CardArrayAdapter(Context context, int textViewResourceId) {
super(context, textViewResourceId);
}
#Override
public void add(Card object) {
cardList.add(object);
super.add(object);
}
#Override
public int getCount() {
return this.cardList.size();
}
#Override
public Card getItem(int index) {
return this.cardList.get(index);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
CardViewHolder viewHolder;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.list_item_card, parent, false);
viewHolder = new CardViewHolder();
viewHolder.line1 = (TextView) row.findViewById(R.id.txtViewNumarCumparator);
viewHolder.line2 = (TextView) row.findViewById(R.id.listaProduse);
viewHolder.line3 = (TextView) row.findViewById(R.id.sumaProduse);
row.setTag(viewHolder);
} else {
viewHolder = (CardViewHolder)row.getTag();
}
Card card = getItem(position);
viewHolder.line1.setText(card.getNumarCumparator());
viewHolder.line2.setText(card.getListaProduse());
viewHolder.line3.setText(card.getSumaProduse());
return row;
}
Layout for card view :
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:descendantFocusability="afterDescendants"
android:orientation="vertical"
android:paddingBottom="15dp"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="15dp">
<TextView
android:id="#+id/txtViewNumarCumparator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="NumarCumparator" />
<TextView
android:id="#+id/listaProduse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="#+id/txtViewNumarCumparator"
android:layout_marginTop="10dp"
android:text="NumarProduse" />
<TextView
android:id="#+id/sumaProduse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginTop="15dp"
android:text="SumaProdsue" />
Here, is my attempt for Gson, I put it in a JSONManager class :
public class JSONManager {
private static JSONManager instance = null;
protected JSONManager() {
// Exists only to defeat instantiation.
}
public static JSONManager getInstance() {
if (instance == null) {
instance = new JSONManager();
}
return instance;
}
//Create list of Cards because we need to show list for date selected
public List<Card> readJSON(String dateFromCalendar) throws JSONException {
String JSON = SharedPreference.getString(Util.get(), SharedPreference.APP_DATA, SharedPreference.JSON_DATA, "");
String numeVanzator = SharedPreference.getString(Util.get(), SharedPreference.USER_DATA, SharedPreference.NUME_VANZATOR,"");
JSONObject jsonObj = new JSONObject(JSON);
JSONArray contacts = jsonObj.getJSONArray("jsonData");
List<Card> listCard = null;
Card card = null;
listCard = new ArrayList<>();
for (int i =0; i< contacts.length();i++) {
JSONObject c = contacts.getJSONObject(i);
String data = c.getString("data");
if (data.equals(dateFromCalendar)){
String numeVanzato = c.getString("numeVanzator");
if (numeVanzato.equals(numeVanzator)){
Integer numarClient = c.getInt("numarClient");
JSONObject detaliiCos = c.getJSONObject("detaliiCos");
Integer sumaProduse = detaliiCos.getInt("sumaProduse");
String produseselectate = c.getString("produseSelectate");
card = new Card(numarClient, produseselectate, sumaProduse);
listCard.add(card);
}
}
}
return listCard;
} }
Code for activity where i tried to get data inside from Gson.
#Override
protected void onResume() {
super.onResume();
c = Calendar.getInstance();
String numeVanzator = SharedPreference.getString(this, SharedPreference.USER_DATA, SharedPreference.NUME_VANZATOR, "");
if (!numeVanzator.equals("")) {
textViewNumeVanzator.setText(numeVanzator);
}
String jsonData = SharedPreference.getString(getApplicationContext(), SharedPreference.APP_DATA, SharedPreference.JSON_DATA, "");
System.out.println("JSON data" + jsonData);
textViewDataCurenta.setText(getDate(c.getTimeInMillis()));
cardArrayAdapter = new CardArrayAdapter(this, R.layout.list_item_card);
Card card = null;
List<Card> listCard = new ArrayList<Card>();
c = Calendar.getInstance();
try {
String date = getDate(c.getTimeInMillis());
listCard = JSONManager.getInstance().readJSON(date);
} catch (JSONException e) {
e.printStackTrace();
}
for (int i = 0; i <= listCard.size()-1; i++) {
card = listCard.get(i);
cardArrayAdapter.add(card);
}
listViewVanzatorActivity.setAdapter(cardArrayAdapter);
}
Right now, everything is working perfectly but when click on save Button nothing appears in next activity and no errors.
Hope, you understand my question, I really need your help. Thank you !!
In your code you created two times Intent for call activity that is not good way.
just remove second intent from this
Intent sumaProduse = new Intent(FormCumparareActivity.this, VanzatorActivity.class);
sumaProduse.putExtra("sumaProduse", totalPrice);
startActivity(sumaProduse);
Intent intent = new Intent(FormCumparareActivity.this, VanzatorActivity.class);
intent.putExtra("produseSelectate", produseSelectate);
startActivity(intent);
now create new bundle and add pass to this with key like this:
Intent intent = new Intent(FormCumparareActivity.this, VanzatorActivity.class);
Bundle bundle = new Bundle();
bundle.put("key",totalPrice);
bundle.put("key",produseSelectate);
intent .putExtras(bundle)
startActivity(intent);
you are getting list from JSON which are not store in shared preferences.
hope you are get it my point.

Android ListView, adding items from database in listview

I have a process in which a user selects a city, then sees medical practitioners in that state.
I have results that show the name of the medical practice:
#Override
protected void onResume() {
super.onResume();
setProgressBarIndeterminateVisibility(true);
Bundle b = getIntent().getExtras();
final String[] resultArr = b.getStringArray("selectedItems");
String location = b.getString("selectedItems");
ParseQuery<ParseUser> query = ParseUser.getQuery();
query.orderByAscending(ParseConstants.KEY_PRACTICE_NAME);
query.findInBackground(new FindCallback<ParseUser>() {
#Override
public void done(List<ParseUser> users, ParseException e) {
setProgressBarIndeterminateVisibility(false);
if (e == null) {
// Success
//store users variable in Parse to mMidwifeLocations
mMidwives = users;
mCurrentUser = ParseUser.getCurrentUser();
//mMidwifeType = ParseUser.getString("usertype");
//store users in string array, locations
String[] midwives = new String[mMidwives.size()];
String[] locations = new String[mMidwives.size()];
String check;
String location;
int i = 0;
for(ParseUser user : mMidwives) {
//get city value from user, assign it to check variable
location = user.getString("city");
check = user.getString("userType");
if (!Arrays.asList(midwives).contains(check) && type != "patient" && Arrays.asList(resultArr).contains(location) ) {
//in locations array, assign practiename values
midwives[i] = user.getString("practicename");
}
}
i++;
I also want to return in the list the primary contact, address, and practice philosophy..what is the best strategy to do this? I am using a simple_list_item_1 list type...there are other list types...wondering if using one of those might be the answer..thanks in advance..
First of all you probably want to do all of this inside the onCreate() method.
Im not to sure if this is what you want but from what i understand i am writing this.
I would personally write down all the data you want in a string-array in your strings.XML
<string-array name="string_array">
<item name ="item1"> item1 </item>
.......
</string-array>
Then I would just grab that data and sort it in order of what order your states are in. So they would match. But by looking at what you have done you have done that with ease
Then creating a custom layout assign each string to it.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
Change this layout how you would like to see your data, also add more textviews to how many you would need.
Now you would need to create a adapter for this listview.
class adapter extends BaseAdapter {
ArrayList<SingleRow> arrayList;
Context context;
adapter(Context contxt) {
context = contxt;
arrayList = new ArrayList<SingleRow>();
Resources res = contxt.getResources();
String[] items= res.getStringArray(R.array.string_array);
for (int i = 0; i < 1; i++) {//Change the 1 in i < 1 to how big your list is.
arrayList.add(new SingleRow(items[i]));
}
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public Object getItem(int position) {
return arrayList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.items_layout, parent, false);
TextView item1 = (TextView) row.findViewById(R.id.txtItem1);
SingleRow temp = arrayList.get(position);
items.setText(temp.items);
return row;
}
}
class SingleRow {
String items;
SingleRow(String items) {
this.items = items;
}
}
After reading the code and analyzing it you would figure out how to add data to the textviews for each row item, and do so by how many you will need.
Now you will have to set the adapter to the listview by...
ListView listView = (ListView) findViewById(R.id.itemListView);
listView.setAdapter(new adapter(getActivity()));
Now you should be able to make a custom listview layout. If any problems occur please just comment on this answer and ill try to fix it.
Good luck.

Categories

Resources