my app consist of a main activity with 3 fragments and I have an arraylist of boolean type in the second fragment of grid adapter to check the states of checkbox in every position so an action could be done in the first fragment.
the issue is that the arreylist never updates and it keeps the same data values
my code is below
public class GridAdapter extends BaseAdapter {
private ArrayList<GridWord> list;
private Context context;
private ArrayList<Boolean> checkBoxState;
public boolean status;
GridAdapter (Context context) {
this.context = context;
checkBoxState = new ArrayList<Boolean>();
for (int y = 0; y < 14; y++){
checkBoxState.add(y, false);
}
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int position) {
return list.get(position);
}
#Override
public long getItemId(int i) {
return i;
}
class ViewHolder {
ImageView logoImage;
TextView textName;
CheckBox checkBox;
ViewHolder (View v){
logoImage = v.findViewById(R.id.grid_image);
textName = v.findViewById(R.id.grid_text);
checkBox = v.findViewById(R.id.grid_checbox);
}
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
ViewHolder holder = null;
if (row == null){
LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.grid_item,parent,false);
holder = new ViewHolder(row);
row.setTag(holder);
}
else {
holder = (ViewHolder) row.getTag();
}
final GridWord temp = list.get(position);
holder.logoImage.setImageResource(temp.logo);
holder.textName.setText((CharSequence) temp.name);
final ViewHolder finalHolder = holder;
finalHolder.checkBox.setId(position);
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
status = true;
if(((finalHolder.checkBox.isChecked()))) {
checkCheckBox(position, false);
finalHolder.checkBox.setChecked(checkBoxState.get(position));
}
else {
checkCheckBox(position, true);
finalHolder.checkBox.setChecked(checkBoxState.get(position));
}
}
});
finalHolder.checkBox.setChecked(checkBoxState.get(position));
return row;
}
public ArrayList<Boolean> getCheckBoxState(){
return checkBoxState;
}
public void checkCheckBox(int position, boolean value) {
if (value)
checkBoxState.set(position, true);
else
checkBoxState.set(position, false);
notifyDataSetChanged();
}
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
isVisible = isVisibleToUser;
if (isVisible && isStarted) {
checkList.clear();
checkList = gridAdapter.getCheckBoxState();
for (int x = 0; x < checkList.size(); x++) {
if (checkList.get(x)) {
// some code
}
}
adapter.notifyDataSetChanged();
}
}
I would suggest you to have this arraylist in you activity holding this 3 fragments. Try updating this Arraylist from your Second fragment.
This way, whenever you want to read the values in First Fragment, you can read them from this global arraylist and hence so you have single instance of your arraylist.
Related
I am using gridview layout for displaying multiple item and items are displaying fine, if I check on the big screen then all work done is fine because no scrolling is required.
But if I user small screen while scrolling it changing position dynamically.
** Example:**
If I display 50 items it working fine if I display 1000 items I need to scroll down, on that time selected items are changing their positions dynamically.
Adapter Code
public class EM_event_total_userseatsAdapter extends ArrayAdapter<EM_event_total_UserSeatsModel> implements View.OnClickListener {
ArrayList<EM_event_total_UserSeatsModel> dataSet;
public ArrayList<Integer> EMeventuserseatslist = new ArrayList<Integer>();
Context mContext;
ViewHolder holder;
String user_seats;
private int[] tagCollection;
private String[] mobileValues;
private String[] mobileValuesD;
private static class ViewHolder {
TextView TvEmUserSeats;
ImageView IvUsreSeats,available,selctedimag;
}
private String[] strings;
List<Integer> selectedPositions = new ArrayList<>();
SparseBooleanArray selectedItems;
public
EM_event_total_userseatsAdapter(ArrayList<EM_event_total_UserSeatsModel> data, Context context) {
super(context, R.layout.list_em_get_seats, data);
this.dataSet = data;
this.mContext=context;
selectedItems = new SparseBooleanArray();
}
public int getTagFromPosition(int position) {
return tagCollection[position];
}
#Override
public void onClick(View v) {
int position=(Integer) v.getTag();
Object object= getItem(tagCollection[position]);
EM_event_total_UserSeatsModel dataModel=(EM_event_total_UserSeatsModel)
object;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
EM_event_total_UserSeatsModel dataModel = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
ViewHolder viewHolder; // view lookup cache stored in tag
final View result;
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(R.layout.list_em_get_seats, parent, false);
viewHolder.TvEmUserSeats = (TextView) convertView.findViewById(R.id.TvEmUserSeats);
viewHolder.IvUsreSeats = (ImageView) convertView.findViewById(R.id.IvUsreSeats);
result=convertView;
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
result=convertView;
}
String blue_available = "seat3.png";
String red_booked = "seat1.png";
String get_seat = dataModel.getBookedStatus();
viewHolder.TvEmUserSeats.setText(dataModel.getSeatName());
//holder.imgSeatSelected.setVisibility(isSelected(position) ? View.VISIBLE : View.INVISIBLE);
if(Integer.parseInt(get_seat) == 1){
Picasso.with(mContext).load(main_url+"assets/admin/img/" + red_booked).into(viewHolder.IvUsreSeats);
}else
{
Picasso.with(mContext).load(main_url+"assets/admin/img/" + blue_available).into(viewHolder.IvUsreSeats);
}
return convertView;
}
public void toggleSelection(int position) {
if (selectedItems.get(position, false)) {
selectedItems.delete(position);
} else {
selectedItems.put(position, true);
}
notifyDataSetChanged();
}
public void clearSelections() {
selectedItems.clear();
notifyDataSetChanged();
}
public int getSelectedItemCount() {
return selectedItems.size();
}
public String getSelectedItems() {
String items = "";
for (int i = 0; i < selectedItems.size(); i++) {
items += selectedItems.keyAt(i);
}
return items;
}
}
This question has been asked so many times, but none of the solutions solved my issue.
I have an activity with two fragments with a viewpager, And each fragment has a listview. Upon moving between tabs my listview's items are repeating.
here is the adapter code.
public class ComboMenuAdapter extends BaseAdapter {
private Context mContext;
private MenuHolder mMenuHolder;
private ArrayList<Integer> index;
public ComboMenuAdapter(Context mContext, ArrayList<Integer> index) {
this.index = index;
this.mContext = mContext;
}
#Override
public int getCount() {
return index.size();
}
#Override
public MenuHolder getItem(int position) {
return DataHandler.getInstance().getData(index.get(position));
}
#Override
public long getItemId(int position) {
return position;
}
private class Holder {
ImageView image;
TextView price, liters, itemnametxt, mAdd_txt, minus, plus, counter;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
final Holder mHolder;
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v= vi.inflate(R.layout.combo_meals_adapter, null);
mHolder = new Holder();
mHolder.price = (TextView) v.findViewById(R.id.price);
mHolder.itemnametxt = (TextView) v.findViewById(R.id.itemnametxt);
mHolder.image = (ImageView) v.findViewById(R.id.image);
mHolder.liters = (TextView) v.findViewById(R.id.ml);
mHolder.mAdd_txt = (TextView) v.findViewById(R.id.addtxt);
mHolder.minus = (TextView) v.findViewById(R.id.minus);
mHolder.counter = (TextView) v.findViewById(R.id.count);
mHolder.plus = (TextView) v.findViewById(R.id.plus);
v.setTag(mHolder);
} else {
mHolder = (Holder) v.getTag();
}
mMenuHolder = getItem(position);
mHolder.itemnametxt.setText(mMenuHolder.getItemname());
mHolder.image.setImageResource(R.mipmap.ic_launcher);
mHolder.price.setText(mMenuHolder.getItemprice());
mHolder.counter.setText(mMenuHolder.getItemCount());
return v;
}
}
I am unable to find the mistake, please help me, Thank you in advance.
Here, I am storing the data using DataHandler Class
public class DataHandler {
ArrayList<MenuHolder> listOfItemsFromJson = new ArrayList<MenuHolder>();
private static DataHandler mInstance = null;
static public DataHandler getInstance() {
if (null == mInstance) {
mInstance = new DataHandler();
}
return mInstance;
}
public DataHandler() {
listOfItemsFromJson = new ArrayList<>();
}
public ArrayList<MenuHolder> getListOfItemsFromJson() {
return listOfItemsFromJson;
}
public void clearList() {
listOfItemsFromJson.clear();
}
public void addData(MenuHolder holder) {
listOfItemsFromJson.add(holder);
}
public MenuHolder getData(int position) {
return listOfItemsFromJson.get(position);
}
public void removeData(int position) {
listOfItemsFromJson.remove(getData(position));
}
public void modifyData(MenuHolder holder, int position) {
listOfItemsFromJson.set(position, holder);
}
public int size() {
return listOfItemsFromJson.size();
}
}
Upon onCreateView(), I am placing the data
for (int i = 0; i < DataHandler.getInstance().size(); i++) {
if (DataHandler.getInstance().getData(i).isCombo()) {
DataHandler.getInstance().removeData(i);
}
}
for (int i = 0; i < 3; i++) {
MenuHolder mMenuHolder = new MenuHolder();
mMenuHolder.setItemname(itemNames[i]);
mMenuHolder.setImageName("#mipmap/ic_launcher");
mMenuHolder.setItemCount("0");
mMenuHolder.setItemprice("500");
mMenuHolder.setUserSeleted(false);
mMenuHolder.setCombo(true);
mMenuHolder.setDrinks(false);
mMenuHolder.setBiryani(false);
DataHandler.getInstance().addData(mMenuHolder);
}
index.clear();
for (int i = 0; i < DataHandler.getInstance().size(); i++) {
if (DataHandler.getInstance().getListOfItemsFromJson().get(i).isCombo()) {
index.add(i);
}
}
mCombosAdapter = new ComboMenuAdapter(getActivity(), index);
mlistView.setVisibility(View.VISIBLE);
mlistView.setAdapter(mCombosAdapter);
mlistView.setOnItemClickListener(this);
mMenuHolder = getItem(position);
should be retrieved before setting the data. Move it outside the if/else logic before.
mMenuHolder = getItem(position);
mHolder.itemnametxt.setText(mMenuHolder.getItemname());
mHolder.image.setImageResource(R.mipmap.ic_launcher);
mHolder.price.setText(mMenuHolder.getItemprice());
mHolder.counter.setText(mMenuHolder.getItemCount());
you want to retrieve the item at position before filling up your view
Make sure you clear your adapter before adding new objects to it:
if (!someAdapter.isEmpty())
someAdapter.clear();
someAdapter.addAll(new ArrarList(arrayListContainingUpdatedStuff));
No need for a new adapter allocation, you might lose you reference to the old one and the list might go blank.
Hope this helps.
for this code you get Repeating data may be
for (int i = 0; i < 3; i++)
{
MenuHolder mMenuHolder = new MenuHolder();
mMenuHolder.setItemname(itemNames[i]);
mMenuHolder.setImageName("#mipmap/ic_launcher");
mMenuHolder.setItemCount("0");
mMenuHolder.setItemprice("500");
mMenuHolder.setUserSeleted(false);
mMenuHolder.setCombo(true);
mMenuHolder.setDrinks(false);
mMenuHolder.setBiryani(false);
DataHandler.getInstance().addData(mMenuHolder);
}
I have a list view of the emails of all the contacts in the phonebook.My list is a custom listview with a checkbox.Now the problem is as follows.
For eg i have 20 emails in the list.If i select the first email say "A" in the list and then scrolls the list,other emails are also getting selected by itself.Also if i again scroll back to the list ,my selected email "A" is being deselected by it own. I dnot know why this is occuring
CustomList
public class EmailListAdapter extends BaseAdapter {
private Context context;
private ArrayList<String> data;
DbHandler dbHandler;
public EmailListAdapter(Context context, ArrayList<String> data) {
this.context = context;
this.data = data;
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(final int i, View view, ViewGroup viewGroup) {
final ViewHolder holder;
dbHandler = new DbHandler(context);
if (view == null) {
holder = new ViewHolder();
view = LayoutInflater.from(context).inflate(R.layout.email_custom_list, viewGroup, false);
holder.tvContact = (TextView) view.findViewById(R.id.tv_email_name);
holder.checkBox = (CheckBox) view.findViewById(R.id.cb_email_checkbox);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (compoundButton == holder.checkBox) {
if (b) {
// dbHandler.updateContactList(data.get(i).getUserID(), 1);
} else {
// dbHandler.updateContactList(data.get(i).getUserID(), 0);
}
}
}
});
holder.tvContact.setText(data.get(i));
return view;
}
private class ViewHolder {
TextView tvContact;
CheckBox checkBox;
}
The Adapter is recycling your views. Let's look at the following example:
Your ListView shows 10 rows at once and the first row has a blue background color. Now If you start scrolling the 11th row will become visible and the first will be hidden.
Internally the system recycles your first row and uses it as the 11th. So your 11th row will be blue as well.
So in order to fix this you have to set the background color each time in your getView(...) function. In your example you have to save the state of the different CheckBoxes manually and reapply them in the getView-function.
Edit
Just found this post on StackOverflow. It's discussing this topic even more detailed: How ListView's recycling mechanism works
Solution
Following just the relevant parts:
private int[] mStates;
public EmailListAdapter(Context context, ArrayList<String> data) {
this.context = context;
this.data = data;
mStates = new int[data.size()];
}
#Override
public View getView(final int position, View view, ViewGroup viewGroup) {
//...
if (mStates[position] == 0) {
holder.checkbox.setChecked(false);
} else {
holder.checkbox.setChecked(true);
}
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (compoundButton == holder.checkBox) {
if (b) {
mStates[position] = 1;
//dbHandler.updateContactList(data.get(i).getUserID(), 1);
} else {
mStates[position] = 0;
//dbHandler.updateContactList(data.get(i).getUserID(), 0);
}
}
}
});
//...
}
Since you are using a view holder your check box get reused while scrolling.The same check box at top comes again at bottom while you scroll when you use view holder.
And when you scroll back to top the check box comes back may not be old one.
So you have to save each checklists state to a list and use it according to position as your text view.
Solved Ans
public class EmailListAdapter extends BaseAdapter {
private Context context;
private ArrayList<EmailModel> data;
DbHandler dbHandler;
int[] emails;
ArrayList<String> emailSeperated;
public EmailListAdapter(Context context, ArrayList<EmailModel> data) {
this.context = context;
this.data = data;
emails = new int[data.size()];
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(final int i, View view, ViewGroup viewGroup) {
final ViewHolder holder;
dbHandler = new DbHandler(context);
emailSeperated = new ArrayList<String>();
if (view == null) {
holder = new ViewHolder();
view = LayoutInflater.from(context).inflate(R.layout.email_custom_list, viewGroup, false);
holder.tvContact = (TextView) view.findViewById(R.id.tv_email_name);
holder.checkBox = (CheckBox) view.findViewById(R.id.cb_email_checkbox);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
// if (emails[i] == 0) {
// holder.checkBox.setChecked(false);
// } else {
// holder.checkBox.setChecked(true);
// }
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (compoundButton == holder.checkBox) {
if (b) {
emails[i] = 1;
//dbHandler.updateContactList(data.get(i).getUserID(), 1);
emailSeperated.add(data.get(i).getEmail());
Log.e("Email values", emailSeperated.toString());
//
} else {
emails[i] = 0;
emailSeperated.remove(data.get(i).getEmail());
Log.e("Email values", emailSeperated.toString());
}
}
}
}
);
if (emails[i] == 0) {
holder.checkBox.setChecked(false);
} else {
holder.checkBox.setChecked(true);
}
holder.tvContact.setText(data.get(i).
getEmail()
);
return view;
}
private class ViewHolder {
TextView tvContact;
CheckBox checkBox;
}
}
I want to implement a scenario-
There is present a checkbox on the top of the screen and there is a custom listview with checkboxes below that top checkbox.
I want that one someone checks that checkbox all the listview checkboxes should be checked and vice versa.
public class GroupMemberListAdapter extends BaseAdapter {
private LayoutInflater inflater = null;
Context Mycontext;
public GroupMemberListAdapter(Context context) {
Mycontext = context;
inflater = LayoutInflater.from(context);
}
public int getCount() {
return broadcastList.size();
}
public Object getItem(int paramInt) {
return paramInt;
}
public long getItemId(int paramInt) {
return paramInt;
}
public View getView(int position, View convertView, ViewGroup parent) {
EventViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.contactcustomlayout,
null);
holder = new EventViewHolder();
holder.mtvGroupMemberName = (TextView) convertView
.findViewById(R.id.tvGroupMemberName);
holder.checkbox_group_member = (CheckBox)convertView.findViewById(R.id.checkBox_GroupMember);
/*holder.mtvGroupMemberAbout = (TextView) convertView
.findViewById(R.id.tvGroupMemberAbout);*/
convertView.setTag(holder);
} else {
holder = (EventViewHolder) convertView.getTag();
}
holder.mtvGroupMemberName.setText(""+broadcastList.get(position));
//holder.mtvGroupMemberAbout.setText(""+data.get(position));
return convertView;
}
public class EventViewHolder {
private TextView mtvGroupMemberName;
private TextView mtvGroupMemberAbout;
private CheckBox checkbox_group_member;
}
}
checkBox_selectAll.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
checkAllBoxes();
}
});
private void checkAllBoxes(){
int size = mlvGroupBroadContact.getAdapter().getCount();
System.out.println("Size of the list is:"+size);
}
How can I check all the list view boxes???
If your ListView's choice mode is CHOICE_MODE_MULTIPLE or CHOICE_MODE_SINGLE:
private void deselectAll() {
getListView().clearChoices();
//--as of GingerBread, clearChoices() alone is not sufficient--
//--we'd have to manually un-check visible items--
for (int i = 0; i < getListView().getChildCount(); i++) {
View c = getListView().getChildAt(i);
if (c instanceof Checkable) {
((Checkable) c).setChecked(false);
}
}
}
private void selectAll() {
SparseBooleanArray sba = getListView().getCheckedItemPositions();
for (int i = 0; i < getAdapter().getCount(); i++) {
sba.put(i, true);
}
for (int i = 0; i < getListView().getChildCount(); i++) {
View c = getListView().getChildAt(i);
if (c instanceof Checkable) {
((Checkable) c).setChecked(true);
}
}
}
Replace getListView() and getAdapter() with your ListView and its Adapter instances.
you can use the below code to check all checkboxes in the listview
private void checkAllBoxes(){
int size = mlvGroupBroadContact.getAdapter().getCount();
System.out.println("Size of the list is:"+size);
CheckBox chk;
for(int i=0;i<size;i++)
{
chk= ((CheckBox)jobList.getChildAt(i).findViewById(R.id.chk));
chk.setChecked(true);
}
}
Update a Boolean variable in your adapter class from on checkBox_selectAll click listner.
and call view.getAdapter.notifyDataSetChanged();
In getView based on this variable set it state checked or unchecked.
I have a ListView in my app which has a custom adapter. I have a ImageView, a CheckBox and a TextView in my list view and i have one button in my app which should delete Checked items from the list on onClick event but the problem is - It does not matter which items i am selecting but it's always deleting the items from the botton of the list.
here is my custom adapter's code -
public class IconAdapter extends BaseAdapter
{
private Activity activity;
private Object[] data;
private ArrayList<HashMap<String,String>> listItems;
public static LayoutInflater inflater = null;
private PackageManager pm;
public ArrayList<Boolean> itemChecked = new ArrayList<Boolean>();
private ArrayList<String> itemSelected = new ArrayList<String>();
private ArrayList<TextView> ctv = new ArrayList<TextView>();
private int posi;
private String pkg;
public IconAdapter(Activity a, ArrayList<HashMap<String,String>> items)
{
activity = a;
listItems = items;
data = items.toArray();
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
pm = a.getPackageManager();
for(int i = 0; i < items.size(); i++)
{
itemChecked.add(i,false);
}
for(int i = 0; i < items.size(); i++)
{
itemSelected.add(i," ");
}
}
public int getCount() {
return listItems.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public static class ViewHolder{
public TextView textView;
public ImageView imageView;
public CheckBox checkBox;
}
public View getView(final int position, View convertView, ViewGroup parent)
{
View row = convertView;
ViewHolder holder;
if(row==null)
{
row = inflater.inflate(R.layout.item, parent, false);
holder = new ViewHolder();
holder.textView = (TextView)row.findViewById(R.id.text1);
holder.imageView = (ImageView)row.findViewById(R.id.image);
holder.checkBox = (CheckBox)row.findViewById(R.id.check);
row.setTag(holder);
}
else
{
holder = (ViewHolder) row.getTag();
}
String s = data[position].toString();
String[] tokens = s.split(",");
String[] mToken = tokens[0].split("=");
String taskName = mToken[1];
String[] mTokens = tokens[1].split("=");
final String pkgName = mTokens[1].substring(0, (mTokens[1].length() - 1));
holder.textView.setText(taskName);
holder.textView.setTag(pkgName);
holder.checkBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton button, boolean b) {
if (b)
{
itemChecked.set(position, true);
itemSelected.set(position, pkgName);
}
else
{
itemChecked.set(position, false);
}
}
});
holder.checkBox.setChecked(itemChecked.get(position));
try{
Drawable icon = pm.getApplicationIcon(pkgName);
holder.imageView.setImageDrawable(icon);
}
catch (PackageManager.NameNotFoundException ne)
{
}
return row;
}
public String getPkgName(int position)
{
return itemSelected.get(position);
}
public void setItemChecked(boolean isChecked)
{
}
}
nd here is my onClick code -
public void onClick(View view)
{
int size = icon.getCount();
for(int i = size-1; i >= 0; i--)
{
if(icon.itemChecked.get(i))
{
list.remove(i);
}
}
icon.notifyDataSetChanged();
}
please help!!!!!
And when i removed notifyDataSetChanged from onClick and reload the list manually again its working exactly i want it to work so there is some problem in NotyfyDataSetChanged. Please help.
You can use notifyDataSetChanged method of your adapter, but keep in mind some points that are stated here (see accepted answer) notifyDataSetChanged example
did you put a log statement in onCheckedChanged method and see what position is being set ? My guess is that you shouldn't use the position argument in that manner. One way to do so could be to use holder.checkBox.setTag(new Integer(position)) and in the onCheckedChanged method use int posClicked = ((Integer)button.getTag()).intValue() and then use this instead of position