How to select selected value multivalue in recyclerview - java

i want to get selected ids in activity which is selected in recyclerview adapter
holder.images.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (holder.checked.getVisibility() == View.VISIBLE) {
holder.checked.setVisibility(View.GONE);
} else if (holder.checked.getVisibility() == View.GONE) {
holder.checked.setVisibility(View.VISIBLE);
}
}
});

Use list to handle your selected items or positions
declare list for store selected items
private List<Integer> selectedPositions=new ArrayList();
update code in onBindViewHolder like below
holder.checked.setVisibility(selectedPositions.contains(position)?View.VISIBLE:View.GONE);
holder.images.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (selectedPositions.contains(position)) {
holder.checked.setVisibility(View.GONE);
selectedPositions.removeAt(selectedPositions.indexOf(position));
} else {
holder.checked.setVisibility(View.VISIBLE);
selectedPositions.add(position);
}
}
});

Here that solution i created arrylist and put data size
public static ArrayList<Integer> dataSize=new ArrayList<>();
and pass to adapter
holder.checked.setVisibility(idpositions.get(position)==0?View.GONE:View.VISIBLE);
holder.images.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (dataSize.size()>0) {
if (holder.checked.getVisibility() == View.VISIBLE) {
holder.checked.setVisibility(View.GONE);
dataSize.set(position,0);
} else if (holder.checked.getVisibility() == View.GONE) {
dataSize.add(position,data.getId());
holder.checked.setVisibility(View.VISIBLE);
}
}
}
});
and on button click simply get that arraylist and get your selected value
if(dataSize.size()>0){
for (int i = 0; i < dataSize.size(); i++) {
if (dataSize.get(i)==0){
continue;
}else {
ids= ids+String.valueOf(dataSize.get(i))+",";
}
}
Toast.makeText(this, ids, Toast.LENGTH_SHORT).show();
}

Now, you need to declare a list to hold those selected ids
private List<DATA_TYPE> selectedIds = new ArrayList();
What you can do is declare one isSelected boolean in your model. In onBindViewHolder method, set visibility as
if (YOUR_POJO.isSelected()) {
holder.checked.setVisibility(View.VISIBLE);
} else {
holder.checked.setVisibility(View.GONE);
}
When you click on image check if it was already selected based on that you can add/remove its id
holder.images.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(YOUR_POJO.isSelected()){
YOUR_POJO.setSelected(false);
if (selectedIds.contains(YOUR_POJO.getId()){
selectedIds.remove(YOUR_POJO.getId());
}
} else {
YOUR_POJO.setSelected(true);
selectedIds.add(YOUR_POJO.getId());
}
notifyItemChanged(holder.getAdapterPosition(), YOUR_POJO);
}
});
Hope this helps.

Create an interface class like this;
public interface ItemSelectedListener{
void onItemSelected(int selectedposition);
}
In your adapter initialize your interface;
private List<ItemSelectedListener> mItemSelectedSubscribers = new ArrayList<ItemSelectedListener>();
Add this method in your adapter ;
public void subscribeItemSelection(ItemSelectedListenerlistener) {
mItemSelectedSubscribers .add(listener);
}
Set this loop in your click events;
for (ItemSelectedListener listener : mMediaSelectedSubscribers) {
listener.onItemSelected(position);
}
In your activity, implement your interface and you will set a implemented methods. this methods look like this;
int selectedPosition;
#Override
public void onMediaSelected(int position) {
selectedPosition = position;
}
When you do this you can use your selected position where you want in your activity
Hope this help!

Related

How do I set listeners on an array of objects?

