Remove GridView items one by one - android

I want to remove items from a gridView one by one. the problem is that are all removed once !
This is my code
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
boolean sw = false;
while(!sw)
{
int i=0;
if(!adapter.isEmpty())
{
adapter.removeItem(i);
i+=1;
} else sw = true;
}
}
}, 700);
in adapter I've created a remove function.. This it is
public void removeItem(final int position)
{
data.remove(position);
notifyDataSetChanged();
}
Advices ?

The problem is you are running all the remove in one go, try with this
public void removeAllItem()
{
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run()
{
if(!adapter.isEmpty())
{
adapter.removeLastItem();
removeAllItem();
}
}
}, 700);
}
and removeLastItem() is
public void removeLastItem()
{
int lastIndex = data.size() - 1;
data.remove(lastIndex);
notifyDataSetChanged();
}
Which will remove every item from the last index every 700 miliseconds.

Declare object in class level
boolean sw = false;
Change code like below
while (!sw) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
int i = 0;
if (!adapter.isEmpty()) {
adapter.removeItem(i);
i += 1;
} else sw = true;
}
}, 700);
}
Hope it will help you !!

Related

How to get to next object in foreach

Im making a quizz app in android studio.I have a slight issue. I display the questions and answers fine, but when the user click on a button, be it right or wrong answer, i want the next question to come.
I feel its really stupid, but heres what i did.
private void getListe() {
new Thread(new Runnable() {
#Override
public void run() {
QuizzController quizzController = new QuizzController(GameActivity.this);//bon contexte?
liste = quizzController.getGame(difficulte, categorie, nb);
handlerGame.post(new Runnable() {
#Override
public void run() {
Toast.makeText(GameActivity.this,"gg", Toast.LENGTH_SHORT).show();
for(QuizzRoom q : liste ){
tvQuestion.setText(q.question);
btnBadAnswer.setText(q.mauvaisesReponses);
btnGoodAnswer.setText(q.bonneReponse);
}
btnGoodAnswer.setOnClickListener(v -> {
score+=10;
tvScore.setText(String.valueOf(score));
});
}
});
}
}).start();private void getListe() {
new Thread(new Runnable() {
#Override
public void run() {
QuizzController quizzController = new QuizzController(GameActivity.this);//bon contexte?
liste = quizzController.getGame(difficulte, categorie, nb);
handlerGame.post(new Runnable() {
#Override
public void run() {
Toast.makeText(GameActivity.this,"gg", Toast.LENGTH_SHORT).show();
for(QuizzRoom q : liste ){
tvQuestion.setText(q.question);
btnBadAnswer.setText(q.mauvaisesReponses);
btnGoodAnswer.setText(q.bonneReponse);
}
btnGoodAnswer.setOnClickListener(v -> {
score+=10;
tvScore.setText(String.valueOf(score));
});
}
});
}
}).start();
I cannot figure how to get to the next QuizzRoom object (answer+questions). Feels like it should just come right on when the loop starts over, but it doesnt.
Thanks in advance for any tips in the right direction.
This is not the best way but it should work:
private int questionsCount;
new Thread(new Runnable() {
#Override
public void run() {
QuizzController quizzController = new QuizzController(GameActivity.this);//bon contexte?
liste = quizzController.getGame(difficulte, categorie, nb);
//get the size of the list
questionsCount = liste.size()
handlerGame.post(new Runnable() {
#Override
public void run() {
Toast.makeText(GameActivity.this,"gg", Toast.LENGTH_SHORT).show();
btnGoodAnswer.setOnClickListener(v -> {
score+=10;
//will remove the last question form the count
questionsCount--
tvScore.setText(String.valueOf(score));
showQuestion(liste)
});
}
});
}
}).start();
void showQuestion(List<QuizzRoom> questions){
//here you should check if there are any questions left
// if(questionsCount < 0) do something
QuizzRoom q = questions[questionsCount]
tvQuestion.setText(q.question);
btnBadAnswer.setText(q.mauvaisesReponses);
btnGoodAnswer.setText(q.bonneReponse);
}

Android: Handler and Timer inside a RecyclerView is not working properly

In a chatting window I have a feature like self destructing message after a duration. For which I have a class which shows burning animation after the duration. While sending text the handler and timer I used in the below class is working fine for 2-3 times then some animation discrepancy is found like the fire isn't starting in exact location.
Apart from that while sending a file from file chooser fragment when it returns to the recyclerview of the chatwindow nothing happens until I touch the screen and scroll it a bit. While debugging I noticed that the first time when bindview is called after sending a file the handler and timer is not executing properly. Instead if I navigate back and enter the chatwindow again it's working perfectly. It burns the filemessage perfectly then.
The burner class:
public class Burner {
private static final TaggedLogger logger = new TaggedLogger("Burner");
public static void burnMessage(final TextMessageViewHolder holder, final BurnerListener listener) {
final int DURATION = 3000;
if (!holder.isBurning) {
final Handler handler = new Handler(Looper.getMainLooper());
final Animator.AnimatorListener animatorListener = new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
logger.log("onAnimationStart");
}
#Override
public void onAnimationEnd(Animator animator) {
listener.onBurnFinished();
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
};
holder.isBurning = true;
holder.fireAnimationHolder.setVisibility(View.VISIBLE);
holder.fireAnimationHolder.measure(0, 0);
Activity activity = (Activity) ChatProperties.getChatWindowContext();
if (activity != null) {
final ParticleSystem particleSystem = new ParticleSystem(activity, 48, R.drawable.fire_2, DURATION)
.setSpeedByComponentsRange(-0.025f, 0.0f, -0.06f, -0.08f)
.setAcceleration(0.00003f, 0)
.setInitialRotationRange(30, 45)
.addModifier(new AlphaModifier(255, 0, 200, 1000))
.addModifier(new ScaleModifier(0.5f, 2f, 0, 1000));
holder.fireAnimationHolder.post(new Runnable() {
#Override
public void run() {
holder.fireAnimationHolder.measure(0,0);
int fireAnimationHolderWidth = holder.fireAnimationHolder.getWidth();
// logger.log("fireAnimationHolderWidth = " + fireAnimationHolderWidth);
particleSystem.emit(holder.fireSource, 12);
holder.fireSource.animate().translationXBy(fireAnimationHolderWidth).setStartDelay(500).setDuration(DURATION).setListener(animatorListener).start();
holder.fireSourceController.setPivotX(0);
holder.fireSourceController.animate().alpha(1f).scaleX(1f).setDuration(DURATION).start();
}
});
new Timer().scheduleAtFixedRate(new TimerTask() {
int elapsedTime = 0;
#Override
public void run() {
elapsedTime += 300;
if (elapsedTime >= DURATION) {
handler.post(new Runnable() {
#Override
public void run() {
particleSystem.cancel();
}
});
this.cancel();
} else {
handler.post(new Runnable() {
#Override
public void run() {
particleSystem.updateEmitPoint(holder.fireSource, Gravity.CENTER);
}
});
}
}
}, 100, 300);
}
}
}
This burnMessage method is called from the bindview of the TextMessageViewholder's bindview method and FilemessageViewHolder extends TextMessageViewHoler class.
In TextMessageViewHolder's bindview method this function is called if it's a self destructing message:
private void handleMessageBurning(final Message message) {
if (message.imBurnTime > 0 && BurnMessageHelper.animatedBurnMessageEntryMap.containsKey(message.callerId)) {
Log.e("BurnThread","message to be burned");
Burner.burnMessage(this, new BurnerListener() {
#Override
public void onBurnFinished() {
if (ChatProperties.isGroupChat) {
DataHelper.getInstance().deleteGroupMessage(Target.target, message.callerId);
} else {
DataHelper.getInstance().deleteMessage(Target.target, message.callerId);
}
BurnMessageHelper.animatedBurnMessageEntryMap.remove(message.callerId);
isBurning = false;
}
});
} else {
fireAnimationHolder.setVisibility(View.GONE);
}
}
What is happening here? Does the thread of the timer can't run in main thread here due to some reason? Please help. Thanks.
N.B. I tried this in Marshmallow, Nougat and Oreo.

how to change the image automatically in view pager when it reaches the last image it should come to the first image automatically

I am now implementing the view pager and i want to continuously change the image one by one automatically for a particular periods of time may be once in 5 ms .
I also have to manually allow the user to swipe the images (it is working properly)
But the image is not automatically changing and when it reaches the last image it should come to the first image automatically
final Handler handler = new Handler();
final Runnable Update = new Runnable() {
public void run() {
if (currentPage == strImages.length-1) {
currentPage = 0;
}
intro_images.setCurrentItem(currentPage++, true);
}
};
timer = new Timer(); // This will create a new Thread
timer .schedule(new TimerTask() { // task to be scheduled
#Override
public void run() {
handler.post(Update);
}
}, 500, 3000);
I used above code but it does not work properly
try this add addOnPageChangeListener to your viewPager like this
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (position == strImages.length-1) {
currentPage = 0;
}
intro_images.setCurrentItem(currentPage++, true);
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
or for auto change page try this create a time task like this
Timer timer;
timer = new Timer();
timer.scheduleAtFixedRate(new RemindTask(), 0, 3000); // delay*/
private class RemindTask extends TimerTask {
int current = viewPager.getCurrentItem();
#Override
public void run() {
runOnUiThread(new Runnable() {
public void run() {
if (current < strImages.size()) {
viewPager.setCurrentItem(current);
current += 1;
} else {
current = 0;
viewPager.setCurrentItem(current);
}
}
});
}
}
The below code is to get the last position and to scroll to the 1st position:
pager.addOnPageChangeListener(new ViewPager.OnPageChangeListener()
{
#Override
public void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) {
if (position == Yourlist.size()-1) {
pager.setCurrentItem(0);
}
pager.setCurrentItem(position++,true);
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
The below code is For automatic change picture in every 10s using CountDown Timer:
- First you have to declare one array,which will contain your
images,then after you have to use below code.
int i=0;
new CountDownTimer(1000,1000)
{
#Override
public void onTick(long millisUntilFinished) {}
#Override
public void onFinish() {
iV.setImageDrawable(sdk.getContext().getResources().getDrawable(array[i]));
i++;
if(i== array.length-1) {i=0;}
start();
}
}.start();
You don't need the combination of Handler and TimerTask for this, You can use simple Handler like this using Handler.postDelayed
private Handler handler = new Handler();
final Runnable Update = new Runnable() {
public void run() {
int totalCount = intro_images.getAdapter().getCount();
int currentItem = intro_images.getCurrentItem();
if (currentItem == (totalCount - 1)) {
currentItem = 0;
} else {
currentItem = currentItem + 1;
}
intro_images.setCurrentItem(currentItem, true);
handler.postDelayed(this, 3000);
}
};
#Override
protected void onResume() {
super.onResume();
handler.postDelayed(Update, 500);
}
#Override
protected void onPause() {
super.onPause();
if(handler != null) {
handler.removeCallbacks(Update);
}
}
just add listener to your viewpager to get the last position and to scroll to the 1st position.
vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
if(position==yourlist.length){
vp.setCurrentItem(0);
}
}
});
AnimationDrawable animation = new AnimationDrawable();

Android remove all recyclerview with animation on a button click

I have a recycler view. On a button click I want to remove all the items from the recyclerview but the items must be removed with animation.
I am able to remove all the items at once but I don't know how to remove them with animation. Thanks
It's old, but wish this helps someone else as it's already not answered yet; I have done it by deleting a single item at a time by simulating a swipe animation on this item, and post a delay before deleting the next item, and so on to the way down to the last item of the RecyclerView
Step No.1:
In your activity that holds the clear all button and the RecyclerView instance: Create a method of single item delete
private void deleteItem(View rowView, final int position) {
Animation anim = AnimationUtils.loadAnimation(requireContext(),
android.R.anim.slide_out_right);
anim.setDuration(300);
rowView.startAnimation(anim);
new Handler().postDelayed(new Runnable() {
public void run() {
if (myDataSource.size() == 0) {
addEmptyView(); // adding empty view instead of the RecyclerView
return;
}
myDataSource.remove(position); //Remove the current content from the array
myRVAdapter.notifyDataSetChanged(); //Refresh list
}
}, anim.getDuration());
}
Step No.2:
Create the method that will delete all RecyclerView list items >> call it in your button click callback.
boolean mStopHandler = false;
private void deleteAllItems() {
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
if (myDataSource.size() == 0) {
mStopHandler = true;
}
if (!mStopHandler) {
View v = myRecyclerView.findViewHolderForAdapterPosition(0).itemView;
deleteItem(v, 0);
} else {
handler.removeCallbacksAndMessages(null);
}
handler.postDelayed(this, 250);
}
};
requireActivity().runOnUiThread(runnable);
}
Also it's important to handle configuration change in manifest, activity section, as if the configuration changes while clearing your recycler view list, an exception will be raised
<activity
android:name=".activities.MainActivity"
android:configChanges="orientation|screenSize|keyboard"
android:label="#string/app_name">
...
</activity>
This is a pretty good library and what's better is the documentation for it. You can even insert durations for transitions and animations.
Also, remember that if you are using default animation, after calling myDataSet.remove(pos) using adapter.notifyDataSetChanged() while there is an animation ongoing will cause the animation to stop.
Extend BaseItemAnimator class of recyclerview-animators library:
MyAdapter adapter = new MyAdapter(null);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setAdapter(adapter);
recyclerView.setItemAnimator(new MyScaleInLeftAnimator());
findViewById(R.id.button).setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View view) {
int count = adapter.getItemCount();
adapter.clear();
adapter.notifyItemRangeRemoved(0, count);
}
}
);
...
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder{
private ArrayList<String> mItems;
...
public void clear() {
if (mItems != null) {
mItems.clear();
}
}
}
...
public class MyScaleInLeftAnimator extends BaseItemAnimator {
private long lastRemoval;
private int removeCount;
public MyScaleInLeftAnimator() {
lastRemoval = 0;
removeCount = 0;
}
public MyScaleInLeftAnimator(Interpolator interpolator) {
mInterpolator = interpolator;
lastRemoval = 0;
removeCount = 0;
}
#Override protected void preAnimateRemoveImpl(RecyclerView.ViewHolder holder) {
ViewCompat.setPivotX(holder.itemView, 0);
}
#Override protected void animateRemoveImpl(final RecyclerView.ViewHolder holder) {
long time = System.currentTimeMillis();
long d = time - lastRemoval;
if (d < 100) {
removeCount++;
} else {
removeCount = 0;
}
lastRemoval = time;
ViewCompat.animate(holder.itemView)
.scaleX(0)
.scaleY(0)
.setDuration(getRemoveDuration())
.setInterpolator(mInterpolator)
.setListener(new DefaultRemoveVpaListener(holder))
.setStartDelay(removeCount * 100)
.start();
}
#Override protected void preAnimateAddImpl(RecyclerView.ViewHolder holder) {
ViewCompat.setPivotX(holder.itemView, 0);
ViewCompat.setScaleX(holder.itemView, 0);
ViewCompat.setScaleY(holder.itemView, 0);
}
#Override protected void animateAddImpl(final RecyclerView.ViewHolder holder) {
ViewCompat.animate(holder.itemView)
.scaleX(1)
.scaleY(1)
.setDuration(getAddDuration())
.setInterpolator(mInterpolator)
.setListener(new DefaultAddVpaListener(holder))
.setStartDelay(getAddDelay(holder))
.start();
}
}
This is how I have done without using any libraries - by inserting delays in the loop to remove items & restore (if needed)
clearItemsView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final List<LineItem> lineItemsCopy = new ArrayList<>(lineItems);
new Thread(new Runnable() {
#Override
public void run() {
for (int i=0; i<lineItemsCopy.size(); i++) {
runOnUiThread(new Runnable() {
#Override
public void run() {
salesOrderItemListAdapter.removeItem(0);
}
});
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
Snackbar snackbar = Snackbar.make(coordinatorLayout, getString(R.string.items_cleared_message), Snackbar.LENGTH_LONG)
.setAction(getString(R.string.label_undo), new View.OnClickListener() {
#Override
public void onClick(View v) {
new Thread(new Runnable() {
#Override
public void run() {
for (int i=0; i<lineItemsCopy.size(); i++) {
final int finalI = i;
runOnUiThread(new Runnable() {
#Override
public void run() {
salesOrderItemListAdapter.restoreItem(lineItemsCopy.get(finalI), 0);
}
});
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}).setActionTextColor(Color.YELLOW);
snackbar.show();
}
});

Android update ProgressBar with Handler

I would like to update the progressBar with Handler and for loop but without success.
Code:
public void increase_splash_bar (int from, int to)
{
Handler handler1 = new Handler(Looper.getMainLooper());
for (progress_k = from; progress_k<=to ;progress_k++)
{
handler1.postDelayed(new Runnable()
{
#Override
public void run()
{
FrontLayout.update_splash_progress_bar(progress_k, 100);
}
}, 2000);
}
}
Question:
The progress bar increase immediately to the end value instead of progressively.
Why?
Try this:
public void increase_splash_bar (int from, int to)
{
Handler handler1 = new Handler(Looper.getMainLooper());
for (progress_k = from; progress_k<=to ;progress_k++)
{
final int curr_progress_k = progress_k;
handler1.postDelayed(new Runnable()
{
#Override
public void run()
{
FrontLayout.update_splash_progress_bar(curr_progress_k, 100);
}
}, progress_k * 100); // adjust "100" value to adjust speed
}
}
Repeat a task with a time delay?
#inazaruk
private ProgressBar progressBar;
private Handler mHandler;
private int progressInt = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
progressBar = (ProgressBar) findViewById(R.id.pb);
progressBar.setProgress(0);
mHandler = new Handler();
runnable.run();
}
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
updateProgress();
} catch (Exception ignored) {
} finally {
mHandler.postDelayed(runnable, progressInt);
}
}
};
private void updateProgress() {
progressInt += 1;
if (progressInt > 100) {
mHandler.removeCallbacks(runnable);
} else {
progressBar.setProgress(progressInt);
}
}
try this code:
Solution 1
public void increase_splash_bar (int from, int to)
{
Handler handler1 = new Handler();
class Task implements Runnable {
int start,end;
Task(int a,int b) { start = a; end = b;}
#Override
public void run() {
for (int i =start ; i <= end; i++) {
final int value = i;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
handler1.post(new Runnable() {
#Override
public void run() {
progressBar.setProgress(value);
}
});
}
}
}
Thread t = new Thread(new Task(from, to)); //call it
t.start();
}
Solution 2: More Simple
If thread is too much to ask for this problem..
you can use the following solution to use a single Handler to update progressbar:
code
public class HandlerDemo extends Activity
{
ProgressBar bar;
Handler handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
bar.incrementProgressBy(5);
}
};
boolean isRunning = false;
#Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.main);
bar = (ProgressBar) findViewById(R.id.progress);
}
public void onStart()
{
super.onStart();
bar.setProgress(0);
Thread background = new Thread(new Runnable()
{
public void run()
{
try
{
for (int i = 0; i < 20 && isRunning; i++)
{
Thread.sleep(1000);
handler.sendMessage(handler.obtainMessage());
}
}
catch (Throwable t)
{
// just end the background thread
}
}
});
isRunning = true;
background.start();
}
public void onStop()
{
super.onStop();
isRunning = false;
}
}
Hope it helps..

Categories

Resources