I creating an app that has a custom listview. My problem is it not functioning properly. Look at the image below . That's my custom listview.
Image 1
Then when i want try to search . This happen .
Image 2
As you can see. The text in the Edittext is not matching with the result in custom listview. But when i try to click the result in custom listview. it redirect me on the page of the edittext string. My only problem is the text result in custom listview is not matching with the text input in the edittext.
This is my codes.
ListViewAdapter.java
public class LstViewAdapter extends ArrayAdapter<ArrayList> implements Filterable {
private Context context;
private int resource;
private int id;
private LstViewAdapter adapter;
private ArrayList arrayList;
private FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
private Filter filter;
public LstViewAdapter(Context context, int resource, int id, ArrayList arrayList){
super(context, resource, id, arrayList);
this.context = context;
this.resource = resource;
this.id = id;
this.arrayList = arrayList;
this.adapter = this;
}
// Hold views of the ListView to improve its scrolling performance
private static class ViewHolder {
public TextView type;
public ImageButton removeButton;
}
public View getView(final int position, final View convertView, ViewGroup parent) {
View rowView = convertView;
// Inflate the list_item.xml file if convertView is null
if(rowView==null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
rowView= inflater.inflate(resource, parent, false);
ViewHolder viewHolder = new ViewHolder();
viewHolder.type= (TextView) rowView.findViewById(R.id.txt);
viewHolder.removeButton= (ImageButton) rowView.findViewById(btn_del);
rowView.setTag(viewHolder);
}
final String x = (String) arrayList.get(position);
final String y = arrayList.get(position).toString().trim();
// Set text to each TextView of ListView item
ViewHolder holder = (ViewHolder) rowView.getTag();
holder.type.setText(x);
holder.removeButton.setBackgroundResource(R.drawable.deletes);
holder.removeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
AlertDialog.Builder builder2=new AlertDialog.Builder(context);
builder2.setTitle("Delete Class");
builder2.setMessage("Do you want to delete class "+y+"?");
final EditText input = new EditText(context);
input.setHint("hint");
builder2.setIcon(R.drawable.deletes);
builder2.setPositiveButton("Delete",new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
arrayList.remove(position);
notifyDataSetChanged();
Toast.makeText(v.getContext(), "Class " + y + " has been deleted", Toast.LENGTH_SHORT).show();
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference().child("users").child("teacher").child(user.getUid().toString().trim()).child("class").child(y);
mDatabase.setValue(null);
}
});
builder2.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog dialog = builder2.show();
}
});
return rowView;
}
#Override
public Filter getFilter() {
if (filter == null)
filter = new AppFilter<String>(arrayList);
return filter;
}
private class AppFilter<T> extends Filter {
private String sourceObjects;
public AppFilter(String objects) {
sourceObjects = new AppFilter<String>(arrayList);
synchronized (this) {
sourceObjects.addAll(objects);
}
}
#Override
protected FilterResults performFiltering(CharSequence chars) {
String filterSeq = chars.toString().toLowerCase();
FilterResults result = new FilterResults();
if (filterSeq != null && filterSeq.length() > 0) {
String filter = new AppFilter<String>(arrayList);
for (T object : sourceObjects) {
// the filtering itself:
if (object.toString().toLowerCase().contains(filterSeq))
filter.add(object);
}
result.count = filter.size();
result.values = filter;
} else {
// add all objects
synchronized (this) {
result.values = sourceObjects;
result.count = sourceObjects.size();
}
}
return result;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
// NOTE: this function is *always* called from the UI thread.
String filtered = (String) results.values;
notifyDataSetChanged();
clear();
for (int i = 0, l = filtered.size(); i < l; i++)
add((String) filtered.get(i));
notifyDataSetInvalidated();
}
}
}
MainActivity
public class MyClassesActivity extends AppCompatActivity {
private Button btnCreateClass;
private DatabaseReference mDatabase;
private ListView mUserList;
private ArrayList<String> mUsername = new ArrayList<>();
private FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
private FirebaseAuth auth;
final String userId = FirebaseAuth.getInstance().getCurrentUser().getUid().toString().trim();
String selectedItem, value;
LstViewAdapter arrayAdapter;
private EditText inputSearch;
int textlength = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_classes);
getSupportActionBar().setTitle("My Classes");
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
btnCreateClass = (Button) findViewById(R.id.createclass);
mUserList = (ListView) findViewById(R.id.userlist);
inputSearch = (EditText) findViewById(R.id.inputSearch);
inputSearch.setVisibility(View.GONE);
//get current user
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
arrayAdapter= new LstViewAdapter(this, R.layout.listitem,R.id.txt, mUsername);
mUserList.setAdapter(arrayAdapter);
mDatabase = FirebaseDatabase.getInstance().getReference().child("users").child("teacher").child(user.getUid().toString().trim()).child("class");
mDatabase.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
value = dataSnapshot.getKey().toString().trim();
mUsername.add(value);
arrayAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
btnCreateClass.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MyClassesActivity.this, CreateClassActivity.class);
startActivity(intent);
}
});
mUserList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectedItem = (String) parent.getItemAtPosition(position);
Intent intent = new Intent(MyClassesActivity.this, StudentListActivity.class);
intent.putExtra("secname", selectedItem);
startActivity(intent);
}
});
inputSearch.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
// When user changed the Text
arrayAdapter.getFilter().filter(cs);
arrayAdapter.notifyDataSetChanged();
}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable arg0) {
// TODO Auto-generated method stub
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_class, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (item.getItemId()) {
case android.R.id.home:
// app icon in action bar clicked; goto parent activity.
this.finish();
return true;
default:
if (id == R.id.search) {
inputSearch.setVisibility(View.VISIBLE);
inputSearch.requestFocus();
//Do something
return true;
}
return super.onOptionsItemSelected(item);
}
}
}
listitem.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:paddingBottom="10dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp"
android:descendantFocusability="blocksDescendants">
<TextView
android:id="#+id/txt"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="10dp"
android:layout_alignParentLeft="true" />
<ImageButton
android:id="#+id/btn_del"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:src="#drawable/deletes"
android:onClick="onClick"
android:background="#android:color/transparent"
android:layout_alignParentRight="true" />
Related
I am using contextual action bar in my fragment("UnitsFragment.java") to delete and edit items of recyclerview. But when I come back from recyclerview adapter class("UnitsRv.java"). The context seems to be null. I tried returning context from adapter and it worked for function "prepareSelection". However for "onActionItemClicked" under ActionMode.callback, I need to get context so that I can use alertdialog for editing the items.
The "requireContext()" throws this error: Fragment UnitsFragment{e3a36c8 (b4957397-055a-4b1c-8af2-fee89a3e9b35)} not attached to a context.
Here are my codes.
UnitsFragment.java
public class UnitsFragment extends Fragment {
private static final String TAG = "UnitsFragment";
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
ArrayList<UnitsList> unitsLists = new ArrayList<>();
Activity mcontext = getActivity();
Context dcontext;
ActionMode actionMode;
public static ArrayList<UnitsList> selectionList = new ArrayList<>();
public static boolean isInActionMode = false;
List<String> list = DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao().findUnitNameList();
public UnitsFragment() {
}
private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.menu_item_action, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_edit:
if (selectionList.size() == 1) {
final EditText editText = new EditText(requireContext());
new AlertDialog.Builder(requireContext())
.setTitle("Rename unit name").setView(editText)
.setPositiveButton("Rename", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
UnitsList unitsList = selectionList.get(0);
unitsList.setUnit_name(editText.getText().toString().trim());
isInActionMode = false;
((UnitsRv) mAdapter).changeDataItem(getCheckedLastPosition(), unitsList);
actionMode.finish();
selectionList.clear();
}
})
.create()
.show();
Toast.makeText(getContext(), "Edit", Toast.LENGTH_SHORT).show();
mode.finish();
return true;
}
case R.id.menu_item_delete:
isInActionMode = false;
((UnitsRv) mAdapter).removeData(selectionList);
Toast.makeText(getContext(), "Delete", Toast.LENGTH_SHORT).show();
actionMode.finish();
selectionList.clear();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
}
};
private int getCheckedLastPosition() {
ArrayList<UnitsList> dataSet = UnitsRv.getDataSet();
for (int i = 0; i < dataSet.size(); i++) {
if (dataSet.get(i).equals(selectionList.get(0))) {
return i;
}
}
return 0;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_units, container, false);
setHasOptionsMenu(true);
dcontext = rootView.getContext();
Log.d(TAG, "onCreateView1: " + dcontext);
recyclerView = rootView.findViewById(R.id.rv_units);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
DividerItemDecoration.HORIZONTAL));
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
DividerItemDecoration.VERTICAL));
layoutManager = new GridLayoutManager(getContext(), 2);
recyclerView.setLayoutManager(layoutManager);
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
Log.d(TAG, "onCreateView: " + getContext());
mAdapter = new UnitsRv(mcontext,unitsLists);
recyclerView.setAdapter(mAdapter);
return rootView;
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
inflater.inflate(R.menu.add, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_new:
final View customLayout = getLayoutInflater().inflate(R.layout.add_unit_dialog, null);
final EditText edt_unit_name = customLayout.findViewById(R.id.edt_new_unit_name);
final AlertDialog dialog = new AlertDialog.Builder(getContext())
.setView(customLayout)
.setTitle("Unit name")
.setPositiveButton(android.R.string.ok, null) //Set to null. We override the onclick
.setNegativeButton(android.R.string.cancel, null)
.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialogInterface) {
Button ok_btn = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
Button cancel_btn = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
ok_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String unit_name = edt_unit_name.getText().toString().trim();
if (!TextUtils.isEmpty(unit_name)) {
String old_unit_name = DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao()
.findByUnitName(unit_name);
if (old_unit_name == null) {
DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao()
.insertUnits(new UnitsList(unit_name));
unitsLists.add(new UnitsList(unit_name));
dialog.dismiss();
} else {
edt_unit_name.setError("Unit already exists");
}
} else {
edt_unit_name.setError("Can't be empty");
}
}
});
cancel_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss();
}
});
}
});
dialog.show();
return true;
}
return super.onOptionsItemSelected(item);
}
public void prepareSelection(Context context,int position) {
if(actionMode == null) {
isInActionMode = true;
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
mAdapter = new UnitsRv(context, unitsLists);
Log.d(TAG, "prepareSelection: " + mAdapter);
Log.d(TAG, "prepareSelection1: " + dcontext);
mcontext = (Activity)context;
actionMode = mcontext.startActionMode(actionModeCallback);
mAdapter.notifyDataSetChanged();
if (!selectionList.contains(unitsLists.get(position))) {
selectionList.add(unitsLists.get(position));
}
updateViewCounter();
}
}
private void updateViewCounter() {
int counter = selectionList.size();
if (counter == 1) {
actionMode.setTitle(counter + "item selected");
} else {
actionMode.setTitle(counter + "items selected");
}
}
}
This is my Adapter class.
UnitsRv.java
public class UnitsRv extends RecyclerView.Adapter<UnitsRv.ViewHolder> {
private static final String TAG = "UnitsRv";
private static ArrayList<UnitsList> munitsLists = new ArrayList<>();
UnitsFragment unitsFragment = new UnitsFragment();
Context mcontext;
public UnitsRv(Context context,ArrayList<UnitsList> unitsLists) {
mcontext = context;
munitsLists = unitsLists;
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView unit_name;
public ViewHolder(View v) {
super(v);
unit_name = v.findViewById(R.id.unit_name);
v.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
if (UnitsFragment.isInActionMode){
unitsFragment.prepareSelection(mcontext,getAdapterPosition());
notifyItemChanged(getAdapterPosition());
}
}
#Override
public boolean onLongClick(View view) {
Log.d(TAG, "onLongClick: " + getAdapterPosition());
unitsFragment.prepareSelection(view.getContext(),getAdapterPosition());
return true;
}
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.units_item, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
holder.unit_name.setText(munitsLists.get(position).getUnit_name());
if (UnitsFragment.isInActionMode){
if (UnitsFragment.selectionList.contains(munitsLists.get(position))){
holder.itemView.setBackgroundResource(R.color.colorSelected);
}
}
}
#Override
public int getItemCount() {
return munitsLists.size();
}
public static ArrayList<UnitsList> getDataSet() {
return munitsLists;
}
public void changeDataItem(int position, UnitsList unitsList) {
munitsLists.set(position, unitsList);
notifyDataSetChanged();
}
public void removeData(ArrayList<UnitsList> list) {
for (UnitsList unitsList : list) {
munitsLists.remove(unitsList);
}
notifyDataSetChanged();
}
}
First, you should not create instance of your UnitsFragment inside your adapter.
You can use EventBus to communicate between Activities, Fragments, Adapters, etc.
Or You can do your task using interface. like below.
Create an interface like this
public interface AdapterCallback {
void prepareSelection(Context context,int position);
}
In your UnitsFragment implement the above interface. like the following
public class UnitsFragment extends Fragment implements AdapterCallback{
// your other codes
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_units, container, false);
setHasOptionsMenu(true);
// .... your other codes
Log.d(TAG, "onCreateView: " + getContext());
// modify below line like this
mAdapter = new UnitsRv(mcontext, unitsLists, this); // here you have to pass an extra parameter that will implement your callback method from adapter.
recyclerView.setAdapter(mAdapter);
return rootView;
}
// ... you other codes
#Override
public void prepareSelection(Context context,int position) {
if(actionMode == null) {
isInActionMode = true;
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
mAdapter = new UnitsRv(context, unitsLists,this); // add this as parameter.
Log.d(TAG, "prepareSelection: " + mAdapter);
Log.d(TAG, "prepareSelection1: " + dcontext);
mcontext = (Activity)context;
actionMode = mcontext.startActionMode(actionModeCallback);
mAdapter.notifyDataSetChanged();
if (!selectionList.contains(unitsLists.get(position))) {
selectionList.add(unitsLists.get(position));
}
updateViewCounter();
}
}
// other codes
}
Now, inside your Adapter you need to add an extra argument in constructor of UnitsRv and call your interface method from adapter ussing mAdapterCallback.
public class UnitsRv extends RecyclerView.Adapter<UnitsRv.ViewHolder> {
private static final String TAG = "UnitsRv";
private static ArrayList<UnitsList> munitsLists = new ArrayList<>();
UnitsFragment unitsFragment = new UnitsFragment(); // remove this line
private AdapterCallback mAdapterCallback; // add this line
Context mcontext;
public UnitsRv(Context context,ArrayList<UnitsList> unitsLists, AdapterCallback callback) {
mcontext = context;
munitsLists = unitsLists;
this.mAdapterCallback = callback; // add this line
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView unit_name;
public ViewHolder(View v) {
super(v);
unit_name = v.findViewById(R.id.unit_name);
v.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
if (UnitsFragment.isInActionMode){
mAdapterCallback.prepareSelection(mcontext,getAdapterPosition()); // modify this line
notifyItemChanged(getAdapterPosition());
}
}
#Override
public boolean onLongClick(View view) {
Log.d(TAG, "onLongClick: " + getAdapterPosition());
mAdapterCallback.prepareSelection(view.getContext(),getAdapterPosition()); // modify this line
return true;
}
}
// your other codes....
}
You should check for your fragment is attached or not with isAdded()
place if(!isAdded()) return in your onActionItemClicked. and replace requireContext() with getContext() because requireContext() always throws IllegalStateException if fragment is not attached.
override onAttach method to save context in your fragment.
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.context= context;
}
Hope this helps.
My MainActivity has a RecyclerView adapter, and data to this RecyclerView is added through a AlertDialog which passes the entered text to the MainActivity. The recycler view gets refreshed somehow when the positive button in the dialog is pressed even though I never call notifyItemInserted() or notifyDatasetChange() after passing the new input. I want to know how this happens, my guess is the recyclerview is somehow refreshed after the positive button is pressed in the dialog box
Custom AlertDialog Code:
public class CustomDialog extends AppCompatDialogFragment {
OnNoteAddedListener onNoteAddedListener;
public interface OnNoteAddedListener {
public void onClick(String note);
}
public CustomDialog(OnNoteAddedListener onNoteAddedListener) {
this.onNoteAddedListener = onNoteAddedListener;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
final LayoutInflater inflater = getActivity().getLayoutInflater();
final View dialogLayout = inflater.inflate(R.layout.dialog_box, null);
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
builder.setView(dialogLayout).setPositiveButton("Ok", new DialogInterface.OnClickListener() {#Override
public void onClick(DialogInterface dialog, int id) {
EditText addNote = dialogLayout.findViewById(R.id.note_text);
String note = addNote.getText().toString();
onNoteAddedListener.onClick(note);
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
CustomDialog.this.getDialog().cancel();
}
});
return builder.create();
}
}
Adapter code:
class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>
{
private static final String TAG = "RecyclerViewAdapter";
private List<String> notesList;
private Context mContext;
private SendPositionConnector sendPositionConnector;
public interface SendPositionConnector
{
public void sendPosition(int position);
}
public RecyclerViewAdapter(List<String> notesList, Context mContext)
{
this.notesList = notesList;
this.mContext = mContext;
this.sendPositionConnector = (MainActivity)mContext;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, final int position)
{
Log.d(TAG, "onBindViewHandler: called");
viewHolder.noteContent.setText(notesList.get(position));
viewHolder.parentLayout.setOnLongClickListener(new View.OnLongClickListener(){
#Override
public boolean onLongClick(View view)
{
Log.d(TAG, "onLongClick: long clicked on");
sendPositionConnector.sendPosition(position);
return false;
}
});
}
#Override
public int getItemCount()
{
return notesList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder
{
TextView noteContent;
RelativeLayout parentLayout;
ImageView bullet;
public ViewHolder(#NonNull View itemView)
{
super(itemView);
bullet = itemView.findViewById(R.id.bullet);
noteContent = itemView.findViewById(R.id.text_content);
parentLayout = itemView.findViewById(R.id.parent_layout);
}
}
}
Activity Code:
public class MainActivity extends AppCompatActivity implements RecyclerViewAdapter.SendPositionConnector
{
private static final String TAG = "MainActivity";
private List<String> notesList = new ArrayList<>();
private RecyclerView recyclerView;
private RecyclerViewAdapter adapter;
private int position;
public AgentAsyncTask agentAsyncTask;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.my_recycler_view);
registerForContextMenu(recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
agentAsyncTask = new AgentAsyncTask(notesList, getApplicationContext(), true, new AgentAsyncTask.OnRead(){
#Override
public void onRead(List<String> notesList)
{
if(!notesList.isEmpty())
MainActivity.this.notesList = notesList;
adapter = new RecyclerViewAdapter(notesList, MainActivity.this);
recyclerView.setAdapter(adapter);
}
});
agentAsyncTask.execute();
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.add_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle item selection
switch (item.getItemId())
{
case R.id.add_note:
showDialogBox(item);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
protected void onStop()
{
super.onStop();
new AgentAsyncTask(notesList, getApplicationContext(), false, new AgentAsyncTask.OnRead(){
#Override
public void onRead(List<String> notesList)
{
if(!notesList.isEmpty())
MainActivity.this.notesList = notesList;
}
}).execute();
}
#Override
protected void onDestroy()
{
super.onDestroy();
}
private boolean showDialogBox(MenuItem menuItem)
{
AppCompatDialogFragment dialogFragment = new CustomDialog(new CustomDialog.OnNoteAddedListener(){
#Override
public void onClick(String note)
{
Log.d(TAG, "onClick: "+ note);
notesList.add(note);
}
});
dialogFragment.show(getSupportFragmentManager(),"Adding");
return true;
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo)
{
super.onCreateContextMenu(menu, v, menuInfo);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
#Override
public boolean onContextItemSelected(MenuItem menuItem)
{
switch(menuItem.getItemId())
{
case R.id.delete:
notesList.remove(position);
adapter.notifyItemRemoved(position);
adapter.notifyItemRangeChanged(position, notesList.size());
return true;
default:
return false;
}
}
#Override
public void sendPosition(int position)
{
this.position = position;
}
private static class AgentAsyncTask extends AsyncTask<Void, Void, List<String>>
{
private List<String> notesList;
private boolean flag;
OnRead onRead;
Context context;
AppDataBase dataBase;
private static final String TAG = "AgentAsyncTask";
public interface OnRead
{
public void onRead(List<String> notesList);
}
private AgentAsyncTask(List<String> notesList,Context context,boolean flag, OnRead onRead)
{
this.notesList = notesList;
this.onRead = onRead;
this.flag = flag;
this.context = context;
}
#Override
protected List<String> doInBackground(Void... params)
{
dataBase = Room.databaseBuilder(context, AppDataBase.class, "database-name").build();
if(!flag)
{
Gson gson = new Gson();
Type type = new TypeToken<List<String>>() {}.getType();
String json = gson.toJson(notesList, type);
Log.d(TAG, "doInBackground: "+json);
Notes notes = new Notes();
notes.setNoteContent(json);
notes.setUid(1);
dataBase.notesDao().insertNotes(notes);
return notesList;
}
else
{
Gson gson = new Gson();
String notesListContent = dataBase.notesDao().getNotes();
if(dataBase.notesDao().getCount() != 0)
{
notesList = gson.fromJson(notesListContent, new TypeToken<List<String>>()
{
}.getType());
}
else
{
return notesList;
}
return notesList;
}
}
#Override
protected void onPostExecute(List<String> notesList)
{
super.onPostExecute(notesList);
if(flag)
onRead.onRead(notesList);
}
}
}
What's probably happening is that when the dialog returns, it causes a re-layout of the RecyclerView, which rebinds the views. This is prone to bugs though, since it may not have updated the recycler about stuff like the list length or item view types, etc, so the appropriate notify method should always be used.
When you get the text from the dialog to main activity after pressing the positive button.
Append your list with that new text that you are passing to adapter and call method
adapter.notifyDataSetChanged();
i have a custom listview that has 3 textview for Name, Unique id and Number of Absent and 1 image button for Delete in every list item. I tried to sort the number of absent, it sorts but the order breaks. I saw in internet the comparator and i think that's the solution to my problem but i don't know how to use it. Hoping that someone here can help me.
This is how i add values in my 3 ArrayList (mUid for unique id, MFullname for name, mStatus for Number of absent)
pagod = FirebaseDatabase.getInstance().getReference().child("users").child("teacher").child(user.getUid().toString().trim()).child("class").child(aba).child(message).child("Listofstudents");
pagod.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
String userid = child.child("userid").getValue().toString().trim();
String name = child.child("name").getValue().toString().trim();
mUid.add(userid);
mFullname.add(name);
//studentlist.invalidateViews();
//adapter.notifyDataSetChanged();
if (dataSnapshot.child(userid).child("attendance").exists()) {
pagodnapagod = FirebaseDatabase.getInstance().getReference();
Query query = pagodnapagod.child("users").child("teacher").child(user.getUid().toString().trim()).child("class").child(aba).child(message).child("Listofstudents").child(userid).child("attendance").child("finals").orderByChild("status").equalTo("absent");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
String numberOfStudent ="Number of Absent: "+dataSnapshot.getChildrenCount();
//Toast.makeText(MyClassesActivity.this, numberOfStudent, Toast.LENGTH_SHORT).show();
mStatus.add(numberOfStudent);
//Collections.sort(mStatus, Collections.reverseOrder());
adapters.notifyDataSetChanged();
progressDialog.dismiss();
} else {
String numberOfStudent = "Number of Absent: 0";
mStatus.add(numberOfStudent);
//Collections.sort(mStatus, Collections.reverseOrder());
adapters.notifyDataSetChanged();
progressDialog.dismiss();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
} else {
String numberOfStudent = "Number of Absent: 0";
mStatus.add(numberOfStudent);
//Collections.sort(mStatus, Collections.reverseOrder());
adapters.notifyDataSetChanged();
progressDialog.dismiss();
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
This is my custom adapter.
class Adapters extends BaseAdapter implements Filterable {
private Context context;
private int resource;
private int ids;
private ArrayList arrayList;
private List<String> originalData=null;
private List<String>filteredData=null;
private List<String> userId;
private List<String> status;
private FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
private Adapters.ItemFilter mFilter = new Adapters.ItemFilter();
private LayoutInflater inflater;
public Adapters(Context context, int resource, int id, ArrayList arrayList, ArrayList userId, ArrayList status){
this.context = context;
this.resource = resource;
this.ids = id;
this.arrayList = arrayList;
this.filteredData = arrayList ;
this.originalData = arrayList ;
this.userId = userId;
this.status = status;
inflater = LayoutInflater.from(context);
}
public int getCount() {
return filteredData.size();
}
public Object getItem(int position) {
return filteredData.get(position);
}
public long getItemId(int position) {
return position;
}
// Hold views of the ListView to improve its scrolling performance
private class ViewHolder {
public TextView type;
public TextView uid;
public TextView count;
public ImageButton removeButton;
}
public View getView(final int position, final View convertView, ViewGroup parent) {
View rowView = convertView;
// Inflate the list_item.xml file if convertView is null
if(rowView==null){
rowView = inflater.inflate(R.layout.listitem6, null);
rowView= inflater.inflate(resource, parent, false);
Adapters.ViewHolder viewHolder = new Adapters.ViewHolder();
viewHolder.type= (TextView) rowView.findViewById(R.id.txt);
viewHolder.uid= (TextView) rowView.findViewById(R.id.id);
viewHolder.count= (TextView) rowView.findViewById(R.id.count);
viewHolder.removeButton= (ImageButton) rowView.findViewById(btn_del);
rowView.setTag(viewHolder);
}
final String x = (String) arrayList.get(position);
final String y = arrayList.get(position).toString().trim();
// Set text to each TextView of ListView item
Adapters.ViewHolder holder = (Adapters.ViewHolder) rowView.getTag();
holder.type.setText(x);
holder.uid.setText(x);
holder.count.setText(x);
holder.removeButton.setBackgroundResource(R.drawable.deletes);
holder.removeButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
View parentRow = (View) view.getParent();
ListView listView = (ListView) parentRow.getParent();
final int position = listView.getPositionForView(parentRow);
TextView userId=(TextView) parentRow.findViewById(R.id.id);
TextView userName=(TextView) parentRow.findViewById(R.id.txt);
final String name = userName.getText().toString().trim();
final String uid = userId.getText().toString().trim();
//Toast.makeText(StudentListActivity.this, name +"\n" + uid, Toast.LENGTH_SHORT).show();
final AlertDialog.Builder builder2=new AlertDialog.Builder(context);
final View dialogView = inflater.inflate(R.layout.customdialog, null);
builder2.setView(dialogView);
final EditText input = (EditText) dialogView.findViewById(R.id.edit1);
final TextInputLayout inputs = (TextInputLayout) dialogView.findViewById(R.id.text_field);
TextWatcher watcher = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void afterTextChanged(Editable s) {
inputs.setErrorEnabled(false);
inputs.setError(null);
}
};
input.addTextChangedListener(watcher);
builder2.setTitle("Delete Class");
builder2.setMessage("Do you want to delete "+y+" from this class?");
builder2.setPositiveButton("ok", null);
builder2.setNegativeButton("cancel", null);
builder2.setIcon(R.drawable.deletes);
builder2.setCancelable(false);
final AlertDialog mAlertDialog = builder2.create();
mAlertDialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(final DialogInterface dialog) {
Button a = mAlertDialog.getButton(AlertDialog.BUTTON_POSITIVE);
a.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// TODO Do something
if (input.getText().toString().equalsIgnoreCase("delete")) {
arrayList.remove(position);
notifyDataSetChanged();
Toast.makeText(view.getContext(), y + " has been deleted in this class", Toast.LENGTH_SHORT).show();
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference().child("users").child("teacher").child(user.getUid().toString().trim()).child("class").child(aba).child(message).child("Listofstudents").child(uid);
mDatabase.setValue(null);
ref0 = FirebaseDatabase.getInstance().getReference();
ref0.child("usersclass").orderByChild("userid_classid").equalTo(uid+"-"+message).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child: dataSnapshot.getChildren()) {
String hello = child.getKey();
ref0.child("usersclass").child(hello).setValue(null);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
dialog.dismiss();
notifyDataSetChanged();
restartThis();
} else {
inputs.setError("Enter word DELETE");
}
}
});
Button b = mAlertDialog.getButton(AlertDialog.BUTTON_NEGATIVE);
b.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// TODO Do something
dialog.dismiss();
}
});
}
});
mAlertDialog.show();
}
});
holder.type.setText(filteredData.get(position));
holder.uid.setText(userId.get(position));
holder.count.setText(status.get(position));
return rowView;
}
public Filter getFilter() {
return mFilter;
}
private class ItemFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
String filterString = constraint.toString().toLowerCase();
FilterResults results = new FilterResults();
final List<String> list = originalData;
int count = list.size();
final ArrayList<String> nlist = new ArrayList<String>(count);
String filterableString ;
for (int i = 0; i < count; i++) {
filterableString = list.get(i);
if (filterableString.toLowerCase().contains(filterString)) {
nlist.add(filterableString);
}
}
results.values = nlist;
results.count = nlist.size();
return results;
}
#SuppressWarnings("unchecked")
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredData = (ArrayList<String>) results.values;
notifyDataSetChanged();
}
}
}
When back to previous activity or I get out the app is closed and show this error:
E/RecyclerView: No adapter attached; skipping layout
Within a asycntask in his method onPostExecute I declare a recycleview and RecyclerView.LayoutManager but no have idea what it's wrong. I need your help to solve this problem. Below is my code:
#Override
public void onPostExecute(List<Modules> result) {
if (pDialog.isShowing()){
RecyclerView.LayoutManager Manager =new LinearLayoutManager(DepartureModule.this);
RecyclerView.Adapter adapter = new ModuleAdapter(result);
RecyclerView RVODetails = (RecyclerView) findViewById(R.id.RVODetails);
RVODetails.setLayoutManager(Manager);
RVODetails.setAdapter(adapter);
pDialog.dismiss();
}
and this is my adapter class:
public class ModuleViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
ItemClickListener itemClickListener;
public final ImageButton Actions;
public final ImageView Image;
public final TextView ModuleCode;
public final TextView ModuleDescription;
public final TextView ModuleDate;
public String ModuleIds;
public ModuleViewHolder(View itemView) {
super(itemView);
Image = (ImageView)itemView.findViewById(R.id.logo);
Actions = (ImageButton)itemView.findViewById(R.id.Actions);
//TitleModuleCode = (TextView)itemView.findViewById(R.id.TitleModuleCode);
ModuleCode = (TextView)itemView.findViewById(R.id.ModuleCode);
//TitleModuleDescription = (TextView)itemView.findViewById(R.id.TitleModuleDescription);
ModuleDescription = (TextView)itemView.findViewById(R.id.ModuleDescription);
ModuleDate = (TextView)itemView.findViewById(R.id.ModuleDate);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
this.itemClickListener.OnItemClick(view,getLayoutPosition());
// Toast.makeText(view.getContext(), "POS" + getLayoutPosition()
// , Toast.LENGTH_LONG).show();
}
public void setItemClickListener(ItemClickListener ItemClick){
this.itemClickListener = ItemClick;
}
}
public ModuleAdapter(List<Modules> Items){
this.Items = Items;
}
#Override
public int getItemCount() {
return Items.size();
}
#Override
public ModuleViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.layout_cardview,viewGroup,false);
return new ModuleViewHolder(view);
}
#Override
public void onBindViewHolder(final ModuleViewHolder ViewHolder, final int position) {
context = ViewHolder.itemView.getContext();
Typeface typeface = Typeface.createFromAsset(context.getAssets(),
"fonts/CaviarDreams.ttf");
ViewHolder.Image.setImageResource(Items.get(position).getImages());
ViewHolder.Actions.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ShowPopupMenu(ViewHolder.Actions,position,ViewHolder);
}
});
ViewHolder.ModuleCode.setText(Items.get(position).getModule());
ViewHolder.ModuleCode.setTypeface(typeface); ViewHolder.ModuleDescription.setText(Items.get(position).getDescription());
ViewHolder.ModuleDescription.setTypeface(typeface);
ViewHolder.ModuleDate.setText(Items.get(position).getDate());
ViewHolder.ModuleDate.setTypeface(typeface);
ViewHolder.ModuleIds = Items.get(position).getModuleIds();
ViewHolder.setItemClickListener(new ItemClickListener() {
#Override
public void OnItemClick(View view, int Pos) {
//Toast.makeText(context, "POSITION :" + Pos, Toast.LENGTH_SHORT).show();
}
});
}
private void ShowPopupMenu (final View view, final int position,final ModuleViewHolder holder){
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()){
case R.id.action_modify:
final Connection connectionupdate = new Connection(context,Connection.DATABASE_NAME,null,
Connection.DATABASE_VERSION);
final SQLiteDatabase dbUpdate = connectionupdate.getWritableDatabase();
Typeface typeface = Typeface.createFromAsset(context.getAssets(),"fonts/CaviarDreams.ttf");
AlertDialog.Builder ModifyModule = new AlertDialog.Builder(context);
LayoutInflater modifyinflater = (LayoutInflater)context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
final View viewmodify = modifyinflater.inflate(R.layout.layout_custom_dialog_create_modules,null);
TILM = (TextInputLayout)viewmodify.findViewById(R.id.TILM);
TILM.setTypeface(typeface);
TILD = (TextInputLayout)viewmodify.findViewById(R.id.TILD);
TILD.setTypeface(typeface);
ModuleCodeE = (EditText)viewmodify.findViewById(R.id.ModuleCode);
ModuleCodeE.setTypeface(typeface);
ModuleDescE = (EditText)viewmodify.findViewById(R.id.ModuleDesc);
ModuleDescE.setTypeface(typeface);
ModuleCodeE.setText(Items.get(position).getModule());
ModuleDescE.setText(Items.get(position).getDescription());
final String Id = Items.get(position).getModuleIds();
ModifyModule.setView(viewmodify);
ModifyModule.setIcon(R.drawable.logomini);
ModifyModule.setTitle("Construmuebles FM");
ModifyModule.setMessage(" Modifica los valores en los siguientes campos :");
ModifyModule.setPositiveButton("Actualizar", new DialogInterface.OnClickListener(){
#Override
public void onClick(DialogInterface dialogInterface, int i) {
ContentValues VUpdate = new ContentValues();
VUpdate.put(Database.CamposModuloDetails.KEY_MODULE_CODE,ModuleCodeE.getText().toString()); VUpdate.put(Database.CamposModuloDetails.KEY_MODULE_DESC,ModuleDescE.getText().toString());
long IdUpdate = dbUpdate.update(Database.MODULE_DETAILS_TABLE,VUpdate,Database.CamposModuloDetails
.KEY_MODULE_DETAILS_ID + " = ?",new String []{Id});
new UpdateCardView(context,IdUpdate).execute();
dialogInterface.dismiss();
}
});
ModifyModule.setNegativeButton("Cancelar", new DialogInterface
.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
ModifyModule.show();
return true;
case R.id.action_delete:
new DeleteCardView(context,holder,position).execute();
return true;
}
return false;
}
});
menu.show();
}
class DeleteCardView extends AsyncTask<Void,Void,Long>{
private ProgressDialog pDialog;
ModuleViewHolder holder;
int position;
public DeleteCardView(Context context,ModuleViewHolder holder,int position) {
pDialog = new ProgressDialog(context);
this.holder = holder;
this.position = position;
}
#Override
protected void onPreExecute() {
pDialog.setMessage(" Eliminado registro...");
pDialog.show();
}
#Override
protected Long doInBackground(Void... voids) {
String ModuleIdCardView = holder.ModuleIds;
Connection connection = new Connection(context, Connection.DATABASE_NAME, null,
Connection.DATABASE_VERSION);
long i = connection.DeleteByIdCardView(ModuleIdCardView);
if (i != 0) {
return i;
} else {
return i;
}
}
#Override
protected void onPostExecute(Long Result) {
if (pDialog.isShowing()){
pDialog.dismiss();
Items.remove(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position,Items.size());
if (Items.size()==0){ /**viewPager.setCurrentItem(0);**/ }
}
}
}
}
Rearrange your code as follows
recyclerView = (RecyclerView) findViewById(R.id.RVODetails);
mAdapter = new ModuleAdapter(result);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(mAdapter);
}
I need sort alphabetically in my custom ListView. In list_item, I have TextImage and two TextView (app name, package name) and can't understand how sort by alphabet app name:
My list item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal">
<ImageView
android:id="#+id/app_icon"
android:layout_width="56dp"
android:layout_height="56dp"
android:padding="4dp"
android:scaleType="centerCrop"
android:contentDescription="#null"
tools:src="#mipmap/ic_launcher" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center|center_vertical"
android:orientation="vertical"
android:paddingLeft="8dp">
<TextView
android:id="#+id/tv_app_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textStyle="bold"
tools:text="Application name"/>
<TextView
android:id="#+id/tv_app_package"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textStyle="bold"
tools:text="app.package.name"/>
</LinearLayout>
</LinearLayout>
And my adapter:
public class ListViewAdapter extends ArrayAdapter{
private Context context;
private List mItem;
private PackageManager packageManager;
public ListViewAdapter(Context context, int list_item, List items) {
super(context, R.layout.list_item, items);
this.context = context;
this.mItem = items;
packageManager = context.getPackageManager();
}
public int getCount(){
return ((null != mItem) ? mItem.size() : 0);
}
#Override
public ApplicationInfo getItem(int position) {
return (null != mItem) ? (ApplicationInfo) mItem.get(position) : null;
}
public long getItemId(int position){
return position;
}
public View getView(int position, View convertView, ViewGroup parent){
View view = convertView;
if (null == view) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_item, null);
}
ApplicationInfo data = (ApplicationInfo) mItem.get(position);
if (null != data){
TextView appName = (TextView) view.findViewById(R.id.tv_app_name);
TextView appPackage = (TextView) view.findViewById(R.id.tv_app_package);
ImageView icon = (ImageView) view.findViewById(R.id.app_icon);
appName.setText(data.loadLabel(packageManager));
appPackage.setText(data.packageName);
icon.setImageDrawable(data.loadIcon(packageManager));
}
return view;
}
}
My fragment in which show ListView
public class ResultFragment extends ListFragment {
private PackageManager packageManager = null;
private ListViewAdapter listViewAdapter = null;
private List mItem;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
packageManager = getContext().getPackageManager();
new LoadApplications().execute();
}
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
ApplicationInfo applicationInfo = (ApplicationInfo) mItem.get(position);
try{
Intent intent = packageManager.getLaunchIntentForPackage(applicationInfo.packageName);
if (intent != null){
startActivity(intent);
}
}catch (ActivityNotFoundException e){
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
}catch (Exception e){
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}
private List<ApplicationInfo> checkForLauncherIntent(List<ApplicationInfo> list){
ArrayList mItem = new ArrayList();
for(ApplicationInfo info : list) {
try{
if(packageManager.getLaunchIntentForPackage(info.packageName) != null) {
mItem.add(info);
}
} catch(Exception e) {
e.printStackTrace();
}
}
return mItem;
}
private class LoadApplications extends AsyncTask<Void, Void, Void>{
private ProgressDialog progressDialog = null;
#Override
protected Void doInBackground(Void... params){
mItem = checkForLauncherIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
listViewAdapter = new ListViewAdapter(getActivity(), R.layout.list_item, mItem);
return null;
}
#Override
protected void onPostExecute(Void result){
setListAdapter(listViewAdapter);
progressDialog.dismiss();
super.onPostExecute(result);
}
#Override
protected void onPreExecute(){
progressDialog = ProgressDialog.show(getActivity(), null, "Loading file info...");
super.onPreExecute();
}
}
}
Please help me by sorting my list alphabetically.
From Android Documentation
public abstract android.content.Intent
getLaunchIntentForPackage(java.lang.String packageName)
Returns a
"good" intent to launch a front-door activity in a package. This is
used, for example, to implement an "open" button when browsing through
packages. The current implementation looks first for a main activity
in the category Intent.CATEGORY_INFO, and next for a main activity in
the category Intent.CATEGORY_LAUNCHER. Returns null if neither are
found.
Parameters: packageName - The name of the package to inspect.
Returns: A fully-qualified Intent that can be used to launch the main
activity in the package. Returns null if the package does not contain
such an activity, or if packageName is not recognized.
You need to make some changes in your code
private ArrayList<ResolveInfo> checkForLauncherIntent(List<ApplicationInfo> list){
ArrayList<ResolveInfo> mItems = new ArrayList();
for(ApplicationInfo info : list) {
try{
if(packageManager.getLaunchIntentForPackage(info.packageName) != null) {
Intent intent = packageManager.getLaunchIntentForPackage(info.packageName));
ResolveInfo app = packageManager.resolveActivity(intent,0);
mItems.add(app);
}
} catch(Exception e) {
e.printStackTrace();
}
}
return mItems;
}
in your asn task
private class LoadApplications extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params){
ArrayList<ResolveInfo> mItem = checkForLauncherIntent(packageManager.getInstalledApplications(PackageManager.GET_META_DATA));
listViewAdapter = new ListViewAdapter(ctx, mItem);
return null;
}
#Override
protected void onPostExecute(Void result){
super.onPostExecute(result);
listView.setAdapter(listViewAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ResolveInfo resolveInfo = listViewAdapter.getItem(position);
ActivityInfo activityInfo = resolveInfo.activityInfo;
ComponentName name = new ComponentName(activityInfo.applicationInfo.packageName,activityInfo.name);
Intent intent = new Intent();
intent.setComponent(name);
startActivity(intent);
}
});
}
#Override
protected void onPreExecute(){
super.onPreExecute();
//progressDialog = ProgressDialog.show(getActivity(), null, "Loading file info...");
}
}
In your adapter constructor
public class ListViewAdapter extends BaseAdapter {
private Context context;
private ArrayList<ResolveInfo> mItem;
private PackageManager packageManager;
public ListViewAdapter(Context context, ArrayList<ResolveInfo> items) {
this.context = context;
this.mItem = items;
packageManager = context.getPackageManager();
Collections.sort(mItem,new ResolveInfo.DisplayNameComparator(packageManager));
}
public int getCount(){
return mItem.size();
}
#Override
public ResolveInfo getItem(int position) {
return mItem.get(position);
}
public long getItemId(int position){
return position;
}
public View getView(int position, View convertView, ViewGroup parent){
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(R.layout.testa, null);
}
ResolveInfo app = mItem.get(position);
TextView appName = (TextView) convertView.findViewById(R.id.tv_app_name);
TextView appPackage = (TextView) convertView.findViewById(R.id.tv_app_package);
ImageView icon = (ImageView) convertView.findViewById(R.id.app_icon);
ActivityInfo activity = app.activityInfo;
appPackage.setText(activity.applicationInfo.packageName);
appName.setText(app.loadLabel(packageManager));
icon.setImageDrawable(app.loadIcon(packageManager));
return convertView;
}
}
Find the entire project At Github
First change The Chinese to pinyin you can use the jar pinyin4j-2.5.0.jar
then maybe you can try this method
Arrays.sort(arrayList,String.CASE_INSENSITIVE_ORDER);
Do this it will work
Create a class comparator like this
public class CustomComparator implements Comparator<ApplicationInfo> {
#Override
public int compare(ApplicationInfo o1, ApplicationInfo o2) {
return o1.loadLabel(packageManager).toString().compareTo(o2.loadLabel(packageManager).toString());
}
}
Now use this class in the Async Task where you are creating the adapter
Collections.sort(mItem, new CustomComparator());
listViewAdapter = new ListViewAdapter(context, mItem);
it will sort your list
Let me know in case of more issue
use this method when you need to sort in listview,
Collections.sort(apps, new Comparator<App>() {
#Override
public int compare(App lhs, App rhs) {
//here getTitle() method return app name...
return lhs.getTitle().compareTo(rhs.getTitle());
}
});
Please try this.
public class MainActivity extends AppCompatActivity {
private ArrayList<UserInfo> userInfos;
private CustomListAdapter customListAdapter;
private ListView customListView;
private String[] names={
"3 Khan",
"2 Ahmed",
"1 Iqbal"
};
private String[] professions={
"Rank 1",
"Rank 2",
"Rank 3"
};
private int[] photos={
R.drawable.sample_5,
R.drawable.sample_1,
R.drawable.sample_6
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setSupportActionBar((Toolbar)findViewById(R.id.toolbar));
customListView=(ListView)findViewById(R.id.custom_list_view);
userInfos=new ArrayList<>();
Arrays.sort(names,String.CASE_INSENSITIVE_ORDER);
customListAdapter=new CustomListAdapter(userInfos,this);
customListView.setAdapter(customListAdapter);
getDatas();
customListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(MainActivity.this, "Name : " + names[i] + "\n Profession : " + professions[i], Toast.LENGTH_SHORT).show();
}
});
}
// getting all the datas
private void getDatas(){
for(int count=0;count<names.length;count++){
userInfos.add(new UserInfo(names[count],professions[count],photos[count]));
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_option,menu);
MenuItem menuItem=menu.findItem(R.id.search);
SearchView searchView=(SearchView)menuItem.getActionView();
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
newText=newText.toString();
ArrayList<UserInfo> newUserInfos=new ArrayList<>();
for(UserInfo userInfo:userInfos){
String name=userInfo.getName().toLowerCase();
String profession=userInfo.getProfession().toLowerCase();
if(name.contains(newText) || profession.contains(newText)){
newUserInfos.add(userInfo);
}
}
customListAdapter.filterResult(newUserInfos);
customListAdapter.notifyDataSetChanged();
return false;
}
});
return super.onCreateOptionsMenu(menu);
}
}```