I am refactoring an Android app of mine. In the initial version I instantiated eight objects of the same class in the main activity and set listeners separately onto them. For each instance I initialized a separate variable.
Now I want to add the objects to an array and set listeners in the loop, but when I test the app the listener is set only on the last instance.
mObjects = new ArrayList<>();
mObjects.add(createNewObject(R.id.objectPlaceholder1, R.id.objectProgressTextView));
mObjects.add(createNewObject(R.id.objectPlaceholder2, R.id.object2ProgressTextView));
mObjects.add(createNewObject(R.id.objectPlaceholder3, R.id.object3ProgressTextView));
mObjects.add(createNewObject(R.id.objectPlaceholder4, R.id.object4ProgressTextView));
mObjects.add(createNewObject(R.id.objectPlaceholder5, R.id.object5ProgressTextView));
mObjects.add(createNewObject(R.id.objectPlaceholder6, R.id.object6ProgressTextView));
mObjects.add(createNewObject(R.id.objectPlaceholder7, R.id.object7ProgressTextView));
mObjects.add(createNewObject(R.id.objectPlaceholder8, R.id.object8ProgressTextView));
for (int i = 0; i < mObjects.size(); ++i) {
object = mObjects.get(i);
object.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
countDownEditText = findViewById(R.id.countdownEditText);
if (countDownEditText.getText().toString().equals("")) {
showToastText(R.string.count_down_time);
return;
}
if (object.checkReadyForAction()) {
countDownTime = Integer.parseInt(countDownEditText.getText().toString());
object.startCountDown(countDownTime);
} else {
showToastText(R.string.action_not_ready);
}
}
});
object.image.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
object.reset();
return true;
}
});
}
Alright, I got it working. Just implemented the needed listeners.
// ...
for (int i = 0; i < mObjects.size(); ++i) {
object = mObjects.get(i);
object.image.setOnClickListener(new ObjectClickListener(object));
object.image.setOnLongClickListener(new ObjectLongClickListener(object));
}
private class ObjectClickListener implements View.OnClickListener {
ExampleObject mObject;
ObjectClickListener(ExampleObject object) {
mObject = object;
}
#Override
public void onClick(View v) {
countDownEditText = findViewById(R.id.countdownEditText);
if (countDownEditText.getText().toString().equals("")) {
showToastText(R.string.count_down_time);
return;
}
if (mObject.checkReadyForAction()) {
countDownTime = Integer.parseInt(countDownEditText.getText().toString());
mObject.startCountDown(countDownTime);
} else {
showToastText(R.string.action_not_ready);
}
}
}
private class ObjectLongClickListener implements View.OnLongClickListener {
ExampleObject mObject;
ObjectLongClickListener(ExampleObject object) {
mObject = object;
}
#Override
public boolean onLongClick(View v) {
mObject.reset();
return true;
}
}

findViewHolderForAdapterPosition() returns null

I know this question has been asked with the exact same title but a decent solution was not provided, hence my "duplicate".
when adding a new Item to the recyclerView, I want to set the focus to the latest item (it's a list of EditText's). However, because of recalculating the view, calling "findViewHolderForAdapterPosition" returns null. It could be solved by waiting half a second before calling the function as shown here
addOptionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
optionsAdapter.addOption();
optionsRecyclerView.postDelayed(new Runnable() {
#Override
public void run() {
int last = optionsAdapter.getItemCount()-1;
OptionsAdapter.OptionViewHolder o = (OptionsAdapter.OptionViewHolder) optionsRecyclerView.findViewHolderForAdapterPosition(last);
o.editText.setSelected(true);
}
},500);
}
});
//OptionsAdapter class
public void addOption()
{
values.add("");
notifyItemInserted(values.size()-1);
}
However, it is not the neatest method nor does it always work. Is there perhaps a better way to get around it?
Edit:
Another idea:
addOptionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
optionsAdapter.addOption();
int last = optionsAdapter.getItemCount()-1;
optionsRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
int lastVisible = layoutManager.findLastVisibleItemPosition();
if (lastVisible == last) {
optionsRecyclerView.removeOnScrollListener(this);
OptionsAdapter.OptionViewHolder o = (OptionsAdapter.OptionViewHolder) optionsRecyclerView.findViewHolderForAdapterPosition(last);
o.editText.setSelected(true);
}
}
optionsRecyclerView.scrollToPosition(last);
}
});
Try this:
addOptionButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
optionsAdapter.addOption();
int last = optionsAdapter.getItemCount()-1;
optionsRecyclerView.scrollToPosition(last);
OptionsAdapter.OptionViewHolder o = (OptionsAdapter.OptionViewHolder) optionsRecyclerView.findViewHolderForAdapterPosition(last);
o.editText.setSelected(true);
}
});

List<ParseUser> .contains ParseUser always FALSE

