I am using GridView in my alert dialogue with below codes.its giving me error called in title. My codes and more required information is like below.
private void showGotoPageDialog() {
final Dialog mDialog = new Dialog(getActivity());
mDialog.setContentView(R.layout.grid_dialogue);
mDialog.getWindow().setLayout(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
GridView mGridView = (GridView) mDialog.findViewById(R.id.grid_dialog);
ArrayList<String> tmp = new ArrayList<>(mPageOptions.length);
for(int i = 0; i < mPageOptions.length; i++)
{
tmp.add(mPageOptions[i].split(" ")[1]);
}
CustomAdapter adapter = new CustomAdapter(getActivity(), tmp, mPageIndx);
//ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, tmp);
mGridView.setAdapter(adapter);
mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int item, long l) {
mDialog.dismiss();
mPageIndx = item + 1;
updateQuotesListServer();
updatePageInfo();
}
});
mDialog.show();
TextView dismiss = (TextView) mDialog.findViewById(R.id.dialog_dismiss);
dismiss.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mDialog.dismiss();
}
});
}
and Adapter like this
private class CustomAdapter extends BaseAdapter
{
private ArrayList<String> list;
private LayoutInflater inflater;
private int currentPage;
CustomAdapter(Activity activity, ArrayList<String> list, int currentPage)
{
this.list = new ArrayList<>();
this.list.addAll(list);
inflater = (LayoutInflater) activity.getSystemService(AppCompatActivity.LAYOUT_INFLATER_SERVICE);
this.currentPage = currentPage;
}
public void setCurrentPage(int currentPage)
{
this.currentPage = currentPage;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return i;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = View.inflate(getActivity(),R.layout.dialogue_item, null);
TextView txt = (TextView) view.findViewById(R.id.textview_dialogue);
txt.setText(list.get(i));
if(i == currentPage-1)
{
txt.setTextColor(Color.BLACK);
}
return view;
}
}
its giving me warning on this line
view = View.inflate(getActivity(),R.layout.dialogue_item, null);
warning is like below
Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling.
My code is working fine as expected and I am not facing any issue. I want know that What changes require for fix this and what is benefit of it ? Let me know if someone can help me for come out from this and solve my doubt.
Thanks
View adapter is built so that instead of creating a new view for each item, views that scroll off screen can be reused (they are passed in via the 2nd argument of getView). You are being warned that you should try to reuse these views instead of always inflating new ones. Change the line to
if (view == null) view = View.inflate(getActivity(),R.layout.dialogue_item, null);
Try this instead
view = View.inflate(R.layout.dialogue_item, viewGroup, null);
If not necessary, in other words if view is not null, then it is not necessary to call the following line in getView() method :
view = inflter.inflate(R.layout.spinner_rect, null);
the problem arises the same wrong source code available on the web:
https://abhiandroid.com/ui/custom-spinner-examples.html
https://demonuts.com/android-custom-spinner-image/
apply my solution for correctness
Thanks for useful answers: I had the same error but I was using view binding. Resolved using this approach.
Related
This is example from Android for beginners book. I think that problem is with mNoteAdapter but I can't find where it exactly is. I tried to use adapter from other source and it was working(I mean click) so I could see at least log in logcat. How does mNoteAdapter affect on possibility of seeing users click by app? How can I find where problem is?
mNoteAdapter = new NoteAdapter();
ListView listNote = (ListView) findViewById(R.id.listView);
listNote.setAdapter(mNoteAdapter);
listNote.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> adapter, View view, int
whichItem, long id) {
Log.e("CLICK", "CliCK");
}
});
}
Here is a piece of NoteAdapter class
public class NoteAdapter extends BaseAdapter {
List<Note> noteList = new ArrayList<Note>();
#Override
public int getCount() {
}
#Override
public Note getItem(int whichItem) {
}
#Override
public long getItemId(int whichItem) {
}
#Override
public View getView(int whichItem, View view, ViewGroup viewGroup) {
if (view == null) {
LayoutInflater inflater = (LayoutInflater)
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.listitem, viewGroup, false);
}
TextView txtTitle = (TextView) view.findViewById(R.id.txtTitle);
ImageView ivImportant = (ImageView) view.findViewById(R.id.imageViewImportant);
Note tempNote = noteList.get(whichItem);
if (!tempNote.isImportant()) {
ivImportant.setVisibility(View.GONE);
}
txtTitle.setText(tempNote.getTitle());
return view;
}
public void addNote(Note n) {
}
}
There are many ways to display items as list on Android..
--> ListView, RecyclerView etc.
Lists need a source right? Let's assume that your source is an array of 1000 elements. Your ListView has to have as many columns to display all of them right?
Adapter is responsible for taking the array, and assigning each element to every list placeholders
This row was added to the top of .xml file
android:descendantFocusability="blocksDescendants"
I have a custom adapter where i display text and a spinner. I have tried to store the state of each spinner so as to display the same items when the activity is open again i have tried different things but i have not been successfull. Please how do i accomplish this thanks. This is the latest thing i have tried
CustomListAdapter(Context context, ArrayList<String> subjects) {
super(context, R.layout.custom_list_view, subjects);
}
#NonNull
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater layoutInflater = LayoutInflater.from(getContext());
View customView = layoutInflater.inflate(R.layout.custom_list_view, parent, false);
singleSubject = getItem(position);
TextView singleText = (TextView) customView.findViewById(R.id.listSubjectsMyCourses);
colorLayout = (LinearLayout)customView.findViewById(R.id.colorForSubjects);
relativeLayout = (RelativeLayout)
customView.findViewById(R.id.relativeForView);
parentLayout = (RelativeLayout)
customView.findViewById(R.id.parentLayout);
points = new ArrayList<>();
selected = new ArrayList<>();
selectedsttring = new ArrayList<>();
customView.findViewById(R.id.textViewForGrades);
tinyDB = new TinyDB(getContext());
spinnerForGradePoints = (Spinner)customView.findViewById(R.id.spinnerForGrades);
final ArrayAdapter<String> gradePointAdapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_dropdown_item_1line, UserCourseSelection2.userSubjectGradePoint);
spinnerForGradePoints.setAdapter(gradePointAdapter);
spinnerForGradePoints.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
selectedItempos = adapterView.getSelectedItemPosition();
String getSelectedItem = adapterView.getItemAtPosition(i).toString();
tinyDB.putInt("selected", selectedItempos);
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
singleText.setText(singleSubject);
colorLayout.setBackgroundColor(UserCourseSelection2.userSubjectsListColor.get(position));
int getSelected = tinyDB.getInt("selected");
spinnerForGradePoints.setSelection(getSelected);
return customView;
}
SharedPreferences is the way if you dont want to use dependency injection like dagger or some kind of custom local cache on the application level.
For SharedPreferences in spinner check this answer:
https://stackoverflow.com/a/13431729/5577679
I've been working on creating a single choice ListView populated by a custom ArrayAdapter (which works), except I need to set a pre-determined RadioButton in the ListView as setChecked(true) when the activity launches.
I'm populating my ListView with a List<Server> servers object at inflation that contains a boolean 'default_server' used to determine which row / RadioButton should be setChecked(true).
Selecting the various ListView items after the activity has launched correctly flags the specific RadioButton as setChecked(true) in Single Choice mode as desired.
My code:
ServerActivity.java
public class ServersActivity extends FragmentActivity
//FragmentActivity needed to display dialog fragment when ListView item clicked
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.server_list);
servers = getServers();
lv = (ListView) findViewById(android.R.id.list);
lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
adapter = new ServerActivityArrayAdapter(this, R.layout.server_list_item, servers);
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// show dialog if not long clicked
if (!longClicked) {
lv.setItemChecked(position, true);
showServerDialog(position);
}
}
});
}
ServerActivityArrayAdapter.java
public class ServerActivityArrayAdapter extends ArrayAdapter<Server> {
private int layout;
private int mSelectedPosition = -1;
private RadioButton mSelectedRB;
private static LayoutInflater inflater;
public ServerActivityArrayAdapter(Context context, int layout, List<Server> servers) {
super(context, layout, servers);
ListArrays listArrays = new ListArrays(context);
this.layout = layout;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
private static class ServerViewHolder {
private TextView textView;
private RadioButton radioButton;
public ServerViewHolder() {
// EMPTY DEFAULT CONSTRUCTOR
}
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final Server server = this.getItem(position);
final ServerViewHolder viewHolder;
if (convertView == null) {
convertView = inflater.inflate(layout, parent, false);
viewHolder = new ServerViewHolder();
viewHolder.textView = (TextView) convertView.findViewById(R.id.tvServerName);
viewHolder.radioButton = (RadioButton) convertView.findViewById(R.id.rbDefault);
convertView.setTag(viewHolder);
} else {
viewHolder = (ServerViewHolder) convertView.getTag();
}
// TODO: SET THE DEFAULT SERVER
viewHolder.radioButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (position != mSelectedPosition && mSelectedRB != null) {
mSelectedRB.setChecked(false);
}
mSelectedPosition = position;
notifyDataSetChanged();
mSelectedRB = (RadioButton) v;
server.setDefaultServer(mSelectedRB.isChecked());
}
});
if (mSelectedPosition != position) {
viewHolder.radioButton.setChecked(false);
} else {
viewHolder.radioButton.setChecked(true);
if (mSelectedRB != null && viewHolder.radioButton != mSelectedRB) {
mSelectedRB = viewHolder.radioButton;
}
}
viewHolder.textView.setText(server.getName());
return convertView;
}
}
Again, my List<Server> servers object is populating the ListView, the subsequent dialog popups (when a row is clicked) correctly and the RadioButtons on each row are currently functioning in Single Choice mode. I'm using server.setDefaultServer(mSelectedRB.isChecked()); in the setOnClickListener of ServerActivityArrayAdapter to update which server has default_server(true).
Everything I've tried so far in the ServerActivityArrayAdapter seems to break the Single Choice mode requirement of the RadioButton. How can I fix this?
I did go back and implement Shared Preferences into my project as Mridul suggested, but the solution really didn't require them.
Basically, I updated the constructor of my ServerActivityArrayAdapter class to let me pass the ID of the default server from the ServerActivity class when it's created. Also, I set mSelectionPostion = defServer, so the correct RadioButton in my ListView is checked when everything is inflated.
public ServerActivityArrayAdapter(Context context, int layout, List<Server> servers, int defServer) {
super(context, layout, servers);
ListArrays listArrays = new ListArrays(context);
this.layout = layout;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mSelectedPosition = defServer;
}
I used fragment in my app and i'm using SQLite to save local data. But when I finished saving data, and I swipe the page, my listView is not refreshed with new data (Only showing old data). I have tried to provide a method notifyDataSetChanged() on my adapter, but it's not working.
My Base Adapter class :
public class LocalDataAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<LocalDataBean> data;
private static LayoutInflater inflater = null;
public LocalDataAdapter(Activity a, ArrayList<LocalDataBean> d) {
activity = a;
data = d;
inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return data.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public void setItem(ArrayList<LocalDataBean> data){
this.data = data;
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = inflater.inflate(R.layout.list_item, null);
TextView nama_konsumen = (TextView) v.findViewById(R.id.nama_konsumen);
TextView no_telp = (TextView) v.findViewById(R.id.no_telp);
TextView no_hp_cdma = (TextView) v.findViewById(R.id.no_hp_cdma);
TextView no_hp_gsm = (TextView) v.findViewById(R.id.no_hp_gsm);
LocalDataBean obj = (LocalDataBean) getItem(position);
nama_konsumen.setText(obj.getNamaKonsumen());
no_telp.setText(obj.getNoTelp());
no_hp_cdma.setText(obj.getNoCMDA());
no_hp_gsm.setText(obj.getNoGSM());
return v;
}
}
My fragment class :
public class LocalDataFragment extends Fragment {
View view;
Activity act;
SQLHandlerBean utilSql;
ArrayList<LocalDataBean> localdatabean = new ArrayList<LocalDataBean>();
LocalDataAdapter adapter;
ListView list;
public static final String TAG = LocalDataFragment.class.getSimpleName();
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.layout_local_data, null);
act = getActivity();
list = (ListView) view.findViewById(R.id.listViewLocalData);
utilSql = new SQLHandlerBean(this.act);
adapter = new LocalDataAdapter(act, localdatabean);
localdatabean = new ArrayList<LocalDataBean>();
list.setAdapter(adapter);
if (utilSql.ReadAllLocalData().size() < 1) {
Toast.makeText(act, "DATA EMPTY!", Toast.LENGTH_LONG).show();
} else {
localdatabean = utilSql.ReadAllLocalData();
Log.e(TAG, "TOTAL DATA : "+localdatabean.size());
adapter.setItem(localdatabean);
adapter.notifyDataSetChanged();
}
return view;
}
}
Is adapter.notifyDataSetChanged() placement correct?
No, the placement is not in the right place.
As you have placed the notifyDataSetChanged() inside of the onCreateView() method. It will be only invoked 1st time the fragment is launched.
Rather you can add a refresh button in your layout (or in you action bar). And along with the insertion/deletion method of the data, place the notifyDataSetChanged() at the bottom of the click event of that button.
By doing this user can refresh the page whenever they want.
And if you want to refresh the page by swipping the view then, SwipeRefreshLaoyout could be a perfect alternative.
You can check this blog.
I have a ArrayAdapter for a GridView, As you can see in the code I populate the GridView using the getView method with a custom view that called: GridViewCell.
Now on a click of this custom view there is a FlipAnimation method run that works great for the clicked view. What I want to achieve is to run the same animation method for all the other custom views currently in the adapter, so I need to get the instances of all the other views (there are 4 view in the adapter, so I need to get instances of the other 3).
public class AnswersGridAdapter extends ArrayAdapter<Answer>
{
private static final String TAG = AnswersGridAdapter.class.getSimpleName();
private ArrayList<Answer> answersList;
private Context context;
private MainActivity activity;
private QuestionGridFragment fragment;
private View view;
public AnswersGridAdapter(QuestionGridFragment fragment, Context context, int textViewResourceId, ArrayList<Answer> answersList)
{
super(context, textViewResourceId, answersList);
this.answersList = new ArrayList<Answer>();
this.answersList.addAll(answersList);
this.context = context;
this.activity = (MainActivity)context;
this.fragment = fragment;
}
public View getView(final int position, View convertView, ViewGroup parent)
{
final View view = new GridViewCell(context);
if (answersList.get(position).isChecked())
{
((GridViewCell)view).FlipToBackWithoutAnimation();
}
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
((GridViewCell)view).FlipAnmiation();
if (answersList.get(position).isChecked())
{
answersList.get(position).setChecked(false);
}
else
{
answersList.get(position).setChecked(true);
}
activity.getEstimatedCostTextView().setText(String.valueOf(activity.getEstimatedCost()));
fragment.flipOtherChosenAnswer(position);
}
});
((GridViewCell)view).setTextToTitleTextView(answersList.get(position).getAnswerText());
return view;
}
}
I was trying to do something like this:
public void flipOtherChosenAnswer(int position)
{
int cellCount = answersAdapter.getCount();
for (int i=0; i < cellCount; i++ )
{
((GridViewCell)answersAdapter.getView(i, null, null)).FlipAnmiation();
}
}
but that didn't help me. How can this be done?
if you manages click in the onItemClick, the first argument should be the AdapterView, and trought it you can access its children.
int count = adpaterViewInstance.getChildCount();
for (int i = 0; i < count; i++) {
View childAt = adpaterViewInstance.getChildAt(i);
}
Edit:
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> adpaterViewInstance, View v, int position, long id) {
Toast.makeText(HelloGridView.this, "" + position, Toast.LENGTH_SHORT).show();
}
});
Well this is what I finally did, from the fragment that contains the GridView I run this method, that get all the children of the GridView and run the animation method on each one of them.
public void flipOtherChosenAnswer(int position)
{
int cellCount = gvQuestionAnswers.getChildCount();
for (int i=0; i < cellCount; i++ )
{
if (i != position && qustionAnswersList.get(i).isChecked())
{
((GridViewCell)gvQuestionAnswers.getChildAt(i)).FlipAnmiation();
}
}
}