I want to show 2 pieces of data in 1 row of ListView, but I got stuck.
My problem is in showList() method. I can't use my custom ListView XML to show 2 data, I can only show 1 data. I want to show item and itemsemail array in my custom ListView not only item.
Here is my custom ListView adapter code...
private void getDosen() {
//Ketika Aplikasi mengambil data kita akan melihat progress dialog
final ProgressDialog loading = ProgressDialog.show(this,"Mengambil Data","Mohon tunggu..",false,false);
//Logging Interceptor
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
//set Level Log
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ROOT_URL)
.addConverterFactory(GsonConverterFactory.create())//GsonConverter untuk parsing json
.client(httpClient.build())
.build();
RestAPI service = retrofit.create(RestAPI.class);
Call<Model> call = service.loadListDosen();
call.enqueue(new Callback<Model>() { //Asyncronous Request
#Override
public void onResponse(Call<Model> call, Response<Model> response) {
loading.dismiss();
List<Listdosen> dosen = response.body().getListdosen();
//memasukkan data dari varibel dosen ke dosens
dosens = dosen;
//memanggil method untuk menampilkan list
showList();
}
#Override
public void onFailure(Call<Model> call, Throwable t) {
}
});
}
private void showList() {
//String array untuk menyimpan nama semua nama dosen
String[] items = new String[dosens.size()];
String[] itemsemail = new String[dosens.size()];
for (int i = 0; i < dosens.size(); i++) {
items[i] = dosens.get(i).getNama();
itemsemail[i] = dosens.get(i).getEmail();
}
//Membuat Array Adapter for listview
ArrayAdapter adapter = new ArrayAdapter<String>(this, R.layout.activity_dosen_listview, items);
//setting adapter untuk listview
listview.setAdapter(adapter);
}
First of all you need a adapter class that inflates a layout with two TextView that you will bind your data source to.
I have created a layout file and the adapter you can plug into your existing code and I hope it works for you.
This is the layout file.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/items"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:text="#string/app_name"
android:layout_margin="16dp"/>
<TextView
android:id="#+id/itemsEmail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/items"
android:text="#string/app_name"
android:layout_alignBaseline="#+id/items"/>
</RelativeLayout>
For the Adapter class, the code is below
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
public class MyBaseAdapter extends BaseAdapter {
private LayoutInflater layoutinflater;
private List<Listdosen> listStorage;
private Context context;
public MyBaseAdapter(Context context, List<Listdosen> customizedListView) {
this.context = context;
layoutinflater =(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
listStorage = customizedListView;
}
#Override
public int getCount() {
return listStorage.size();
}
#Override
public Listdosen getItem(int position) {
return listStorage.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder listViewHolder;
if(convertView == null){
listViewHolder = new ViewHolder();
convertView = layoutinflater.inflate(R.layout.two_items, parent, false);
listViewHolder.items = (TextView)convertView.findViewById(R.id.items);
listViewHolder.itemEmail = (TextView)convertView.findViewById(R.id.itemsEmail);
convertView.setTag(listViewHolder);
}else{
listViewHolder = (ViewHolder)convertView.getTag();
}
listViewHolder.items.setText(listStorage.get(position).getName());
listViewHolder.itemEmail.setText(listStorage.get(position).getEmail());
return convertView;
}
static class ViewHolder{
TextView items;
TextView itemEmail;
}
}
Adjust your code a bit to fit with the changes.
showList() to showList(List<Listdosen> dosen)
Instead of
ArrayAdapter adapter = new ArrayAdapter<String>(this, R.layout.activity_dosen_listview, items);
use this
ArrayAdapter adapter = new ArrayAdapter<Listdosen>(this, dosen);
Related
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());
}
}
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();
}
In my program I have fetched the data's from the server and view it in a listview. Then from those retrieved data in listview I have to select a string and that string will be passed on to another activity. My data's are retrieved and showed in listview but when I select an item(String) and try to send it to the next activity then instead of that string the package name is passed.
The layout code for retrieving and sending selected String is given below:
public class Doctors_layout extends Fragment implements
AdapterView.OnItemSelectedListener{
public final static String Message = "Sohan";
View myView;
Spinner spinner;
String selectedCity;
Context myContext;
String jsonResult;
JSONObject jsonObject;
JSONArray jsonArray;
String JSON_String;
ContactAdapter contactAdapter;
ListView listView;
Button button;
String send;
public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.doctors_directory, container, false);
myContext = inflater.getContext();
contactAdapter = new ContactAdapter(myContext, R.layout.row_layout);
spinner = (Spinner)myView.findViewById(R.id.spinner);
listView = (ListView)myView.findViewById(R.id.listView);
listView.setAdapter(contactAdapter);
spinner.setOnItemSelectedListener(this);
List<String> city = new ArrayList<String>();
city.add("Choose a City");
city.add("Chittagong");
city.add("Dhaka");
ArrayAdapter<String> aAdapter = new ArrayAdapter<String>(myContext, android.R.layout.simple_spinner_item ,city);
aAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(aAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// here we have to select medical name and intent viewDoctor page
Intent intent = new Intent(myContext, viewDoctor.class);
send = listView.getItemAtPosition(position).toString(); // doesn't retrieve the selected text, intead chooses package name
intent.putExtra(Message, send);
Toast.makeText(myContext, "Listview item "+send, Toast.LENGTH_SHORT).show();
startActivity(intent);
}
});
return myView;
}
And my custom contact adapter class is given below:
package com.example.sohan.patient;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Sohan on 6/9/2016.
*/
public class ContactAdapter extends ArrayAdapter {
List list = new ArrayList();
View row;
ContactHolder contactHolder;
public ContactAdapter(Context context, int resource) {
super(context, resource);
}
public void add(List<Contacts> updatedList) {
list.clear();
list.addAll(updatedList);
notifyDataSetChanged();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public int getCount() {
return list.size();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
row = convertView;
if(row==null){
LayoutInflater layoutInflater = (LayoutInflater)this.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = layoutInflater.inflate(R.layout.row_layout,parent,false);
contactHolder = new ContactHolder();
contactHolder.MedicalName =(TextView) row.findViewById(R.id.textView5);
row.setTag(contactHolder);
}
else{
contactHolder = (ContactHolder)row.getTag();
}
Contacts contacts = (Contacts)this.getItem(position);
contactHolder.MedicalName.setText(contacts.getMedicalName());
return row;
}
static class ContactHolder{
TextView MedicalName;
}
}
Try this, I hope it work...
send = ((TextView) view.findViewById(R.id.textView5)).getText().toString();
or
send = (String) parent.getItemAtPosition(position);
thanks..
send = listView.getItemAtPosition(position).toString();
you are sending a listView object and not actual string.
use:
send = yourListOfStrings.get(position)
UDP:
You are trying to create an adapter with onItemClick listener attacked to it:
contactAdapter = new ContactAdapter(myContext, R.layout.row_layout);
spinner = (Spinner)myView.findViewById(R.id.spinner);
listView = (ListView)myView.findViewById(R.id.listView);
listView.setAdapter(contactAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
right?
So you are suppose to fill(But I haven't found where you are doing this) this adapter with some data:
public void add(List<Contacts> updatedList) {
list.clear();
list.addAll(updatedList);
notifyDataSetChanged();
}
and you want to send a string from from the element of this list to another acitvity, right?
So you need to select an element of this list
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
send = updatedList.get(position).getYourString
inside onItemClickListener
I try to show something into listview using arraylist and simple adapter.
I tried something like below but in my result shows the last names of the arraylist.
What is my wrong i cant understand.
final ListView listView = (ListView) findViewById(R.id.mylist);
ArrayList<HashMap<String, String>> list_of_bookmarks = new ArrayList<HashMap<String, String>>();
HashMap<String, String> b = new HashMap<String, String>();
String[] from = { "php_key","c_key","android_key","hacking_key" };
String[] name_of_bookmarks = { "php","c","android","hacking" };
for(int i=0;i<4;i++)
{
b.put(from[i],name_of_bookmarks[i]);
list_of_bookmarks.add(b);
}
};
int[] to = { R.id.txt1,R.id.txt1,R.id.txt1,R.id.txt1};
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), list_of_bookmarks, R.layout.list_layout, from, to);
listView.setAdapter(adapter);
I just want to show "php","c","android","hacking" in a listview.
And what should be more efficient way to do that.I am a beginner so you may suggest a better way which should i follow
My advice to you would be to create a separate class that extends the Adapter(or some subclass of it)
Here is a simple example of a String array adapter.
package ro.gebs.captoom.adapters;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import antistatic.spinnerwheel.adapters.AbstractWheelTextAdapter;
import com.example.captoom.R;
public class LanguagesAdapter extends AbstractWheelTextAdapter {
// Countries names
private String languages[];
public LanguagesAdapter(Context context) {
super(context, R.layout.lang_item, NO_RESOURCE);
languages = context.getResources().getStringArray(R.array.lang_array);
setItemTextResource(R.id.language_txt);
}
#Override
public View getItem(int index, View cachedView, ViewGroup parent) {
View view = super.getItem(index, cachedView, parent);
return view;
}
#Override
public int getItemsCount() {
return languages.length;
}
#Override
protected CharSequence getItemText(int index) {
return languages[index];
}
}
and the usage is simple just use the method .setAdapter();
Or another example which uses an arrayAdapter:
package apc.example;
import java.util.ArrayList;
import utils.BitmapManager;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class PersonAdapter extends ArrayAdapter<Person> {
Context context;
int layoutResourceId;
ArrayList<Person> data = null;
public PersonAdapter(Context context, int layoutResourceId,
ArrayList<Person> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
ItemHolder holder = null;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ItemHolder();
holder.imgIcon = (ImageView) row.findViewById(R.id.icon);
holder.txtName = (TextView) row.findViewById(R.id.title);
holder.txtDescription = (TextView) row.findViewById(R.id.desc);
row.setTag(holder);
} else {
holder = (ItemHolder) row.getTag();
}
Person bean = data.get(position);
holder.txtName.setText(bean.getName());
holder.txtDescription.setText(bean.getDescription());
Bitmap b = BitmapFactory.decodeResource(context.getResources(), R.drawable.user);
BitmapManager.INSTANCE.setPlaceholder(b);
BitmapManager.INSTANCE.loadBitmap(bean.getUrl(), holder.imgIcon, 80, 80);
return row;
}
public static class ItemHolder {
public ImageView imgIcon;
TextView txtName;
TextView txtDescription;
}
public void updateAdapter(ArrayList<Person> pers){
this.data = pers;
}
}
This is an example of an adapter for a more complex class that has more fields rather than a simple string. But that can easily be modified to ArrayAdapter<String> and then go from there.
Anyways i think it's always a best practice to write your custom adapters for listviews.
Hope this helps!
Main.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="60dp" >
<ListView
android:id="#+id/zone_list"
android:layout_marginBottom="70dp"
android:background="#drawable/batteryborder"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout>
setlanguage.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="60dp">
<TextView
android:id="#+id/tvName"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:textSize="18dp"
android:gravity="center_vertical" />
</LinearLayout>
add in onCreate() of your activity file
ListView listView;
String[] from = { "php_key","c_key","android_key","hacking_key" };
ArrayAdapter arrayAdapter;
listView = (ListView) findViewById(R.id.zone_list);
arrayAdapter = new ArrayAdapter<>(this,R.layout.setlanguage, R.id.tvName, from);
listView.setAdapter(arrayAdapter);
You're reusing the same view in your int[] object.
int[] to = { R.id.txt1,R.id.txt1,R.id.txt1,R.id.txt1};
It looks like it's treating them all as the same object, so each time it adds a new item it changes the previous ones.
In order to use the SimpleAdapter you will need to define each view in the XML with different IDs.
int[] to = { R.id.txt1,R.id.txt2,R.id.txt3,R.id.txt4};
The SimpleAdapter may be simpler in regard to it's internal complexity, but it's definitely not simpler to actually use. With an ArrayAdapter you can just pass it the list of items and let it generate views automatically. It can be any size you need it to be so long as you don't run out of memory. (See below for example)
Once you start working with custom adapters I highly recommend you watch Romain Guy & Adam Powell's I/O talk. It's all a lot to take in when learning, but they do a great job of explaining how ListViews work.
//List of Items
String[] name_of_bookmarks = { "php","c","android","hacking" };
//Create your List object for the ArrayAdapter
//and make it the same size as name_of_books
List<String> listBookmarks = new ArrayList<String>(Array.getLength(name_of_bookmarks));
//Add name_of_bookmarks contents to listBookmarks
Collections.addAll(listBookmarks, name_of_books);
//Create an ArrayAdapter passing it the Context, a generic list item and your list
//An alternative to "this" would be "getApplicationContext()" from your main activity
//or "getActivity()" from a fragment. "getBaseContext()" is not recommended.
ArrayAdapter arrayAdapter = new ArrayAdapter(this, R.layout.list_item_text, listBookmarks);
//Set the adapter to your ListView
final ListView listView = (ListView) findViewById(R.id.mylist);
listView.setAdapter(arrayAdapter);
Try this one
public class MyFragment extends ListFragment{
String[] from = { "php_key","c_key","android_key","hacking_key" };
String[] name_of_bookmarks = { "php","c","android","hacking" };
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
List<HashMap<String, String>> list= new ArrayList<HashMap<String,String>>();
for (int i = 0; i < name_of_bookmarks.length; i++) {
HashMap<String, String> map= new HashMap<String, String>();
map.put("key", name_of_bookmarks[i]);
list.add(map);
}
String[] from = { "key" };
int[] to = { R.id.txt};
SimpleAdapter adapter = new SimpleAdapter(getActivity().getBaseContext(), list, R.layout.list_layout, from, to);
setListAdapter(adapter);
return super.onCreateView(inflater, container, savedInstanceState);
}
}
Whatever You Are Face Problem Exactly I Am Face Of The Problem Called "List
View Display Last Position Of Data Of An Array..."
The Problem Is Generated With Hash Map
final ListView listView = (ListView) findViewById(R.id.mylist);
ArrayList<HashMap<String, String>> list_of_bookmarks = new ArrayList<HashMap<String, String>>();
String[] from = { "php_key","c_key","android_key","hacking_key" };
String[] name_of_bookmarks = { "php","c","android","hacking" };
for(int i=0;i<4;i++)
{
HashMap<String, String> b = new HashMap<String, String>();
b.put(from[i],name_of_bookmarks[i]);
list_of_bookmarks.add(b);
}
};
int[] to = { R.id.txt1,R.id.txt1,R.id.txt1,R.id.txt1};
SimpleAdapter adapter = new SimpleAdapter(getBaseContext(), list_of_bookmarks, R.layout.list_layout, from, to);
listView.setAdapter(adapter);
Try Out This One If Any Doubt Created In Your Mind Then Ask Me Whatever Question Again
Simply You Have To Declared Your Hash Map Inside Your For Loop ...
Using Hash Map Inside Your For Loop Variable 'b' Created Each & Every Time With Considered As An Different Object. And Then Simply Array List Display Different Object Of Hash Map.
You Are Using Same Object To Store Value Of Hash Map And That Variable Was Override With Same Name That's Why you Are Faced The Problem
Thank You...
I try to create a AutoCompleteTextView with custom list items, like showing a picture and a name in one list item. I know how to create it with 1 line of text in a list item but i'm a bit confused on who to do this with more views. I was thing about a ListAdapter and assigning the values to the right views. I'm pretty stuck here. I hope someone can give me a push in the right direction. Question is updated below.
Main activity:
public class AutocompleteCustomActivity extends Activity {
String[] firstView = {"Apple","Banana","Strawberry"};
String[] secondView = {"Green","Yellow","Red"};
AutoCompleteTextView autocomplete;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/*
// Simple 1 line list item
this.autocomplete = (AutoCompleteTextView) findViewById(R.id.autocomplete);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.list_item, firstView);
autocomplete.setAdapter(adapter);
*/
// 2 Lines of text in list item
this.autocomplete = (AutoCompleteTextView) findViewById(R.id.autocomplete);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, R.layout.two_list_items, firstView);
autocomplete.setAdapter(adapter);
}
}
XML:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
UPDATE:
After a lot of hardcore Googling and trial and erroring i came up with this code. I think it's pretty oké but the list items keep showing after selecting one. I know it's the settext that opens the new listitems.
I found this post: Disable Android AutoCompleteTextView after user selects item from drop down
But i don't know what he means :( Anyone knows how to fix this?
package com.sb.autocompletecustom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AutoCompleteTextView;
import android.widget.SimpleAdapter;
public class AutocompleteCustomActivity extends Activity {
AutoCompleteTextView autocomplete;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Data to fill autocomplete
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
Map<String, String> curGroupMap = new HashMap<String, String>();
list.add(curGroupMap);
curGroupMap.put("name", "Banana");
curGroupMap.put("color", "Yellow");
curGroupMap = new HashMap<String, String>();
list.add(curGroupMap);
curGroupMap.put("name", "Strawberry");
curGroupMap.put("color", "Red");
curGroupMap = new HashMap<String, String>();
list.add(curGroupMap);
curGroupMap.put("name", "Strawberry");
curGroupMap.put("color", "Black");
// 2 Lines of text in list item
this.autocomplete = (AutoCompleteTextView) findViewById(R.id.autocomplete);
SimpleAdapter adapter = new SimpleAdapter(this, list, R.layout.two_list_items, new String[] { "name", "color" }, new int[] { R.id.textView1, R.id.textView2 });
autocomplete.setAdapter(adapter);
autocomplete.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> p, View v, int pos, long id) {
Map<String, String> map = (Map<String, String>) p.getItemAtPosition(pos);
String itemName = map.get("name");
autocomplete.setText(itemName);
}
});
}
}
use a custom list adapter. you can inflate the layout and assign the values
public class AutoCompleteCursorAdapter extends CursorAdapter implements Filterable{
private TextView txtDrName, txtDrugName, txtDrugManufacturer;
private int rowResID;
private static Cursor c;
private String autoCompleteTextName;
Context context;
int layout;
public AutoCompleteCursorAdapter(Context context, int layout ) {
super(context, c);
// this.c = c;
this.context = context;
this.autoCompleteTextName = autoCompleteTextName;
this.layout = layout;
}
public long getItemId(int position) {
return position;
}
#Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final LayoutInflater inflater = LayoutInflater.from(context);
View v = inflater.inflate(layout, parent, false);
txtDrName = (TextView)v.findViewById(R.id.txtAutoName) ;
....
}
return v;
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
txtDrName = (TextView) view.findViewById(R.id.txtAutoName) ;
}
#Override
public String convertToString(Cursor cursor) {
// this method dictates what is shown when the user clicks each entry in your autocomplete list
String name="";
name = cursor.getString(cursor.getColumnIndex("prefix"))+" "+cursor.getString(cursor.getColumnIndex("firstName"));
}
return name;
}
#Override
public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
// this is how you query for suggestions
if (getFilterQueryProvider() != null)
{ return getFilterQueryProvider().runQuery(constraint); }
if(constraint!=null){
DataBaseHelper db = new DataBaseHelper(context);
db.openDataBase();
if(autoCompleteTextName.equals(AppConstants.AUTOCOMPLETEDOCTORNAME)){
c = db.getStaffStartingWith((String) constraint);
}
else if (autoCompleteTextName.equals(AppConstants.AUTOCOMPLETEDRUGNAME)){
c = db.getDrugsForStartingWith((String) constraint);
}
c.moveToFirst();
db.close();
}
return c;
}
`