I have an if statement written below:
//Set Friend Action OnClickListener & Image
if (ParseUser.getCurrentUser().getList("friendsArray").contains(searchResultsList.get(position))) {
Glide.with(holder.imgFriendAction.getContext()).load(R.drawable.ic_phone_black_24dp).into(holder.imgFriendAction);
ImageViewCompat.setImageTintList(holder.imgFriendAction, ColorStateList.valueOf(searchContext.getColor(R.color.green)));
}
else if (ParseUser.getCurrentUser().getList("pendingFriendsArray").contains(searchResultsList.get(position))) {
Glide.with(holder.imgFriendAction.getContext()).load(R.drawable.ic_check_black_24dp).into(holder.imgFriendAction);
ImageViewCompat.setImageTintList(holder.imgFriendAction, ColorStateList.valueOf(searchContext.getColor(R.color.gray_dark)));
}
else {
Glide.with(holder.imgFriendAction.getContext()).load(R.drawable.ic_person_add_black_24dp).into(holder.imgFriendAction);
ImageViewCompat.setImageTintList(holder.imgFriendAction, ColorStateList.valueOf(searchContext.getColor(R.color.colorPrimary)));
}
The problem is that every single time I run that statement it always returns FALSE for both if statements even though I know for a fact that 'friendsArray' & 'pendingFriendsArray' return TRUE in many circumstances.
Both arrays contain pointers to the _User table.
searchResultsList is declared as follows:
private List<ParseUser> searchResultsList;
I've logged all three items (friendsArray, pendingFriendsArray & searchResultsList.get(position)) to the console and they show the following:
D/friendsArray: [com.parse.ParseUser#ae66779, com.parse.ParseUser#8371cbe, com.parse.ParseUser#32d511f, com.parse.ParseUser#5fd2c6c, com.parse.ParseUser#7dd0235, com.parse.ParseUser#9c446ca, com.parse.ParseUser#5fe03b]
D/pendingFriendsArray: [com.parse.ParseUser#7c6a358, com.parse.ParseUser#3688cb1, com.parse.ParseUser#480596]
D/searchResultsList.get(position) =: com.parse.ParseUser#5fe03b
The entire class is below:
public class SearchUserAdapter extends RecyclerView.Adapter<SearchUserAdapter.ViewHolder> {
private Context searchContext;
private List<ParseUser> searchResultsList;
OnItemClickListener onItemClickListener;
public SearchUserAdapter(Context context, List<ParseUser> dataSet) {
searchContext = context;
searchResultsList = dataSet;
}
public interface OnItemClickListener {
public void onItemClick(View view, ParseUser searchUserObject, int position);
}
public void setOnItemClickListener(final OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(searchContext).inflate(R.layout.ly_search_user, parent,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
//Set User Name
holder.txtUserName.setText(searchResultsList.get(position).getString("fullName"));
//Set User Location
holder.txtUserLocation.setText(GlobalFunctions.getParseUserLocationAsString(holder.txtUserName.getContext(), searchResultsList.get(position)));
//Set User Profile Image
if (searchResultsList.get(position).getParseFile("profilePicture") != null) {
Glide.with(holder.imgUserProfilePicture.getContext()).applyDefaultRequestOptions(RequestOptions.circleCropTransform()).load(searchResultsList.get(position).getParseFile("profilePicture").getUrl()).into(holder.imgUserProfilePicture);
}
else {
Glide.with(holder.imgUserProfilePicture.getContext()).applyDefaultRequestOptions(RequestOptions.circleCropTransform()).load(R.drawable.ic_profile_place_holder).into(holder.imgUserProfilePicture);
}
//Set Row OnClickListener
holder.rlUserItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (searchResultsList.get(position).getObjectId().equalsIgnoreCase(ParseUser.getCurrentUser().getObjectId())) {
Intent openProfile;
openProfile = new Intent(holder.rlUserItem.getContext(), TimelineActivity.class);
holder.rlUserItem.getContext().startActivity(openProfile);
}
else {
Intent openOtherProfile = new Intent(holder.rlUserItem.getContext(), OtherUserTimelineActivity.class);
openOtherProfile.putExtra("otherUserProfileId", searchResultsList.get(position).getObjectId());
holder.rlUserItem.getContext().startActivity(openOtherProfile);
}
}
});
//Set Friend Action OnClickListener & Image
if (ParseUser.getCurrentUser().getList("friendsArray").contains(searchResultsList.get(position))) {
Glide.with(holder.imgFriendAction.getContext()).load(R.drawable.ic_phone_black_24dp).into(holder.imgFriendAction);
ImageViewCompat.setImageTintList(holder.imgFriendAction, ColorStateList.valueOf(searchContext.getColor(R.color.green)));
}
else if (ParseUser.getCurrentUser().getList("pendingFriendsArray").contains(searchResultsList.get(position))) {
Glide.with(holder.imgFriendAction.getContext()).load(R.drawable.ic_check_black_24dp).into(holder.imgFriendAction);
ImageViewCompat.setImageTintList(holder.imgFriendAction, ColorStateList.valueOf(searchContext.getColor(R.color.gray_dark)));
}
else {
Glide.with(holder.imgFriendAction.getContext()).load(R.drawable.ic_person_add_black_24dp).into(holder.imgFriendAction);
ImageViewCompat.setImageTintList(holder.imgFriendAction, ColorStateList.valueOf(searchContext.getColor(R.color.colorPrimary)));
}
holder.imgFriendAction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
friendActionListenerAction(holder, searchResultsList.get(position));
}
});
}
private void friendActionListenerAction(ViewHolder holder, ParseUser parseUser) {
if (ParseUser.getCurrentUser().getList("friendsArray").contains(parseUser)) {
FLKCallUtils.showCallDialog(holder.imgFriendAction.getContext());
}
else if (ParseUser.getCurrentUser().getList("pendingFriendsArray").contains(parseUser)) {
//Do nothing
}
else {
//Add Friend
FLKFriendUtils.sendFriendRequestFromUserToUser(ParseUser.getCurrentUser(), parseUser);
//Update Image
Glide.with(holder.imgFriendAction.getContext()).load(R.drawable.ic_check_black_24dp).into(holder.imgFriendAction);
ImageViewCompat.setImageTintList(holder.imgFriendAction, ColorStateList.valueOf(searchContext.getColor(R.color.gray_dark)));
}
}
#Override
public int getItemCount() {
return searchResultsList.size();
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public MediumRobotoTextView txtUserName;
public RegularRobotoTextView txtUserLocation;
public RelativeLayout rlUserItem;
ImageView imgUserProfilePicture;
ImageView imgFriendAction;
public ViewHolder(View itemView) {
super(itemView);
rlUserItem = (RelativeLayout) itemView.findViewById(R.id.rl_user_container);
rlUserItem.setOnClickListener(this);
txtUserName = (MediumRobotoTextView) itemView.findViewById(R.id.txt_user_name);
txtUserLocation = (RegularRobotoTextView) itemView.findViewById(R.id.txt_user_location);
imgUserProfilePicture = (ImageView) itemView.findViewById(R.id.img_profile_picture);
imgUserProfilePicture.setOnClickListener(this);
imgFriendAction = (ImageView) itemView.findViewById(R.id.img_friend_action);
imgFriendAction.setOnClickListener(this);
}
#Override
public void onClick(View v) {
//TODO - do something here if you wish
}
}
Upon further investigation I found that the parse-android SDK does not fetch pointers the same every single time. For example when I fetch 'friendsArray', let's say right now, it will return
[com.parse.ParseUser#ae66779, com.parse.ParseUser#8371cbe, com.parse.ParseUser#32d511f, com.parse.ParseUser#5fd2c6c, com.parse.ParseUser#7dd0235, com.parse.ParseUser#9c446ca, com.parse.ParseUser#5fe03b]
However if I then fetch it, let's say in 5 minutes, it will return
[com.parse.ParseUser#ec99877, com.parse.ParseUser#674bcg, com.parse.ParseUser#749hhc, com.parse.ParseUser#6fh3d6dg, com.parse.ParseUser#jdj8dk, com.parse.ParseUser#4c966ca, com.parse.ParseUser#3f0eeb]
Additionally, I noted that even the pointer to searchResultsList.get(position) changes it's reference every time I loaded it.
The way I got around this was to create a function (seen below) that returns an array of the actual objectId's of the pointers inside the 'friendsArray'. This way I can guarantee that it will always be returning the same items and can therefore create an accurate 'contains' comparison.
public static List<String> friendsArrayObjectIdsArray() {
//Create Array of Friends
List<ParseUser> friendsArray = ParseUser.getCurrentUser().getList("friendsArray");
//Create Temp Array of Object Id's
List<String> tempObjectIdsArray = new ArrayList<>();
//Iterate List
for (ParseUser friendUser : friendsArray) {
tempObjectIdsArray.add(friendUser.getObjectId());
}
return tempObjectIdsArray;
}
I then run the following comparison to get the result I am looking for
if (FLKUserUtils.friendsArrayObjectIdsArray().contains(searchResultsList.get(position).getObjectId())) {
//Do something
}

How to pass current data from Adapter to Adapter?

Heterogeneous RecyclerView
Hello friends I have a simple doubt
Here i am adding singleLineText
`addSingleLine.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String singleLineText = singleline.getText().toString();
if(singleLineText.length() != 0)
{
mAdapter.addItem(singleLineText,null);
mAdapter.notifyDataSetChanged();
Log.e(TAG,"adding single line text");
}
singleline.getText().clear();
}
});`
On this part i am adding MultiLineText
` addMultiLine.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String multiLineText = multiline.getText().toString();
String myList[] = multiLineText.split(",");
for(String item : myList)
{
mAdapter.addItem(null,item);
mAdapter.notifyDataSetChanged();
Log.e(TAG,"adding multi line text");
}
multiline.getText().clear();
}
});
}`
My Adapter part of code:
` public void addItem(String singleLineText, String item) {
Model model = new Model();
if(item == null) {
model.setText1(singleLineText);
model.settingSingleLineText(true); // How to identify single line
}
else
{
model.setText2(item);
model.settingMultiLineText(true); // How to identify multiple line
}
modelList.add(model);
}`
GetViewType Method:
` public int getItemViewType(int position) {
if (modelList.get(position).IfSingleLine() != null)
return VERTICAL;
else {
return HORIZONTAL;
}
}`
Model class code snippet:
private Boolean checkSingleLine = null;
public Boolean IfSingleLine()
{
return checkSingleLine;
}
public void settingSingleLineText(Boolean txt1)
{
checkSingleLine = txt1;
}
public void settingMultiLineText(Boolean txt2)
{
checkMultiLine = txt2;
}
`
Problem: How to identify the singleLineText and multiLineText by using the Model Class??
You have a problem with your if (modelList.get(position).IfSingleLine() != null). IfSingleLine() will never be null. You want to check if it is true or false and this is not how you check for that.
Change your getItemViewType to the following and you will get correct orientation result from this function.
public int getItemViewType(int position) {
if (modelList.get(position).IfSingleLine())
return VERTICAL;
else {
return HORIZONTAL;
}
}`

looping through an array backwards from current position

I am quite new to java and android so be patient with me. I have an xml layout containing two buttons. One containing text of "previous" and the other "next". I also have a class containing array of strings which loops in an ascending order in a textView when a "next" button is clicked.
What i want is that i want the array to loop backwards from its current position when the "previous" button is clicked. Any ideas?
Question Class
// This file contains questions from QuestionBank
class Question{
// array of questions
private String mQuestions [] = {
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
"",
// method returns number of questions
int getLength(){
return mQuestions.length;
}
// method returns question from array textQuestions[] based on array index
String getQuestion(int a) {
return mQuestions[a];
}
}
Main Activity.java
public class MainActivityextends AppCompatActivity {
private QuestionLibraryBeginner mQuestionLibrary = new QuestionLibraryBeginner();
private int mQuestionNumber = 1; // current question number
//initialising navigation buttons
private Button mPrevious;
private Button mNext;
private TextView mQuestionText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_beginner_review);
mPrevious = (Button) findViewById(R.id.previous);
mNext = (Button) findViewById(R.id.next);
mQuestionText = (TextView) findViewById(R.id.txtQuestion);
// receive the current question number from last activity by Intent
Intent intent = getIntent();
currentQuestionNumber = intent.getIntExtra("quizNumber", 0); // receiving the number of questions the user has attempted from previous activity
mNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// checking against total number of questions the user has attempted instead of total number of questions from Question Class
if (mQuestionNumber < currentQuestionNumber) {
updateQuestion();
}
});
mPrevious.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// i want it to loop backwards from here
}
});
// logic to update question from array
private void updateQuestion() {
if (mQuestionNumber < mQuestionLibrary.getLength()) {
mQuestionText.setText(mQuestionLibrary.getQuestion(mQuestionNumber));
mQuestionNumber++;
}
}
}
I would suggest to do this:
1) Rename updateQuestion method to nextQuestion
2) Create a method to decrease the mQuestionNumber like this:
private void prevQuestion(){
if(mQuestionNumber > 0){
mQuestionText.setText(mQuestionLibrary.getQuestion(mQuestionNumber));
mQuestionNumber--;}
}
Here's a solution accounting for bounds
mNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
showNextQuestion();
}
});
mPrevious.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View view) {
showPreviousQuestion();
}
});
private void showNextQuestion() {
showQuestion(1);
}
private void showPreviousQuestion() {
showQuestion(-1);
}
private void showQuestion(int increment) {
int newQuestionNumber = mQuestionNumber + increment;
if (newQuestionNumber >= 0 && newQuestionNumber < mQuestionLibrary.getLength()) {
mQuestionNumber = newQuestionNumber;
mQuestionText.setText(mQuestionLibrary.getQuestion(mQuestionNumber));
}
}
It can be done by just adding a flag to mention the move,
mNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateQuestion(true);
});
mPrevious.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
updateQuestion(false);
}
});
And the method would look like:
private void updateQuestion(boolean forward) {
if(forward && mQuestionNumber < mQuestionLibrary.getLength())
mQuestionNumber++
else if (mQuestionNumber>1)
mQuestionNumber--;
mQuestionText.setText(mQuestionLibrary.getQuestion(mQuestionNumber));
}
I would change the following methodes:
would remove mQuestionNummer++; from update question.
You can increment mQuestions directly in the onClickMethode of NextButton.
So you can implement your solution simply by decrement mQuestion-- in onClick of previous Button.
Code would look like this:
public class MainActivityextends AppCompatActivity {
private QuestionLibraryBeginner mQuestionLibrary = new
QuestionLibraryBeginner();
private int mQuestionNumber = 1; // current question number
//initialising navigation buttons
private Button mPrevious;
private Button mNext;
private TextView mQuestionText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_beginner_review);
mPrevious = (Button) findViewById(R.id.previous);
mNext = (Button) findViewById(R.id.next);
// receive the current question number from last activity by Intent
Intent intent = getIntent();
mNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mQuestionNumber < mQuestionLibrary.getLength()) {
mQuestionNumber++;
updateQuestion();
}
});
mPrevious.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// i want it to loop backwards from here
if(mQuestionNumber > 0){
mQuestionNumber--;
updateQuestion();
}
else
{}//don't do anything to prevent IndexOutOfBounds
}
});
// logic to update question from array
private void updateQuestion() {
if (mQuestionNumber < mQuestionLibrary.getLength()) {
mQuestionText.setText(mQuestionLibrary.getQuestion(mQuestionNumber));
}
}
}
You need to don't mess logic of your application with view logic, decouple them.
Just make class Question able to provide previous and next questions. Also according to oop principles (solid, grasp) fetch information from class and make decision outside is wrong, make class to do it's work. Oop it's about telling classes to do things, not work instead of them.
class Questions {
private int index = 0;
private String[] mQuestions;
//better to don't hardcode and provide questions in constructor
public Question(String[] questions) {
this.questions = questions;
}
//we don't need this method
int getLength(){
return mQuestions.length;
}
//provide human readable information about current position in question list
// when you want to provide this information to user introduce label field in activity
public String currentPosition() {
int questionPosition = index + 1;
int questionsLength = mQuestions.length;
return String.format("current question number is %d from %d" , questionPosition, questionsLength);
}
//return next question when available, if next not available returns last question from array
public String next() {
int lastIndex = mQuestions.length - 1;
if(index < lastIndex) {
index++;
}
return mQuestions[index];
}
//return current question
public String current() {
return mQuestions[index];
}
//return previous question when available, if previous not available returns first question from array
public String previous() {
int firstIndex = 0;
if(index > firstIndex) {
index--;
}
return mQuestions[index];
}
}
And how to use it in Activity:
public class MainActivity extends AppCompatActivity {
//better to don't hardcode here, but provide this class from
//constructor of MainActivity just like questions array provide
// to constructor in Questions class
private Questions questions = new Questions(new String[]{"q1","q2"});
private Button mPrevious;
private Button mNext;
private TextView mQuestionText;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_beginner_review);
mPrevious = (Button) findViewById(R.id.previous);
mNext = (Button) findViewById(R.id.next);
Intent intent = getIntent();
//when create Activity populate question field with first question
mQuestionText.setText(questions.current());
mNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mQuestionText.setText(questions.next());
}
});
mPrevious.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mQuestionText.setText(questions.previous());
}
});
}
}
p.s. you may improve this code further in way to introduce Observer pattern, Activity is a view, Questions is model.

Categories