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);
}
});
Related
Firebase database contains data for different keys. I need to query and show this data with recyclerview. but since the same data are saved many times in the database, the same results appear many times in recyclerview. I want to prevent this. Even though the queried value is dozens of times in the database, I want it to be displayed only once in recyclerview. How can I do that. I will be happy if you help.
InfiniteFirebaseArray infiniteFirebaseArray = new InfiniteFirebaseArray();
infiniteFirebaseArray.getSearch(areaCode + phoneNumber);
mAdapter = new InfiniteFirebaseRecyclerAdapter<ContactList, NameViewHolder>(ContactList.class, R.layout.layout_search_contact_list_item,
NameViewHolder.class, mUserDatabase, mPageLimit) {
#Override
protected void populateViewHolder(NameViewHolder viewHolder, ContactList model, int position) {
Logger.enter();
if (model != null) {
String string = model.getDisplay_name();
String firstletter = string.substring(0, 1);
resultcount++;
viewHolder.name.setText(model.getDisplay_name());
viewHolder.phone.setText(model.getPhone_number());
viewHolder.userImageText.setText(firstletter);
ContactResult contactResult = new ContactResult();
contactResult.setName(model.getDisplay_name());
contactResult.setPhone(model.getPhone_number());
contactLists.add(contactResult);
Log.d("testcontacts",String.valueOf(contactLists.get(position).getName()));
viewHolder.callPhone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String phoneNumber = contactLists.get(position).getPhone();
callPhone(phoneNumber);
}
});
viewHolder.addContact.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String contactName = contactLists.get(position).getName();
String contactPhoneNumber = contactLists.get(position).getPhone();
addContact(contactName, contactPhoneNumber);
}
});
}
Logger.exit();
}
};
Search_Contact_List.setAdapter(mAdapter);
Search_Contact_List.addOnScrollListener(new EndlessRecyclerViewScrollListener(gridLayoutManager) {
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
Logger.enter();
mAdapter.more();
Logger.exit();
}
});
Database result:
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!
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
}
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.
My Code should frequently update a number (not only show the result, delay of 100) from a loop in an EditText after you click on a button.
Old Code:
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
while (repeat > 0) {
num1 = new Random().nextInt(6)+1;
edit1.setText(String.valueOf(num1));
repeat = repeat - 1;
rep.setText(String.valueOf(repeat));
}
}
});
Now I have this:
final Handler randomHandler = new Handler();
final Runnable randomUpdate = new Runnable() {
#Override
public void run() {
num1 = new Random().nextInt(6) + 1;
edit1.setText(String.valueOf(num1));
repeat--;
rep.setText(String.valueOf(repeat));
randomHandler.postDelayed(this, 1000);
}
};
btnpl5.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
repeat = repeat + 5;
rep.setText(String.valueOf(repeat));
button2.setClickable(true);
button2.setEnabled(true);
}
});
button2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
randomUpdate.run();
button2.setClickable(false);
button2.setEnabled(false);
}
Problem: it won't stop after repeat is 0 (it goes on -1 -2 -3 -4 ..)?
You must always be on the UI thread when calling any method on any
view. If you are doing work on other threads and want to update the
state of a view from that thread, you should use a Handler.
Try this,
handler.postDelayed(new Runnable(){
#Override
public void run() {
num1 = new Random().nextInt(6)+1;
// get previous value and append new generated
edit1.setText(edit1.getText().toString()+String.valueOf(num1));
}
}, (1000)); // run this method in every 1000 milliseconds
This may help you.
You can use an AsyncTask to delay in the background, and publishProgress() to update the UI.
class TextDisplayTask extends AsyncTask<Integer, Integer, Void> {
private int DELAY_MILLIS = 100; // ... set your delay here
#Override
protected Void doInBackground(Integer... params) {
for (int i = 0; i < params[0]; i++) {
int num = new Random().nextInt(6) + 1;
publishProgress(num);
Thread.sleep(DELAY_MILLIS);
}
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
edit1.setText(String.valueOf(values[0]));
}
}
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
new TextDisplayTask().execute(20); // show a number 20 times
}
});