I have a custom List Adapter that has a question in a Text View and four options as an answer in Radio Buttons. All the Radio Buttons are bound together in a Radio Group.
The problem is that I cannot keep track of the buttons that are checked.On scrolling the buttons get checked on random.
How can I store the radio buttons that are checked for a particular
public class MCQAdapter extends ArrayAdapter {
public MCQAdapter(Activity context, ArrayList<MCQ> mcq) {
super(context, 0, mcq);
}
#NonNull
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View listItemView = convertView;
if (listItemView == null) {
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.activity_mcqlist, parent, false);
}
final MCQ currentContent = (MCQ) getItem(position);
TextView content = (TextView) listItemView.findViewById(R.id.Question_Block);
content.setText(currentContent.getQuestion());
RadioGroup rg = (RadioGroup) listItemView.findViewById(R.id.Radio_Group);
final RadioButton rb1 = (RadioButton) listItemView.findViewById(R.id.Option1_Block);
rb1.setText(currentContent.getOptionA());
final RadioButton rb2 = (RadioButton) listItemView.findViewById(R.id.Option2_Block);
rb2.setText(currentContent.getOptionB());
final RadioButton rb3 = (RadioButton) listItemView.findViewById(R.id.Option3_Block);
rb3.setText(currentContent.getOptionC());
final RadioButton rb4 = (RadioButton) listItemView.findViewById(R.id.Option4_Block);
rb4.setText(currentContent.getOptionD());
return listItemView;
}
}
public class MCQ {
String question,optionA,optionB,optionC,optionD,answer,userAnswer;
public MCQ(String quest,String a,String b,String c, String d,String ans){
question = quest;
optionA = a;
optionB = b;
optionC = c;
optionD = d;
answer = ans;
}
public String getQuestion(){
return question;
}
public String getOptionA() {
return optionA;
}
public String getOptionB() {
return optionB;
}
public String getOptionC() {
return optionC;
}
public String getOptionD() {
return optionD;
}
public String getAnswer() {
return answer;
}
public String getUserAnswer() {
return userAnswer;
}
public void setUserAnswer(String userAnswer) {
this.userAnswer = userAnswer;
}
}
public class PropertiesOfConstructionMaterail extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_properties_of_construction_materail);
final ArrayList<MCQ> mcq = new ArrayList<MCQ>();
//Creating Different Instance Of MCQ to genarte various questions for Properties of Consrtuction Material
mcq.add(new MCQ("The property of material by which it can be beaten or rolled into thin plates, is called ?",
"Malleability","Ductility","Plasticity","Elasticity","Malleability"));
mcq.add(new MCQ("The property by which a body returns to its original shape after removal of the force, is called ?",
"Plasticity","Elasticity","Ductility","Malleability","Elasticity"));
mcq.add(new MCQ("The property of a material by which it can be drawn into smaller section due to tension, is called ?"
,"Plasticity","Ductility","Elasticity","Malleability","Ductility"));
MCQAdapter adapter = new MCQAdapter(this,mcq);
ListView listView = (ListView) findViewById(R.id.list);
listView.setAdapter(adapter);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_mcqlist"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.silen.civilengineeringmcq.MCQList"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/Question_Block"
android:textSize="18dp"
android:textStyle="bold"/>
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/Radio_Group">
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/Option1_Block"
android:checked="false"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/Option2_Block"
android:checked="false"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/Option3_Block"
android:checked="false"/>
<RadioButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/Option4_Block"
android:checked="false"/>
</RadioGroup>
You should create a wrapper around your PoJo class (MCQ), name it ViewModel, which store the current state of view inside adapter. In your case that state is a state of radio buttons.
It will looks like:
class ViewModel extends MCQ {
MCQ mcq;
int radioButtonSelectedId;
public ViewModel(MCQ mcq) {
this.mcq = mcq;
this.radioButtonSelectedId = R.id.Option1_Block;
}
public void setRadioButtonSelectedId(int id) {
this.id = id;
}
public int getRadioButtonSelectedId() {
return id;
}
//delegates to mcq getter/setter methods
}
Your getView method:
public View getView(int position, View convertView, ViewGroup parent) {
//your logic above
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
viewModel.setRadioButtonSelectedId(checkedId);
}
});
//same for other radio buttons
rb1.setChecked(viewModel.getRadioButtonSelectedId() == R.id.Option1_Block);
//your logic below
}
So as i mention above, your array list inside adapter would contain ViewModels wrappers, not MCQ classes directly
final ArrayList<ViewModel> mcqList = new ArrayList<>();
MCQ mcq = new MCQ("The property of material by which it can be beaten or rolled into thin plates, is called ?",
"Malleability","Ductility","Plasticity","Elasticity","Malleability")
mcqList.add(new ViewModel(mcq));
I think you should get an option
Related
I'm trying to upgrade my PopupMenu so it would come with icons and custom styles.
I have created a new layout for it
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout
android:id="#+id/layout_sharea"
android:background="#drawable/share"
android:paddingLeft="10.0dip"
android:paddingRight="10.0dip"
android:layout_width="wrap_content"
android:layout_height="50.0dip"
android:onClick="share">
<TextView
android:id="#+id/sharetexta"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/share"
android:drawableLeft="#drawable/share_button"
android:drawablePadding="10.0dip"
android:layout_centerVertical="true" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/layout_shareb"
android:background="#drawable/share"
android:paddingLeft="10.0dip"
android:paddingRight="10.0dip"
android:layout_width="wrap_content"
android:layout_height="50.0dip"
android:layout_below="#+id/layout_sharea"
android:onClick="share">
<TextView
android:id="#+id/sharetextb"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/share"
android:drawableLeft="#drawable/share_button"
android:drawablePadding="10.0dip"
android:layout_centerVertical="true" />
</RelativeLayout>
</RelativeLayout>
I want the PopupMenu to be customized (to be this layout) like in this picture
A PopupMenu is meant for displaying Menus and there really isn't a good way of customizing the appearance of the menu items. If you want something more flexible, your answer is ListPopupWindow.
private static final String TITLE = "title";
private static final String ICON = "icon";
private List<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();
// Use this to add items to the list that the ListPopupWindow will use
private void addItem(String title, int iconResourceId) {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put(TITLE, title);
map.put(ICON, iconResourceId);
data.add(map);
}
// Call this when you want to show the ListPopupWindow
private void showListMenu(View anchor) {
ListPopupWindow popupWindow = new ListPopupWindow(this);
ListAdapter adapter = new SimpleAdapter(
this,
data,
android.R.layout.activity_list_item, // You may want to use your own cool layout
new String[] {TITLE, ICON}, // These are just the keys that the data uses
new int[] {android.R.id.text1, android.R.id.icon}); // The view ids to map the data to
popupWindow.setAnchorView(anchor);
popupWindow.setAdapter(adapter);
popupWindow.setWidth(400); // note: don't use pixels, use a dimen resource
popupWindow.setOnItemClickListener(myListener); // the callback for when a list item is selected
popupWindow.show();
}
Here is my demo for custom ListPopupWindow by custom adapter
Model
public class ListPopupItem {
private String title;
private int imageRes;
public ListPopupItem(String title, int imageRes) {
this.title = title;
this.imageRes = imageRes;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getImageRes() {
return imageRes;
}
}
ListAdapter
public class ListPopupWindowAdapter extends BaseAdapter {
private List<ListPopupItem> items;
public ListPopupWindowAdapter(List<ListPopupItem> items) {
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public ListPopupItem getItem(int i) {
return items.get(i);
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list_popup, null);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tvTitle.setText(getItem(position).getTitle());
holder.ivImage.setImageResource(getItem(position).getImageRes());
return convertView;
}
static class ViewHolder {
TextView tvTitle;
ImageView ivImage;
ViewHolder(View view) {
tvTitle = view.findViewById(R.id.text);
ivImage = view.findViewById(R.id.image);
}
}
}
item_list_popup.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:ignore="ContentDescription"
tools:src="#mipmap/ic_launcher"
/>
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
tools:text="Title"
/>
</LinearLayout>
Finally, show ListPopupWindow
(In this demo, I show MATCH_PARENT popup here, you can show a specific with for popup (eg: 100px, 200px,...)
If you set popup width = WRAP_CONTENT, popup width will equals ANCHOR width)
private void showListPopupWindow(View anchor) {
List<ListPopupItem> listPopupItems = new ArrayList<>();
listPopupItems.add(new ListPopupItem("Menu 1", R.mipmap.ic_launcher));
listPopupItems.add(new ListPopupItem("Menu 2", R.mipmap.ic_launcher));
listPopupItems.add(new ListPopupItem("Menu 3", R.mipmap.ic_launcher));
final ListPopupWindow listPopupWindow =
createListPopupWindow(anchor, ViewGroup.LayoutParams.MATCH_PARENT, listPopupItems);
listPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
listPopupWindow.dismiss();
Toast.makeText(MainActivity.this, "clicked at " + position, Toast.LENGTH_SHORT)
.show();
}
});
listPopupWindow.show();
}
private ListPopupWindow createListPopupWindow(View anchor, int width,
List<ListPopupItem> items) {
final ListPopupWindow popup = new ListPopupWindow(this);
ListAdapter adapter = new ListPopupWindowAdapter(items);
popup.setAnchorView(anchor);
popup.setWidth(width);
popup.setAdapter(adapter);
return popup;
}
Example using
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showListPopupWindow(view);
}
});
DEMO
I set up a Listview in Android Studio but need help with coding a OnItemClickListner.
I have tried the code, but doesn't seem to work.
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView listView = (ListView) findViewById(R.id.list_view);
ArrayList<Object> list = new ArrayList<>();
list.add(new LTCItem("30.06 Sign Violations","Submit A Complaint To Texas Attorney General",R.drawable.gavel));
list.add(new LTCItem("U.S. & Texas LawShield","Legal Defense For Self Defense",R.drawable.lawshield));
listView.setAdapter(new LTCAdapter(this, list));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
}
});
}
}
Below is my list_view file. Where in the file do block descendantFocusability as suggested? Do I put it under listView? Sorry I am learning .
<?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"
android:alwaysDrawnWithCache="true"
android:background="#000000"
android:padding="8dp">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="#+id/itemListViewImgIcon"
android:layout_width="50dp"
android:layout_height="50dp"
android:contentDescription="#+id/itemListViewImgIcon"
android:src="#mipmap/ic_launcher" />
<TextView
android:id="#+id/itemListViewTxtTopicName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
<TextView
android:id="#+id/itemListViewTxtTopicSubtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#id/itemListViewTxtTopicName"
</RelativeLayout>
Ok I added the adapter code which is a Java Class item. Where do I add the code here?
public class LTCAdapter extends BaseAdapter {
ArrayList<Object> list;
private static final int LTC_Item = 0;
private static final int HEADER = 1;
private LayoutInflater inflater;
public LTCAdapter(Context context, ArrayList<Object> list) {
this.list = list;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getItemViewType(int position) {
if (list.get(position) instanceof LTCItem) {
return LTC_Item;
} else {
return HEADER;
}
}
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int i) {
return list.get(i);
}
#Override
public long getItemId(int i) {
return 1;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
if (view == null) {
switch (getItemViewType(i)) {
case LTC_Item:
view = inflater.inflate(R.layout.item_list_view, null);
break;
case HEADER:
view = inflater.inflate(R.layout.item_listview_header, null);
break;
}
}
switch (getItemViewType(i)) {
case LTC_Item:
ImageView image = (ImageView) view.findViewById(R.id.itemListViewImgIcon);
TextView name = (TextView) view.findViewById(R.id.itemListViewTxtTopicName);
TextView subtitle = (TextView) view.findViewById(R.id.itemListViewTxtTopicSubtitle);
image.setImageResource(((LTCItem) list.get(i)).getImage());
name.setText(((LTCItem) list.get(i)).getName());
subtitle.setText(((LTCItem) list.get(i)).getSubtitle());
break;
case HEADER:
TextView title = (TextView) view.findViewById(R.id.itemListViewHeader);
title.setText(((String) list.get(i)));
break;
}
return view;
}
}
Your ListView element doesn't have an ID, you should add android:id="#+id/list_view" to it in the XML file.
Here is an example:
<ListView
android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
As your list view contains focusable elements, you need to write this piece of code in parent layout in your list view item xml file
android:descendantFocusability="blocksDescendants"
Code of the illustration:
mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.setReverseLayout(true);
mLinearLayoutManager.setStackFromEnd(true);
mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
See illustration here
How can I add new items (in my case, messages) to the bottom of Recycler View and still keep the "gravity" of the view to the top?
So, what works now is the following:
The gravity of the view is at the top. That's good! ✓
What doesn't work:
New messages are added to the top of the view. That's bad ×
I want them to be added at the bottom of the view (after the previous message) like so:
See here
Try removing these two lines or setting them false
layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);
setStackFromEnd will set the view to show the last element, the layout direction will remain the same whereas setReverseLayout will change the order of the elements added by the Adapter.
Try using this to move your RecyclerView and EditText up when keyboard appears
<activity name="YourActivity"
android:windowSoftInputMode="stateHidden|adjustResize">
//stateHidden -> keyboard is hidden when you first open the activity
//adjustResize -> this will adjust the layout resize option
...
</activity>
in AndroidManifest.xml.
To hook the RecyclerView at top
<android.support.v7.widget.RecyclerView
android:id="#+id/messageRecyclerViewRep"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="#+id/linearLayout3"
android:layout_marginLeft="36dp"
android:scrollbars="vertical" />
To put the recyclerView at bottom first and push it up as the keyboard pops up.
<LinearLayout
android:id="#+id/recyclerContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#+id/linearLayout3"
android:layout_above="#+id/linearLayout"
android:gravity="bottom">
<android.support.v7.widget.RecyclerView
android:id="#+id/messageRecyclerViewRep"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="36dp"
android:scrollbars="vertical" />
</LinearLayout>
To scroll the recyclerView to bottom when keyboard pops up i.e. when the recycler view's layout is changed ( You can do the same thing on Edit Text active or focused or clicked or something like that. I've done it on recycler view's layout change. )
recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (bottom < oldBottom) {
recyclerView.postDelayed(new Runnable() {
#Override
public void run() {
recyclerView.smoothScrollToPosition(mAdapter.getItemCount());
}
}, 100);
}
}
});
setReverseLayout(true) this will reverse the item traversal & layout order.The first item will come to end not view or content.
setStackFromEnd(true) this will fill the recycler list content starting from the bottom of the view.
Need to setStackFromEnd(true) not setReverseLayout(true)
And in XML Recyclerview height should be match_parent
Below i have given working code.
activity xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="#+id/btnAdd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add" />
<android.support.v7.widget.RecyclerView
android:id="#+id/rcList"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="true" />
</LinearLayout>
list item xml layout
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:gravity="center_vertical">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content" android:textSize="23sp"
android:layout_height="wrap_content" android:textColor="#4a4883"
android:text="Test Text" />
</FrameLayout>
Adapter class
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
private static final String TAG = "CustomAdapter";
private ArrayList<String> mDataSet;
private int size = 0;
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textView;
public ViewHolder(View v) {
super(v);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.d(TAG, "Element " + getAdapterPosition() + " clicked.");
}
});
textView = (TextView) v.findViewById(R.id.textView);
}
public TextView getTextView() {
return textView;
}
}
public CustomAdapter(ArrayList<String> dataSet) {
mDataSet = dataSet;
if (mDataSet != null && !mDataSet.isEmpty()) {
size = mDataSet.size();
}
}
public void refreshData(String add) {
if (!TextUtils.isEmpty(add)) {
mDataSet.add(add);
size = mDataSet.size();
notifyDataSetChanged();
}
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
// Create a new view.
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.list_item, viewGroup, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
Log.d(TAG, "Element " + position + " set.");
viewHolder.getTextView().setText(mDataSet.get(position));
}
#Override
public int getItemCount() {
return size;
}
}
Activity class
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
protected CustomAdapter mAdapter;
protected LinearLayoutManager mLayoutManager;
protected ArrayList<String> listString = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.rcList);
mLayoutManager = new LinearLayoutManager(this);
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
/**
*setStackFromEnd true will fill the content(list item) from the bottom of the view
*/
mLayoutManager.setStackFromEnd(true);
mLayoutManager.setReverseLayout(true);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
findViewById(R.id.btnAdd).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int temp = mAdapter.getItemCount() + 1;
mAdapter.refreshData("Test text " + temp);
mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount());
}
});
mAdapter = new CustomAdapter(listString);
mRecyclerView.setAdapter(mAdapter);
}
}
The simplest way to achieve this would be to load the elements into the Recyclerview in the reverse order to how they are entered in the Firebase Database.
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
Log.d(TAG, "Element " + position + " set.");
viewHolder.getTextView().setText(mDataSet.get(getItemCount() - 1 -position));
}
What this would do is that the item which is inserted last will get displayed at bottom since you are loading the items from top. No need for any change in any of the XMLs or any other code.
I had same issues with Recylerview not resizing itself when the keyboard pops up and therefore I resorted to this method.
All the best!!
I have implemented and here is my Implementation using FirebaseRecyclerView
you need to set this setStackFromEnd=true and setReverseLayout=true
my xml
Recycler View Holder
public class TestingFirebaseHolder extends RecyclerView.ViewHolder {
private TextView mTextView;
private TextView mTextView2;
public TestingFirebaseHolder(View itemView) {
super(itemView);
mTextView = itemView.findViewById(R.id.textViewTesting);
mTextView2 = itemView.findViewById(R.id.textViewTesting2);
}
public void setTextView(String text,String text2)
{
mTextView.setText(text);
mTextView2.setText(text2);
}
}
Testing Class
public class TestingUser {
public String UserName;
public String mUid;
public TestingUser() {
}
public TestingUser(String userName, String uid) {
UserName = userName;
mUid = uid;
}
}
Activity Code
private EditText mEditText;
private RecyclerView mRecyclerView;
private FirebaseRecyclerAdapter<TestingUser,TestingFirebaseHolder> mAdapter;
private FirebaseUser mUser;
private DatabaseReference mReference;
mEditText = findViewById(R.id.testingEditText);
mRecyclerView = findViewById(R.id.hello_rec);
mUser = FirebaseAuth.getInstance().getCurrentUser();
mReference = FirebaseDatabase.getInstance().getReference();
LinearLayoutManager ll = new LinearLayoutManager(this);
ll.setReverseLayout(true); // set this
ll.setStackFromEnd(true); // set this
mRecyclerView.setLayoutManager(ll);
Query query = mReference.child("Testing").child(mUser.getUid()).orderByValue();
mAdapter = new FirebaseRecyclerAdapter<TestingUser, TestingFirebaseHolder>(
TestingUser.class,R.layout.testing_recycler_layout,TestingFirebaseHolder.class,query
) {
#Override
protected void populateViewHolder(TestingFirebaseHolder viewHolder, TestingUser model, int position) {
viewHolder.setTextView(model.mUid,model.UserName);
}
};
mRecyclerView.setAdapter(mAdapter);
public void buttonClick(View view) {
if(!mEditText.getText().toString().isEmpty())
{
TestingUser user = new TestingUser("Salman",mEditText.getText().toString());
mReference.child("Testing").child(mUser.getUid()).push().setValue(user);
mEditText.setText("");
}
}
Result is
link
Try this, it works for me.
mLinearLayoutManager = new LinearLayoutManager(this);
mLinearLayoutManager.stackFromEnd(true)
mLinearLayoutManager.isSmoothScrollbarEnabled(true)
mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
I read along the code here (weblink). And the code has been modified a little bit to become like this:
FileArrayAdapter.java
public class FileArrayAdapter extends ArrayAdapter<Item> {
private Context c;
private int id;
private List<Item> items;
public FileArrayAdapter(Context context, int textViewResourceId,
List<Item> objects) {
super(context, textViewResourceId, objects);
c = context;
id = textViewResourceId;
items = objects;
}
public Item getItem(int i) {
return items.get(i);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) c
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(id, null);
}
/* create a new view of my layout and inflate it in the row */
// convertView = ( RelativeLayout ) inflater.inflate( resource, null );
final Item o = items.get(position);
if (o != null) {
TextView t1 = (TextView) v.findViewById(R.id.TextView01);
setDefaultTextColor(t1);
TextView t2 = (TextView) v.findViewById(R.id.TextView02);
setDefaultTextColor(t2);
TextView t3 = (TextView) v.findViewById(R.id.TextViewDate);
setDefaultTextColor(t3);
/* Take the ImageView from layout and set the city's image */
ImageView imageCity = (ImageView) v.findViewById(R.id.fd_Icon1);
String uri = "drawable/" + o.getImage();
int imageResource = c.getResources().getIdentifier(uri, null,
c.getPackageName());
Drawable image = c.getResources().getDrawable(imageResource);
imageCity.setImageDrawable(image);
if (t1 != null)
t1.setText(o.getName());
if (t2 != null)
t2.setText(o.getData());
if (t3 != null)
t3.setText(o.getDate());
}
return v;
}
private void setDefaultTextColor(TextView tx) {
tx.setTextColor(Color.parseColor("#f8f9fe"));
}
}
And also another object I made so far:
Item.java
public class Item implements Comparable<Item>{
private String name;
private String data;
private String date;
private String path;
private String image;
public Item(String n,String d, String dt, String p, String img)
{
name = n;
data = d;
date = dt;
path = p;
image = img;
}
public String getName()
{
return name;
}
public String getData()
{
return data;
}
public String getDate()
{
return date;
}
public String getPath()
{
return path;
}
public String getImage() {
return image;
}
public int compareTo(Item o) {
if(this.name != null)
return this.name.toLowerCase().compareTo(o.getName().toLowerCase());
else
throw new IllegalArgumentException();
} }
WIth the list layout a bit customized below:
listupload_row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ImageView
android:contentDescription="#string/file_sharing_file_folder"
android:id="#+id/fd_Icon1"
android:layout_width="50dip"
android:layout_height="50dip" >
</ImageView>
<TextView
android:id="#+id/TextView01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_marginTop="5dip"
android:layout_toRightOf="#+id/fd_Icon1"
android:singleLine="true"
android:text="#+id/TextView01"
android:textStyle="bold" >
</TextView>
<TextView
android:id="#+id/TextView02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/TextView01"
android:layout_marginLeft="10dip"
android:layout_toRightOf="#+id/fd_Icon1"
android:text="#+id/TextView02" >
</TextView>
<TextView
android:id="#+id/TextViewDate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_below="#+id/TextView01"
android:layout_marginLeft="5dip"
android:text="#+id/TextViewDate" >
</TextView>
</RelativeLayout>
My question is:
I know If I want to put Checkbox then I should put it under the XML (layout).
But my case is, I want to make the longClick available for showing the Checkboxes.
And how to do that?
If I simply add this code below, of course it will set the ListView to have onLongClick event....
dList.setLongClickable(true);
dList.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int pos, long id) {
// show the checkbox of each lines
return true;
}
});
But to make it once onLongClick executed, how do I show the Combobox? and vice versa....
One possible solution is to hide/show the checkbox based on a flag that is toggled when an item receives a long click.
Do something like this in your adapter's getView method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
...
if(showCheckBoxes) {
v.findViewById(R.id.checkbox).setVisible(View.VISIBLE);
} else {
v.findViewById(R.id.checkbox).setVisible(View.GONE);
}
...
}
and then in your long click listener:
dList.setOnItemLongClickListener(new OnItemLongClickListener() {
public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int pos, long id) {
showCheckBoxes = !showCheckBoxes;
fileArrayAdapter.notifyDataSetChanged();
return true;
}
});
Its simple add checkbox in xml and make visibility gone
android:visibility="gone"
And declare a radiobox in FileArrayAdapter class as you did with textbox and the put your
onItemLongClickListener();
In that check if checkbox is visible then make it disappear or if not visible the make it visible.
if(cb.isVisible()){
cb.setVisibility(View.GONE);
}else{
cb.setVisibility(View.VISIBLE);
}
Thats's it.
I'm trying to write a simple checklist application that contains a LinkedList view that has text and two radio buttons that indicate yes/no. The problem is that when I check one radio button as I scroll down the LinkedList changes the answers in my radio buttons. I'd appreciate any suggestions you have.
My code is as follows
My primary layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relative"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ListView
android:id="#+id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:cacheColorHint="#00000000"
android:divider="#b5b5b5"
android:dividerHeight="1dp" />
</RelativeLayout>
My row item layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Large Text"
android:textAppearance="?android:attr/textAppearanceLarge" />
<RadioGroup
android:id="#+id/radio_group1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|center_horizontal"
android:orientation="horizontal" >
<RadioButton
android:id="#+id/mRadio1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="radio1" />
<RadioButton
android:id="#+id/mRadio2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="radio2" />
</RadioGroup>
</LinearLayout>
My backend java class for the main checklist activity
public class Checklist2 extends Activity {
//Class Values
AlertHandler ah; // object that manages the database of alerts
QuestionHandler qh; // object that manages the database of questions
List <Question>questions ; //List that holds all the Question items in the program
List <Alert> alerts; //List that holds all the Alert items in the program
private ArrayList<RowObject> mSource;
TextView mCountTextView; // from internet example
ListView mListView;
RadioGroupAdapter adapter;
private ListView listView1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.checklist2);
Log.w("Test", "setList()");
setList();
RadioGroup rg = (RadioGroup) findViewById(R.id.radio_group1);
}
//sets the ListView with questions
private void setList(){
mSource = new ArrayList<RowObject>();
Log.w("Test", "ArrayList<RowObject> created");
for (int i =0; i<questions.size(); i++){
Question q = questions.get(i);
mSource.add(new RowObject());
mSource.get(i).setID(q.getID());
mSource.get(i).setQuestion(q.getQuestion());
mSource.get(i).setYes(false);
mSource.get(i).setNo(false);
}
Log.w("Test", "array list filled");
mListView = (ListView) findViewById(R.id.list);
adapter = new RadioGroupAdapter(this,
R.layout.listitem, mSource);
Log.w("Test", "adapter created");
mListView.setAdapter(adapter);
Log.w("Test", "adapter set");
}}
My RowObject.java class
package com.randstad.jpmcchecklist;
public class RowObject {
private int ID;
private boolean yes;
private boolean no;
public String question;
public RowObject(){
super();
}
public RowObject(int iD, String q,boolean y) {
super();
ID = iD;
question = q;
this.yes = y;
}
public RowObject( String question) {
super();
this.question = question;
}
public void setYes(boolean y){
yes = y;
}
public boolean getYes(){
return yes;
}
public void setNo(boolean n){
no = n;
}
public boolean getNo(){
return no;
}
public void setQuestion(String q){
question = q;
}
public String getQuestion(){
return question;
}
public void setID(int id){
ID = id;
}
public int getID(){
return ID;
}
}
My Adapter class
public class RadioGroupAdapter extends ArrayAdapter<RowObject> {
Context context;
int layoutResourceId;
ArrayList <RowObject> data = null;
int position;
ViewHolder holder;
public RadioGroupAdapter(Context context, int layoutResourceId,
ArrayList <RowObject> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
holder = null;
this.position = position;
if (row == null) {
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, parent, false);
holder = new ViewHolder();
holder.txtTitle = (TextView) row.findViewById(R.id.textView1);
holder.yes = (RadioButton) row.findViewById(R.id.mRadio1);
holder.no = (RadioButton) row.findViewById(R.id.mRadio2);
holder.group = (RadioGroup) row.findViewById(R.id.radio_group1);
row.setTag(holder);
//final RadioButton[] rb = new RadioButton[2];
/*
for(int i=0; i<2; i++){
rb[i] = new RadioButton(context);
//rb[i].setButtonDrawable(R.drawable.single_radio_chice);
rb[i].setId(i);
RadioGroup.LayoutParams params = new RadioGroup.LayoutParams(
0, LayoutParams.WRAP_CONTENT);
params.weight=1.0f;
params.setMargins(15, 0, 5, 10);
holder.group.addView(rb[i],params); //the RadioButtons are added to the radioGroup instead of the layout
}
rb[0].setText("Yes");
rb[1].setText("No");
row.setTag(holder);*/
} else {
holder = (ViewHolder) row.getTag();
}
holder.group.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
// TODO Auto-generated method stub
switch(checkedId){
case R.id.mRadio1:
data.get(position).setYes(true);
data.get(position).setNo(false);
break;
case R.id.mRadio2:
data.get(position).setNo(true);
data.get(position).setYes(false);
}
if(data.get(position).getYes()==true){
holder.yes.setChecked(true);
holder.no.setChecked(false);
}else if(data.get(position).getNo() == true){
holder.yes.setChecked(false);
holder.no.setChecked(true);
}else{
holder.yes.setChecked(false);
holder.yes.setChecked(false);
}
}
});
if(data.get(position).getYes()==true){
holder.yes.setChecked(true);
holder.no.setChecked(false);
}else if(data.get(position).getNo() == true){
holder.yes.setChecked(false);
holder.no.setChecked(true);
}else{
holder.yes.setChecked(false);
holder.yes.setChecked(false);
}
//RowObject option = data[position];
//holder.txtTitle.setText(option.title);
return row;
}
static class ViewHolder {
TextView txtTitle;
RadioGroup group;
RadioButton yes;
RadioButton no;
int position;
}}
Thanks, I really appreciate your help.
I guess the error is in
else{
holder.yes.setChecked(false);
holder.yes.setChecked(false);
}
Which should be
else {
holder.yes.setChecked(false);
holder.no.setChecked(false);
}
And for performance - call data.get(position) once in getView() and store it as a local variable.
Try calling row.setTag(holder); right before return row.
Also, you have holder.yes.setChecked(false) twice in your else case.