I have a ViewPager, and lets imagine, that i am on page 0.
I have a button on this page, and on this button click, i want to show a dialog, and change page to the page 1.
When my page changes to page 1, i want the dialog to dissapear.
When i did it, i didn't see the dialog, it was appearing and dissapearing when page was changed, but i am sure, that i have 1000ms delay between this actions.
Please help, how can i show the dialog?
package com.example.ViewPagerDialog;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
public class MyActivity extends Activity {
private int currentPage;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final MyViewPager viewPager = (MyViewPager) findViewById(R.id.view_pager);
final Button leftSwitcher = (Button) findViewById(R.id.left_switcher);
final Button rightSwitcher = (Button) findViewById(R.id.right_switcher);
final ProgressDialog progressDialog = new ProgressDialog(this);
leftSwitcher.setVisibility(View.GONE);
progressDialog.setTitle("Wait...");
viewPager.setAdapter(new MyPagerAdapter(this));
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
public void onPageScrolled(int i, float v, int i2) {
}
public void onPageSelected(int i) {
progressDialog.dismiss();
currentPage = i;
if (i == 0) {
leftSwitcher.setVisibility(View.GONE);
} else if (i == 1) {
leftSwitcher.setVisibility(View.VISIBLE);
rightSwitcher.setVisibility(View.VISIBLE);
} else if (i == 2) {
rightSwitcher.setVisibility(View.GONE);
}
}
public void onPageScrollStateChanged(int i) {
}
});
leftSwitcher.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
progressDialog.show();
sleepThread();
viewPager.setCurrentItem(currentPage - 1);
}
});
rightSwitcher.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
progressDialog.show();
sleepThread();
viewPager.setCurrentItem(currentPage + 1);
}
});
}
private void sleepThread() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private class MyPagerAdapter extends PagerAdapter {
View[] views = new View[3];
public MyPagerAdapter(Context context) {
TextView view1 = new TextView(context);
TextView view2 = new TextView(context);
TextView view3 = new TextView(context);
view1.setText("View 1");
view2.setText("View 2");
view3.setText("View 3");
views[0] = view1;
views[1] = view2;
views[2] = view3;
}
#Override
public int getCount() {
return views.length;
}
#Override
public boolean isViewFromObject(View view, Object o) {
return (view.equals(o));
}
#Override
public Object instantiateItem(ViewGroup collection, int position) {
collection.addView(views[position]);
return views[position];
}
#Override
public void destroyItem(android.view.ViewGroup container, int position, java.lang.Object object) {
container.removeView(views[position]);
}
}
}
First of all, never block the UI thread with Thread.sleep() like you do. By using Thread.sleep() you'll basically set the show command for the dialog(which will happen after you return from the onCLick() method), sleep one second(and your app will freeze) and then set the page on the ViewPager which will trigger the listener, dismissing the dialog. Instead you could use a Handler to
private Handler mHandler = new Handler();
// in the onClick method
progressDialog.show();
mHandler.postDelayed(new Runnable() {
#Override
public void run() {
viewPager.setCurrentItem(currentPage - 1);
}
}, 1000);
Related
I'm implementing Swipe stack demo from here. Now I want track progress of swiped cards. I already made my own logic, and it's working pretty fine. but I've one more functionality, which is while clicking on previous button, user can see one by one all swiped cards in reverse order.
But my swiped card progress stack is not working in that case. How can I do this?
Explain: not total swiped cards count, but which one card is currently I'm seeing like 4 Out of 10
DisplayCardActivity:
package com.jimmytrivedi.cardswipedemo.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.jimmytrivedi.cardswipedemo.Adapter.SwipeStackAdapter;
import com.jimmytrivedi.cardswipedemo.Data.FetchDataFromUriAsyncTask;
import com.jimmytrivedi.cardswipedemo.Listener.JSONDataListener;
import com.jimmytrivedi.cardswipedemo.R;
import com.jimmytrivedi.cardswipedemo.View.SwipeStack;
import java.util.ArrayList;
import butterknife.BindView;
import butterknife.ButterKnife;
public class DisplayCardActivity extends BaseActivity implements SwipeStack.SwipeStackListener, View.OnClickListener, JSONDataListener {
public static final String TAG = DisplayCardActivity.class.getSimpleName();
#BindView(R.id.previous)
ImageButton mPrevious;
#BindView(R.id.next)
ImageButton mNext;
#BindView(R.id.swipe_stack)
SwipeStack mSwipeStack;
#BindView(R.id.fab)
FloatingActionButton mFAB;
#BindView(R.id.card_progress)
TextView cardProgress;
private FetchDataFromUriAsyncTask dataFromUriAsyncTask;
private ProgressDialog progressDialog;
private ArrayList<String> mData;
private ArrayList<String> mTempData;
private int mCurrentCardPosition = 1, lastSwipedPosition = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
init();
}
#Override
protected int getLayoutResource() {
return R.layout.activity_display_card;
}
private void init() {
ButterKnife.bind(this);
setClickListener();
mTempData = new ArrayList<>();
mPrevious.setEnabled(false);
mPrevious.setColorFilter(getResources().getColor(R.color.colorGray));
dataFromUriAsyncTask = new FetchDataFromUriAsyncTask(this, this);
dataFromUriAsyncTask.setJSONDataListener(this);
progressDialog = new ProgressDialog(this);
loadDataFromUrl();
}
private void setClickListener() {
mPrevious.setOnClickListener(this);
mNext.setOnClickListener(this);
mFAB.setOnClickListener(this);
}
private void loadDataFromUrl() {
//Showing progress dialog
progressDialog.setMessage("Fetching Data from...");
progressDialog.setCancelable(false);
progressDialog.show();
dataFromUriAsyncTask.execute();
}
private void changePreviousButtonStatus(int positionValue) {
if (lastSwipedPosition == positionValue) {
mPrevious.setEnabled(false);
mPrevious.setColorFilter(getResources().getColor(R.color.colorGray));
} else {
mPrevious.setEnabled(true);
mPrevious.setColorFilter(getResources().getColor(R.color.colorBlack));
}
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.previous:
changePreviousButtonStatus(1);
lastSwipedPosition = lastSwipedPosition - 1;
if (lastSwipedPosition >= 0) {
mTempData.clear();
for (int i = lastSwipedPosition; i < mData.size(); i++) {
mTempData.add(mData.get(i));
}
mSwipeStack.resetStack();
setCurrentCardPosition(lastSwipedPosition);
} else {
lastSwipedPosition = 0;
}
break;
case R.id.next:
changePreviousButtonStatus(1);
mSwipeStack.swipeTopViewToRight();
break;
case R.id.fab:
mPrevious.setEnabled(false);
mPrevious.setColorFilter(getResources().getColor(R.color.colorGray));
lastSwipedPosition = 0;
mTempData.clear();
mTempData.addAll(mData);
mSwipeStack.resetStack();
if (mData != null)
cardProgress.setText(getResources().getString(R.string.default_count) + mData.size());
break;
}
}
#Override
public void onViewSwipedToLeft(int position) {
mCurrentCardPosition = position + 2;
setCurrentCardPosition(mCurrentCardPosition);
lastSwipedPosition = position + 1;
changePreviousButtonStatus(0);
}
#Override
public void onViewSwipedToRight(int position) {
mCurrentCardPosition = position + 2;
setCurrentCardPosition(mCurrentCardPosition);
lastSwipedPosition = position + 1;
changePreviousButtonStatus(0);
}
#Override
public void onStackEmpty() {
cardProgress.setText("No card in stack");
}
#Override
public void onClickData(ArrayList<String> getData) {
// Dismiss the progress dialog
if (progressDialog.isShowing())
progressDialog.dismiss();
mData = new ArrayList<>(getData);
mTempData.addAll(mData);
setCurrentCardPosition(mCurrentCardPosition);
SwipeStackAdapter mAdapter = new SwipeStackAdapter(mTempData);
mSwipeStack.setAdapter(mAdapter);
mSwipeStack.setListener(this);
}
#Override
public void onJSONParsingError(String error) {
if (progressDialog.isShowing())
progressDialog.dismiss();
showToast(getString(R.string.user_error), Toast.LENGTH_LONG);
}
private void showToast(String message, int length) {
Toast.makeText(this, message, length).show();
}
private void showLog(String msg) {
Log.d(TAG, msg);
}
private void setCurrentCardPosition(int currentPosition) {
cardProgress.setText(currentPosition + " Out of " + mData.size());
}
}
Adapter:
package com.jimmytrivedi.cardswipedemo.Adapter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.jimmytrivedi.cardswipedemo.R;
import java.util.List;
public class SwipeStackAdapter extends BaseAdapter {
public static final String TAG = SwipeStackAdapter.class.getSimpleName();
private List<String> mData;
public SwipeStackAdapter(List<String> data) {
this.mData = data;
}
#Override
public int getCount() {
return mData.size();
}
#Override
public String getItem(int position) {
return mData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.card, parent, false);
TextView textViewCard = convertView.findViewById(R.id.textViewCard);
textViewCard.setText(mData.get(position));
return convertView;
}
private void showLog(String msg) {
Log.d(TAG, msg);
}
}
Problem:
Use case: I've 10 cards (001, 002..010). And there are total 5 things.
1. Left swipe
2. Right seipe
3. Previous button
4. Next button
5. Reset button
If I start right swiping 001 then 002 now I pressed next button for 003 and 004. Now I pressed previous button then again next and again previous,. That time order is not mainting.
Hold a global variable and increment it on SwipeLeft and SwipeRight callback
private int totalCardsSwiped = 0;
#Override
public void onViewSwipedToLeft(int position) {
totalCardsSwiped++; }
#Override
public void onViewSwipedToRight(int position) {
totalCardsSwiped++; }
Why are you doing this in swiped callback methods?
mCurrentCardPosition = position + 2;
I think here is the problem.
or you can call this setCurrentCardPosition() method with the current position
#Override
public void onViewSwipedToLeft(int position) {
mCurrentCardPosition = position + 2;
setCurrentCardPosition(position);
lastSwipedPosition = position + 1;
changePreviousButtonStatus(0);
}
#Override
public void onViewSwipedToRight(int position) {
mCurrentCardPosition = position + 2;
setCurrentCardPosition(position);
lastSwipedPosition = position + 1;
changePreviousButtonStatus(0);
}
Edited
int currentPosition = 1;
After Adding Data in list
txtCardProgress.setText("1 out of " + mData.size());
in onClick
#Override
public void onClick(View v) {
if (v.equals(mButtonLeft)) {
swipedLastPosition = swipedLastPosition - 1;
currentPosition =currentPosition -1;
if (swipedLastPosition >= 0) {
mTempData.clear();//clear all data
for (int i = swipedLastPosition; i < mData.size(); i++) {
mTempData.add(mData.get(i));
}
mSwipeStack.resetStack();
if (swipedLastPosition == 0) {
Toast.makeText(this, "hide back button", Toast.LENGTH_SHORT).show();
}
currentPosition =currentPosition -1;
setCardProgress(currentPosition);
} else {
swipedLastPosition = 0;
currentPosition = 0;
setCardProgress(currentPosition);
}
} else if (v.equals(mButtonRight)) {
mSwipeStack.swipeTopViewToRight();
} else if (v.equals(mFab)) {
swipedLastPosition = 0;
mTempData.clear();
mTempData.addAll(mData);
mSwipeStack.resetStack();
setCardProgress(swipedLastPosition);
}
Callback Methods
#Override
public void onViewSwipedToRight(int position) {
swipedLastPosition = position + 1;
setCardProgress(position);
}
#Override
public void onViewSwipedToLeft(int position) {
swipedLastPosition = position;
setCardProgress(position);
}
Update Progress method
void setCardProgress(int position) {
if (position == mData.size()-1) {
currentPosition = mData.size();
txtCardProgress.setText(currentPosition + " out of " + mData.size());
} else {
currentPosition++;
txtCardProgress.setText(currentPosition + " out of " + mData.size());
}
}
I used the code from Android Hive. Now android studio shows this class uses deprecated api. But don't know which class.
I tried with some classes. My minimum SDK version is 11.
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
public class WelcomeScreen extends AppCompatActivity {
private ViewPager viewPager;
private MyViewPagerAdapter myViewPagerAdapter;
private LinearLayout dotsLayout;
private TextView[] dots;
private int[] layouts;
private Button btnSkip, btnNext;
private PrefManager prefManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Checking for first time launch - before calling setContentView()
prefManager = new PrefManager(this);
if (!prefManager.isFirstTimeLaunch()) {
launchHomeScreen();
finish();
}
// Making notification bar transparent
if (Build.VERSION.SDK_INT >= 21) {
getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
}
setContentView(package_name.R.layout.activity_welcome_screen);
viewPager = (ViewPager) findViewById(package_name.R.id.view_pager);
dotsLayout = (LinearLayout) findViewById(package_name.R.id.layoutDots);
btnSkip = (Button) findViewById(package_name.R.id.btn_skip);
btnNext = (Button) findViewById(package_name.R.id.btn_next);
// layouts of all welcome sliders
// add few more layouts if you want
layouts = new int[]{
};
// adding bottom dots
addBottomDots(0);
// making notification bar transparent
changeStatusBarColor();
myViewPagerAdapter = new MyViewPagerAdapter();
viewPager.setAdapter(myViewPagerAdapter);
viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
btnSkip.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
launchHomeScreen();
}
});
btnNext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// checking for last page
// if last page home screen will be launched
int current = getItem(+1);
if (current < layouts.length) {
// move to next screen
viewPager.setCurrentItem(current);
} else {
launchHomeScreen();
}
}
});
}
private void addBottomDots(int currentPage) {
dots = new TextView[layouts.length];
int[] colorsActive = getResources().getIntArray(package_name.R.array.array_dot_active);
int[] colorsInactive = getResources().getIntArray(package_name.R.array.array_dot_inactive);
dotsLayout.removeAllViews();
for (int i = 0; i < dots.length; i++) {
dots[i] = new TextView(this);
dots[i].setText(Html.fromHtml("•"));
dots[i].setTextSize(35);
dots[i].setTextColor(colorsInactive[currentPage]);
dotsLayout.addView(dots[i]);
}
if (dots.length > 0)
dots[currentPage].setTextColor(colorsActive[currentPage]);
}
private int getItem(int i) {
return viewPager.getCurrentItem() + i;
}
private void launchHomeScreen() {
prefManager.setFirstTimeLaunch(false);
startActivity(new Intent(WelcomeScreen.this, class2.class));
finish();
}
// viewpager change listener
ViewPager.OnPageChangeListener viewPagerPageChangeListener = new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
addBottomDots(position);
// changing the next button text 'NEXT' / 'GOT IT'
if (position == layouts.length - 1) {
// last page. make button text to GOT IT
btnNext.setText(getString(package_name.R.string.start));
btnSkip.setVisibility(View.GONE);
} else {
// still pages are left
btnNext.setText(getString(package_name.R.string.next));
btnSkip.setVisibility(View.VISIBLE);
}
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
};
/**
* Making notification bar transparent
*/
private void changeStatusBarColor() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.TRANSPARENT);
}
}
/**
* View pager adapter
*/
public class MyViewPagerAdapter extends PagerAdapter {
private LayoutInflater layoutInflater;
public MyViewPagerAdapter() {
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(layouts[position], container, false);
container.addView(view);
return view;
}
#Override
public int getCount() {
return layouts.length;
}
#Override
public boolean isViewFromObject(View view, Object obj) {
return view == obj;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = (View) object;
container.removeView(view);
}
}
}
This is my WelcomeScreen.java
I am using latest Android Studio
these are in build.gradle
compileSdkVersion 27
buildToolsVersion '28.0.3'
minSdkVersion 16
targetSdkVersion 26
Anyone know how to find this? or is there any debug tool or something with Android Studio??
private PrefManager prefManager;
PrefManager class has been deprecated. Android Documentation
If you did not get notified by android studio then just go check the android docs for the classes you used.
When app is started it works fine i can swipe left and right without any problem. But as soon as app is been minimized and resumed it again calls the loader and data is been fetched again it results into more no of dots in bottom.
ps: The loader is been called again as dots are in onLoadfinshed.
At first launch
Intial launch
After minimizing and resuming the app
after resuming
package com.example.kaushal.slider;
/**
* Created by kaushal on 25-09-2017.
*/
import android.app.LoaderManager;
import android.content.Loader;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.LinearLayout;
import java.util.List;
public class MainActivity1 extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<video1>> {
customadap adap;
ViewPager viewPager;
private List<video1> videolist;
int LoaderId = 1;
LinearLayout slidedotepanel;
int dotscount;
ImageView[] dots;
String jsonurl = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
viewPager =(ViewPager)findViewById(R.id.viewpager);
slidedotepanel = (LinearLayout)findViewById(R.id.SliderDots);
LoaderManager lm = getLoaderManager();
lm.initLoader(LoaderId,null,this);
}
#Override
public Loader<List<video1>> onCreateLoader(int i, Bundle bundle) {
return new videoLoader1(this,jsonurl);
}
#Override
public void onLoadFinished(Loader<List<video1>> loader, List<video1> videos) {
adap = new customadap(videos,this);
viewPager.setAdapter(adap);
dotscount = adap.getCount();
dots = new ImageView[dotscount];
for(int i = 0;i<dotscount;i++) {
dots[i] = new ImageView(this);
dots[i].setImageDrawable(ContextCompat.getDrawable(this, R.drawable.nonactive_dot));
LinearLayout.LayoutParams layout_linear = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
layout_linear.setMargins(8, 0, 8, 0);
slidedotepanel.addView(dots[i], layout_linear);
}
dots[0].setImageDrawable(ContextCompat.getDrawable(this,R.drawable.active_dot));
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
for(int i =0; i<dotscount;i++){
dots[i].setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.nonactive_dot));
}
dots[position].setImageDrawable(ContextCompat.getDrawable(getApplicationContext(), R.drawable.active_dot));
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
#Override
public void onLoaderReset(Loader<List<video1>> loader) {
}
/*
public void getlib(){
StringRequest stringRequest = new StringRequest(jsonurl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray jsonArray = new JSONArray(response);
JSONObject jsonObject = jsonArray.getJSONObject(0);
JSONArray jarray = jsonObject.getJSONArray("videolist");
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
}*/
}
Updated: currently i am handling it via deleting the loader on LoadFinished in last line it works fine but won't able to handle orientation changes any better approach appreciated.
In the Activity's onCreate, we should check with the load manager if an existing thread already exists. If it does, we should not call initLoader. I've provided a simple example of how to use AsyncTaskLoader.
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import java.lang.ref.WeakReference;
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Integer> {
private static final String TAG = MainActivity.class.getSimpleName();
private static final int TASK_LOADER_ID = 10;
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.d(TAG, "onCreate. Entered function.");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LoaderManager loaderManager = getSupportLoaderManager();
Loader<Integer> myLoader = loaderManager.getLoader(TASK_LOADER_ID);
if (myLoader != null && MyAsyncTask.isRunning()) {
Log.d(TAG, "onCreate --> Existing loader exists and is running. Re-using it.");
// We use initLoader instead of restartLoader as callbacks
// must be replaced with those from this new activity
loaderManager.initLoader(TASK_LOADER_ID, null, this);
MyAsyncTask.setActivity(new WeakReference<>(this));
showProcess( true);
} else {
Log.d(TAG, "onCreate --> Loader is not active.");
showProcess( false);
}
}
private void showProcess(boolean pShowProcess) {
SeekBar seekBar = (SeekBar) findViewById(R.id.sb_progress);
Button btnStart = (Button) findViewById(R.id.btn_start);
Button btnCancel = (Button) findViewById(R.id.btn_cancel);
if (pShowProcess) {
seekBar.setVisibility(View.VISIBLE);
btnStart.setEnabled(false);
btnCancel.setEnabled(true);
}
else {
seekBar.setVisibility(View.INVISIBLE);
seekBar.setProgress(0);
btnStart.setEnabled(true);
btnCancel.setEnabled(false);
}
}
public void clickStart(View view) {
LoaderManager loaderManager = getSupportLoaderManager();
// Restart existing loader if it exists, otherwise a new one (initLoader) is auto created
loaderManager.restartLoader(TASK_LOADER_ID, null, this);
}
// A graceful attempt to stop the loader
public void clickCancel(View view) {
Loader<Integer> myLoader = getSupportLoaderManager().getLoader(TASK_LOADER_ID);
if (myLoader != null) {
MyAsyncTask.cancelled(true);
}
}
#Override
public Loader<Integer> onCreateLoader(int pID, Bundle pArgs) {
Log.d(TAG, "onCreateLoader. Entered function.");
showProcess(true);
return new MyAsyncTask(this);
}
#Override
public void onLoadFinished(Loader<Integer> pLoader, Integer pResult) {
Log.d(TAG, "onLoadFinished --> Number of items processed = " + pResult);
showProcess( false);
getLoaderManager().destroyLoader(TASK_LOADER_ID);
}
#Override
public void onLoaderReset(Loader<Integer> pLoader) { }
private static class MyAsyncTask extends AsyncTaskLoader<Integer> {
private final static int SLEEP_TIME = 10 * 10; // 100 milliseconds
static WeakReference<MainActivity> aActivity;
private static boolean isRunning = false, cancelled = true;
private Integer aResult; // Holds the results once the task is finished or cancelled
MyAsyncTask(MainActivity pActivity) {
super(pActivity);
aActivity = new WeakReference<>(pActivity);
}
synchronized static void setActivity(WeakReference<MainActivity> pActivity) {
aActivity = pActivity;
}
synchronized static void cancelled(boolean pCancelled) {
cancelled = pCancelled;
}
static boolean isRunning() {
return isRunning;
}
#Override
protected void onStartLoading() {
Log.d(TAG, "onStartLoading. Entered function. cancelled = " + cancelled);
super.onStartLoading();
if (aResult != null) {
deliverResult(aResult);
return;
}
if (!isRunning) { // Don't start a new process unless explicitly initiated by clickStart
Log.d(TAG, "onStartLoading --> No existing process running, so we can start a new one.");
forceLoad();
}
}
#Override
public Integer loadInBackground() {
Log.d(TAG, "loadInBackground. Entered function.");
isRunning = true;
cancelled = false;
int i;
for (i = 1; i < 100 && !cancelled; i++) {
try {
Thread.sleep(SLEEP_TIME);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
if (aActivity.get() != null) {
SeekBar seekBar = (SeekBar) aActivity.get().findViewById(R.id.sb_progress);
seekBar.setProgress(i);
}
if (i % 15 == 0) {
Log.d(TAG, "Process running with i = " + i);
}
}
isRunning = false;
aResult = i;
return aResult;
}
}
}
activity_main.xml is given below.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.snoopy.loadertest.MainActivity">
<SeekBar
android:id="#+id/sb_progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickStart"
android:text="Start Process"
app:layout_constraintBottom_toTopOf="#id/sb_progress"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
When the 'Start Button' is clicked, it makes the SeekBar visible and starts the AsyncTaskLoader in a separate thread. While the task is running, you can rotate the device and send it to the background. On restarting the app, onCreate checks if the task exists. If so, it updates the new Activity object to the task so that the new progress bar can be updated by the task. I've tested this and it works. This should give you a better idea on how to use AsyncTaskLoader and manage resume.
I am new to android development and I am trying to pass a Boolean value from dialog fragment to the activity.
the boolean value is supposed to be decided by the user(depends on which button user clicked). However, the boolean immediately turned to false without clicking any button.
I have tried various method recommended I found on internet but none of them works for me(I guess I have some part screwed up...), these method include:
-broadcasting
-implementing interface
-intent.putExtra
and below is the code that I have came up with, could anyone help me take a look? Any help is appreciated.
Stage:
package com.example.fuj.valorsafeworldbytrade;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import static com.example.fuj.valorsafeworldbytrade.LosingDialogFragment.LOSING_FRAGMENT;
public class Stage extends AppCompatActivity {
String stage;
FragmentManager fragmentManager = getSupportFragmentManager();
LosingDialogFragment losingDialogFragment = new LosingDialogFragment();
BasicInfo basicInfo = new BasicInfo();
public void setText(){
TextView cpuReputation = (TextView) findViewById(R.id.cpu_reputation);
TextView cpuGold = (TextView) findViewById(R.id.cpu_gold);
TextView pGoldText = (TextView) findViewById(R.id.player_gold);
TextView pRepText = (TextView) findViewById(R.id.player_reputation);
cpuReputation.setText(String.valueOf(basicInfo.cRep));
cpuGold.setText(String.valueOf(basicInfo.cGold));
pGoldText.setText(String.valueOf(basicInfo.pGold));
pRepText.setText(String.valueOf(basicInfo.pRep));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stage);
setText();
}
protected void onStart() {
super.onStart();
stage = getIntent().getStringExtra(StageChoosingMenu.STAGE);
}
public void playerChoice(View view) {
boolean deceiveEnabled;
switch (view.getId()) {
case R.id.cooperate_button:
deceiveEnabled = false;
break;
case R.id.deceive_button:
deceiveEnabled = true;
break;
default:
throw new RuntimeException("Unknown Button ID");
}
switch (stage){
case "xumo":
xuMo(deceiveEnabled);
break;
}
}
public void xuMo(boolean playerDeceiveEnabled){
boolean cpuDeceiveEnabled;
cpuDeceiveEnabled = (Math.random() - basicInfo.faith > 0);
if (cpuDeceiveEnabled){
if (playerDeceiveEnabled){
basicInfo.playerDvsCpuD();
// faith changes to be amend w/ proper value, need record on the change of status
}
if (!playerDeceiveEnabled){
basicInfo.playerCvsCpuD();
}
}
if (!cpuDeceiveEnabled){
if (playerDeceiveEnabled){
basicInfo.playerDvsCpuC();
}
if (!playerDeceiveEnabled){
basicInfo.playerCvsCpuC();
}
}
if(basicInfo.pGold <= 0 || basicInfo.cGold <= 0 || basicInfo.pRep <= 0 || basicInfo.cRep <= 0){
//to be changed
setText();
losingDialogFragment.show(fragmentManager,LOSING_FRAGMENT);
//trying to show a alert dialog fragment
Log.d("True", String.valueOf(losingDialogFragment.tryAgainEnabled));
if(losingDialogFragment.tryAgainEnabled){//tryAgainEnabled is always false
//This is the part that I wanted to retrieve data from the user(if they want to try again or not)
basicInfo.reset();
losingDialogFragment.dismiss();
}else{
losingDialogFragment.dismiss();
}
}
setText();
// to be changed
}
}
LosingDialogFragment:
package com.example.fuj.valorsafeworldbytrade;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
/**
* Created by fuj on 20/1/2017.
*/
public class LosingDialogFragment extends DialogFragment{
public static final String LOSING_FRAGMENT = "LOSING";
public boolean tryAgainEnabled;
Intent intent = new Intent();
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.fragment_lose, container, false);;
//the following code is used to set the boolean value after the user click the button
final Button tryAgainButton = (Button)rootView.findViewById(R.id.try_again_button);
tryAgainButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tryAgainEnabled = true;
}
});
Button giveUpButton =(Button)rootView.findViewById(R.id.give_up_button);
giveUpButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
tryAgainEnabled = false;
}
});
getDialog().setTitle(LOSING_FRAGMENT);
return rootView;
}
}
I am also sorry that I am not the best with English, if any things is not clear or not polite because of my poor English, please kindly let me know. I apologize in advance for any mistakes I have made.
It's because you check the value of tryAgainEnabled exactly right after showing the Dialog. Dialog starts Asynchronously, It means that it starts in diffrent Thread and your current thread doesn't wait for dismissing Dialog, So this line of your code if(losingDialogFragment.tryAgainEnabled){ runs exactly after you show dialog, befor you set value to tryAgainEnabled. Because the default value of boolean is always false, you will get false everytime.
I suggest that use listener for this:
Dialog:
public class LosingDialogFragment extends DialogFragment {
public static final String LOSING_FRAGMENT = "LOSING";
public boolean tryAgainEnabled;
Intent intent = new Intent();
private View.OnClickListener onTryAgainButtonClickLisnter;
private View.OnClickListener onGiveUpButtonClickLisnter;
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.fragment_lose, container, false);;
final Button tryAgainButton = (Button)rootView.findViewById(R.id.try_again_button);
tryAgainButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(onTryAgainButtonClickLisnter!=null)
onTryAgainButtonClickLisnter.onClick(v);
}
});
Button giveUpButton =(Button)rootView.findViewById(R.id.give_up_button);
giveUpButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(onGiveUpButtonClickLisnter!=null)
onGiveUpButtonClickLisnter.onClick(v);
}
});
getDialog().setTitle(LOSING_FRAGMENT);
return rootView;
}
public void setOnTryAgainButtonClickLisnter(View.OnClickListener onTryAgainButtonClickLisnter) {
this.onTryAgainButtonClickLisnter = onTryAgainButtonClickLisnter;
}
public void setOnGiveUpButtonClickLisnter(View.OnClickListener onGiveUpButtonClickLisnter) {
this.onGiveUpButtonClickLisnter = onGiveUpButtonClickLisnter;
}
}
In your activity call dialog like this:
LosingDialogFragment losingDialogFragment = new LosingDialogFragment();
losingDialogFragment.setOnTryAgainButtonClickLisnter(new View.OnClickListener() {
#Override
public void onClick(View v) {
tryAgain();
losingDialogFragment.dismiss();
}
});
losingDialogFragment.setOnGiveUpButtonClickLisnter(new View.OnClickListener() {
#Override
public void onClick(View v) {
giveUp();
losingDialogFragment.dismiss();
}
});
losingDialogFragment.show(fragmentManager, "");
Declare public boolean tryAgainEnabled; in your Stage Activity and youd can update that variable using ((Stage)context).tryAgainEnabled.
package com.example.fuj.valorsafeworldbytrade;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import static com.example.fuj.valorsafeworldbytrade.LosingDialogFragment.LOSING_FRAGMENT;
public class Stage extends AppCompatActivity {
String stage;
FragmentManager fragmentManager = getSupportFragmentManager();
LosingDialogFragment losingDialogFragment = new LosingDialogFragment();
BasicInfo basicInfo = new BasicInfo();
public boolean tryAgainEnabled;
public void setText(){
TextView cpuReputation = (TextView) findViewById(R.id.cpu_reputation);
TextView cpuGold = (TextView) findViewById(R.id.cpu_gold);
TextView pGoldText = (TextView) findViewById(R.id.player_gold);
TextView pRepText = (TextView) findViewById(R.id.player_reputation);
cpuReputation.setText(String.valueOf(basicInfo.cRep));
cpuGold.setText(String.valueOf(basicInfo.cGold));
pGoldText.setText(String.valueOf(basicInfo.pGold));
pRepText.setText(String.valueOf(basicInfo.pRep));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_stage);
setText();
}
protected void onStart() {
super.onStart();
stage = getIntent().getStringExtra(StageChoosingMenu.STAGE);
}
public void playerChoice(View view) {
boolean deceiveEnabled;
switch (view.getId()) {
case R.id.cooperate_button:
deceiveEnabled = false;
break;
case R.id.deceive_button:
deceiveEnabled = true;
break;
default:
throw new RuntimeException("Unknown Button ID");
}
switch (stage){
case "xumo":
xuMo(deceiveEnabled);
break;
}
}
public void xuMo(boolean playerDeceiveEnabled){
boolean cpuDeceiveEnabled;
cpuDeceiveEnabled = (Math.random() - basicInfo.faith > 0);
if (cpuDeceiveEnabled){
if (playerDeceiveEnabled){
basicInfo.playerDvsCpuD();
// faith changes to be amend w/ proper value, need record on the change of status
}
if (!playerDeceiveEnabled){
basicInfo.playerCvsCpuD();
}
}
if (!cpuDeceiveEnabled){
if (playerDeceiveEnabled){
basicInfo.playerDvsCpuC();
}
if (!playerDeceiveEnabled){
basicInfo.playerCvsCpuC();
}
}
if(basicInfo.pGold <= 0 || basicInfo.cGold <= 0 || basicInfo.pRep <= 0 || basicInfo.cRep <= 0){
//to be changed
setText();
losingDialogFragment.show(fragmentManager,LOSING_FRAGMENT);
Log.d("True", String.valueOf(losingDialogFragment.tryAgainEnabled));
if(losingDialogFragment.tryAgainEnabled){//tryAgainEnabled is always false
basicInfo.reset();
losingDialogFragment.dismiss();
}else{
losingDialogFragment.dismiss();
}
}
setText();
// to be changed
}
}
And in Fragment
package com.example.fuj.valorsafeworldbytrade;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
/**
* Created by fuj on 20/1/2017.
*/
public class LosingDialogFragment extends DialogFragment{
public static final String LOSING_FRAGMENT = "LOSING";
Context context;
Intent intent = new Intent();
#Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View rootView = inflater.inflate(R.layout.fragment_lose, container, false);;
final Button tryAgainButton = (Button)rootView.findViewById(R.id.try_again_button);
tryAgainButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((Stage)context).tryAgainEnabled = true;
}
});
Button giveUpButton =(Button)rootView.findViewById(R.id.give_up_button);
giveUpButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((Stage)context).tryAgainEnabled = false;
}
});
getDialog().setTitle(LOSING_FRAGMENT);
return rootView;
}
}
I created a simple crossfade image class for use in my app. But... i have an error i can't fix due to lack of knowledge. I found this post This Handler class should be static or leaks might occur: IncomingHandler but i have no clue how to fix this in my class. It is a very straightforward class. Create, initialize and start to use it.
I hope someone can help me fix this warning and while we are at it, some hints and tips on my code or comments are very welcome too ;)
MainActivity.java
package com.example.crossfadeimage;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
Xfade xfade = new Xfade();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// INIT(current activity, image id's, time between fades, fade speed)
xfade.init(this, new int[]{ R.id.image1, R.id.image2, R.id.image3 }, 3000, 500);
xfade.start();
}
}
Xfade.java
package com.example.crossfadeimage;
import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.ImageView;
public class Xfade {
private Activity activity;
// Handler
private Handler handlerTimer = new Handler();
private static final int UPDATE_STUFF_ON_DIALOG = 999;
private int updateTime;
private Animation fadeIn;
private Animation fadeOut;
public int[] xfadeImages;
public int xfadeCounter = 1;
public void init(Activity thisActivity, int[] images, int time,
int animationSpeed) {
activity = thisActivity;
xfadeImages = images;
updateTime = time;
// Set Animations
fadeIn = new AlphaAnimation(0, 1);
fadeIn.setDuration(animationSpeed);
fadeOut = new AlphaAnimation(1, 0);
fadeOut.setDuration(animationSpeed);
// Hide all images except the first
// which is always visible
for (int image = 1; image < xfadeImages.length; image++) {
ImageView thisImage = (ImageView) activity
.findViewById(xfadeImages[image]);
thisImage.setVisibility(4);
}
}
public void start() {
handlerTimer.removeCallbacks(taskUpdateStuffOnDialog);
handlerTimer.postDelayed(taskUpdateStuffOnDialog, updateTime);
}
private Runnable taskUpdateStuffOnDialog = new Runnable() {
public void run() {
Message msg = new Message();
msg.what = UPDATE_STUFF_ON_DIALOG;
handlerEvent.sendMessage(msg);
// Repeat this after 'updateTime'
handlerTimer.postDelayed(this, updateTime);
}
};
private Handler handlerEvent = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UPDATE_STUFF_ON_DIALOG: {
crossFade();
}
break;
default: {
super.handleMessage(msg);
}
break;
}
}
};
public void crossFade() {
if (xfadeCounter == 0) {
ImageView lastImage = (ImageView) activity
.findViewById(xfadeImages[xfadeImages.length - 1]);
lastImage.setVisibility(4);
}
if (xfadeCounter < xfadeImages.length) {
ImageView thisImage = (ImageView) activity
.findViewById(xfadeImages[xfadeCounter]);
thisImage.setVisibility(0);
thisImage.startAnimation(fadeIn);
xfadeCounter++;
} else {
// Hide all images except the first
// before fading out the last image
for (int image = 1; image < xfadeImages.length; image++) {
ImageView thisImage = (ImageView) activity
.findViewById(xfadeImages[image]);
thisImage.setVisibility(4);
}
// Fadeout
ImageView lastImage = (ImageView) activity
.findViewById(xfadeImages[xfadeImages.length - 1]);
lastImage.startAnimation(fadeOut);
// LastImage is faded to alpha 0 so it doesn't have to be hidden
// anymore
xfadeCounter = 1;
}
}
}
This allows you to modify views and have your handler set to static.
package com.testing.test;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
public class MainActivity extends Activity implements Runnable {
private static final int THREAD_RESULT = 1000;
private TextView mTextView;
private static Handler mHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (TextView) findViewById(R.id.text);
}
#Override
protected void onResume() {
super.onResume();
mHandler = new CustomHandler(this);
new Thread(this).start();
}
#Override
public void run() {
// Do some threaded work
// Tell the handler the thread is finished
mHandler.post(new Runnable() {
#Override
public void run() {
mHandler.sendEmptyMessage(THREAD_RESULT);
}
});
}
private class CustomHandler extends Handler {
private MainActivity activity;
public CustomHandler(MainActivity activity) {
super();
this.activity = activity;
}
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case THREAD_RESULT:
activity.mTextView.setText("Success!");
break;
}
}
}
}