detect memory leak from MAT - android

I am using Memory analyzer tool to detect posssible memory leak in my application and below is the image of heap profile which is saying i have 5 object of IntroActivity below is my code for introactivity i am not able to find from where this objects are created multiple times
public class IntroActivity extends AppCompatActivity {
[![enter image description here][1]][1]
private ViewPager viewPager;
private MyViewPagerAdapter myViewPagerAdapter=new MyViewPagerAdapter();
private LinearLayout dotsLayout;
private TextView[] dots;
private int[] layouts;
private Context context;
private Button btnSkip, btnNext;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Checking for first time launch - before calling setContentView()
context=IntroActivity.this;
// 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(R.layout.intro_layout);
viewPager = (ViewPager) findViewById(R.id.view_pager);
dotsLayout = (LinearLayout) findViewById(R.id.layoutDots);
btnSkip = (Button) findViewById(R.id.btn_skip);
btnNext = (Button) findViewById(R.id.btn_next);
// layouts of all welcome sliders
// add few more layouts if you want
layouts = new int[]{
R.layout.intro_first_screen,
R.layout.intro_second_screen,
R.layout.intro_third_screen,
R.layout.intro_fourth_screen,
R.layout.intro_fifth_screen,
R.layout.intro_sixth_screen,
R.layout.intro_seventh_screen,
R.layout.intro_eighth_screen};
// adding bottom dots
addBottomDots(0);
// making notification bar transparent
changeStatusBarColor();
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(R.array.array_dot_active);
int[] colorsInactive = getResources().getIntArray(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() {
finish();
}
#Override
public void onBackPressed() {
super.onBackPressed();
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(R.string.start));
btnSkip.setVisibility(View.GONE);
} else {
// still pages are left
btnNext.setText(context.getResources().getString(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);
}
}
#Override
protected void onDestroy() {
super.onDestroy();
}
can anyone please help in find possible leak any help is appriciated

No, you did not have 5 objects of IntroActivity.
Heap profile says there are one instance of IntroActivity and 4 instances that is inner class of IntroActivity.
Inner classes are below including anonymous class.
btnNext.setOnClickListener(new View.OnClickListener() {
...
}
btnNext.setOnClickListener(new View.OnClickListener() {
...
}
ViewPager.OnPageChangeListener viewPagerPageChangeListener = new ViewPager.OnPageChangeListener() {
...
}
public class MyViewPagerAdapter extends PagerAdapter {
...
}
Use LeakCanary to detect memory leaks.
https://github.com/square/leakcanary

Related

Start activity from view pager

I am new to Android programming, I am creating Introduction slides using View Pager and custom adaptor. I have two introduction slides and I want the third slide to be 'sign up' activity itself. With my current implementation, the third slide is just the layout of the activity and not the activity itself.
Can you suggest how to do so?
Here is my WelcomeActivity.java (I want to start LoginActivity.java)
public class WelcomeActivity extends AppCompatActivity {
Button next;
ViewPager vp;
LinearLayout layoutBars;
MyViewPAdaptor vpAdaptor;
TextView dots[];
int[] layouts;
PrefManager prfManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
prfManager = new PrefManager(this);
if (!prfManager.getIsFirstTimeLaunch()) {
launchHomeScreen();
finish();
}
setContentView(R.layout.activity_welcome);
next = (Button) findViewById(R.id.btn_next);
vp = (ViewPager) findViewById(R.id.view_pager);
layoutBars = (LinearLayout) findViewById(R.id.layoutDots);
vpAdaptor = new MyViewPAdaptor();
layouts = new int[]{
R.layout.welcome_screen1,
R.layout.welcome_screen2,
R.layout.activity_login};
vp.setAdapter(vpAdaptor);
// adding bottom dots
addBottomDots(0);
// making notification bar transparent
changeStatusBarColor();
vp.addOnPageChangeListener(viewPagerPageChangeListener);
next.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-1) {
// move to next screen
vp.setCurrentItem(current);
} else {
launchLoginScreen();
}
}
});
}
private void addBottomDots(int currentPage) {
dots = new TextView[layouts.length];
int[] colorsActive = getResources().getIntArray(R.array.array_dot_active);
int[] colorsInactive = getResources().getIntArray(R.array.array_dot_inactive);
layoutBars.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]);
layoutBars.addView(dots[i]);
}
if (dots.length > 0)
dots[currentPage].setTextColor(colorsActive[currentPage]);
}
private int getItem(int i) {
return vp.getCurrentItem() + i;
}
private void launchHomeScreen() {
prfManager.setFirstTimeLaunch(false);
startActivity(new Intent(WelcomeActivity.this, MainActivity.class));
finish();
}
private void launchLoginScreen() {
prfManager.setFirstTimeLaunch(false);
startActivity(new Intent(WelcomeActivity.this, LoginActivity.class));
}
// 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
next.setText(getString(R.string.start));
} else {
// still pages are left
next.setText(getString(R.string.next));
}
}
#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 MyViewPAdaptor extends PagerAdapter {
private LayoutInflater layoutInflater;
public MyViewPAdaptor() {
}
#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);
}
}
}
viewPager.addOnPageChangeListener(new OnPageChangeListener() {
public void onPageScrollStateChanged(int state) {}
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
public void onPageSelected(int position) {
if (position == 2)
startActivity(new Intent(this, LoginActivity.class));
}
});

how can i simplify intro screen logic with mvvm

I am working on a very big project and I am told to write code in a very very efficient way. I have normally written my code but I want the intro layout also to be using mvvm. how can I do that?
my normal welcome activity is below
public class WelcomeActivity extends AppCompatActivity {
private ViewPager viewPager;
private MyViewPagerAdapter myViewPagerAdapter;
private LinearLayout dotsLayout;
private TextView[] dots;
private int[] layouts;
//private Button btnSkip, btnNext;
private LoginSession prefManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Checking for first time launch - before calling setContentView()
prefManager = new LoginSession(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(R.layout.activity_welcome);
viewPager = (ViewPager) findViewById(R.id.view_pager);
dotsLayout = (LinearLayout) findViewById(R.id.layoutDots);
/*btnSkip = (Button) findViewById(R.id.btn_skip);
btnNext = (Button) findViewById(R.id.btn_next);*/
// layouts of all welcome sliders
// add few more layouts if you want
layouts = new int[]{
R.layout.welcome_slide1,
R.layout.welcome_slide2,
R.layout.welcome_slide3
};
// 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(R.array.array_dot_active);
int[] colorsInactive = getResources().getIntArray(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(WelcomeActivity.this, MainActivity.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(R.string.start));
btnSkip.setVisibility(View.GONE);*/
} else {
// still pages are left
/*btnNext.setText(getString(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);
}
}
}
My sharedpreferences is as below
public class LoginSession {
SharedPreferences pref;
SharedPreferences.Editor editor;
Context _context;
int PRIVATE_MODE = 0;
public LoginSession(Context context) {
this._context = context;
pref = _context.getSharedPreferences(Constants.PREF_NAME, PRIVATE_MODE);
editor = pref.edit();
}
public void createLoginSession(JsonObject jsonObject)
{
editor.putBoolean(Constants.LOGGED_IN,true);
editor.putString(Constants.API_TOKEN,jsonObject.get("token_key").getAsString());
editor.putString(Constants.USERNAME,jsonObject.get("username").getAsString());
editor.putInt(Constants.ID,jsonObject.get("id").getAsInt());
editor.commit();
}
public boolean isLoggedIn() {
return pref.getBoolean(Constants.LOGGED_IN, false);
}
public Map<String, String> getLoginDetails() {
Map<String, String> logindetailsMap=new HashMap<>();
logindetailsMap.put(Constants.LOGGED_IN,pref.getString(Constants.LOGGED_IN,null));
logindetailsMap.put(Constants.USERNAME,pref.getString(Constants.USERNAME,null));
logindetailsMap.put(Constants.API_TOKEN,pref.getString(Constants.API_TOKEN,null));
logindetailsMap.put(Constants.ID, String.valueOf(pref.getInt(Constants.ID,0)));
return logindetailsMap;
}
public void setFirstTimeLaunch(boolean isFirstTime) {
editor.putBoolean(IS_FIRST_TIME_LAUNCH, isFirstTime);
editor.commit();
}
public boolean isFirstTimeLaunch() {
return pref.getBoolean(IS_FIRST_TIME_LAUNCH, true);
}
}
I have already used livedata. please help me modify this code
For starters, you should use data binding instead of "findViewById". This would be a good starting point to see how to bind your fields and buttons.
Also , please see how the code is divided into View, ViewModel and Model

Deleting Image from a ViewPager

I am using a ViewPager to show my Images.
These Images are sent as a List from One Activity to another & then I show them in the ViewPager.
But the Issue is that if I click on a Delete Button them the Image is Deleted & Removed from the List but it still show on the Next Image.
e.g. 1st Image's height is fullscreen > I delete it, viewpager moves to next Image, this image has a height of 350 then the background above & below 350 shows the old Image...
Also, I get a IndexOutOfBoundsExceptiom when I try to delete the 2nd Last Item...
Heres my Code -
public class ImageViewer extends AppCompatActivity {
public int position;
private ArrayList<String> list;
private HackyViewPager pager;
private ImagePagerAdapter ipa;
private List<PhotoView> photoViewList;
private HelperMethods helperMethods;
private static boolean sendResult = false;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.img);
sendResult = false;
helperMethods = new HelperMethods(ImageViewer.this);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().hide();
Intent i = getIntent();
position = i.getExtras().getInt("position");
list = i.getStringArrayListExtra("list");
pager = (HackyViewPager) findViewById(R.id.pager);
photoViewList = new ArrayList<PhotoView>();
for(int val = 0; val < list.size(); val++) {
PhotoView photoView = new PhotoView(this);
photoView.setZoomable(true);
Glide.with(ImageViewer.this)
.load(new File(list.get(val)))
.into(photoView);
photoViewList.add(photoView);
}
ipa = new ImagePagerAdapter(photoViewList);
pager.setAdapter(ipa);
pager.setCurrentItem(position);
FloatingActionButton dlt = (FloatingActionButton) findViewById(R.id.dlt);
dlt.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(ImageViewer.this);
builder.setMessage("Sure to Delete this Image?")
.setNegativeButton("Nope", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
getFilePos().delete();
ipa.remove(pager.getCurrentItem());
Toast.makeText(ImageViewer.this, "Image Deleted", Toast.LENGTH_SHORT)
.show();
}
});
builder.create()
.show();
}
});
}
public File getFilePos() {
return new File(list.get(pager.getCurrentItem()));
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()){
case android.R.id.home:
onBackPressed();
break;
}
return true;
}
static class ImagePagerAdapter extends PagerAdapter {
private List<PhotoView> images;
public ImagePagerAdapter(List<PhotoView> images) {
this.images = images;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
PhotoView imageView = images.get(position);
container.addView(imageView);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(images.get(position));
}
#Override
public int getCount() {
return images.size();
}
void remove(int pos) {
images.remove(pos);
notifyDataSetChanged();
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
#Override
public boolean isViewFromObject(View view, Object o) {
return view == o;
}
}
}
After deletion of image from list you must call the
notifyitemremoved();
on method remove on adapter.
This will work for you
you have to set the adapter to viewpager again, then it will refresh the content.
removeView(int pos) in my PagerAdaper
public void removeView(int index) {
imageFileNames.remove(index);
notifyDataSetChanged();
}
wherever I am removing the file I have to do like this
imagePagerAdapter.removeView(currentPosition);
viewPager.setAdapter(imagePagerAdapter);
EDIT:
This below method is effective, you can apply the below one.
public void updateView(int pos){
viewPager.setAdapter(null);
imagePagerAdapter =new ImagePagerAdapter(YOUR_CONTEXT,YOUR_CONTENT);
viewPager.setAdapter(imagePagerAdapter);
viewPager.setCurrentItem(pos);
}
replace YOUR_CONTEXT with your context and your content with your content name i.e. updated list or something.

How to avoid going to previous slide in Viewpager in android

I have implemented a ViewPager in my application which consist of two slides. I can go from first slide to second slide and reverse as well. But I have a special case here. If the user goes from First Slide to Second Slide. He should not be able to go back to the First slide. I need to disable going back to the First Slide once he enters the Second Slide.
Here is my code:
public class BotConnectionDialog extends DialogFragment {
private RelativeLayout toolbar;
private ImageView toolbarCloseButton;
private View layoutView;
private ViewPager viewPager;
private BotConnectionDialogAdapter myViewPagerAdapter;
private LinearLayout dotsLayout;
private TextView[] dots;
int width, height;
DisplayMetrics metrics;
private int[] layouts;
private final String TAG = BotConnectionDialog.class.getSimpleName();
private Button btnSkip, btnNext;
View.OnClickListener myListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
getActivity().getSupportFragmentManager().popBackStackImmediate();
}
});
}
};
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_Black_NoTitleBar_Fullscreen);
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.botconnection_layout, container, false);
Typeface typeface = Typeface.createFromAsset(getActivity().getAssets(), "fonts/corbert.otf");
toolbar = (RelativeLayout) rootView.findViewById(R.id.customAppBarLayout);
toolbar.setBackgroundColor(Color.parseColor("#00000000"));
toolbarCloseButton = (ImageView) rootView.findViewById(R.id.toolbarCloseButton);
toolbarCloseButton.setOnClickListener(myListener);
viewPager = (ViewPager) rootView.findViewById(R.id.view_pager);
dotsLayout = (LinearLayout) rootView.findViewById(R.id.layoutDots);
btnSkip = (Button) rootView.findViewById(R.id.btn_skip);
btnSkip.setTypeface(typeface);
btnNext = (Button) rootView.findViewById(R.id.btn_next);
btnNext.setTypeface(typeface);
metrics = getResources().getDisplayMetrics();
width = metrics.widthPixels;
height = metrics.heightPixels;
// layouts of all welcome sliders
// add few more layouts if you want
layouts = new int[]{
R.layout.slide1,
R.layout.slide2};
// adding bottom dots
addBottomDots(0);
myViewPagerAdapter = new BotConnectionDialogAdapter();
viewPager.setAdapter(myViewPagerAdapter);
viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
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 {
}
}
});
return rootView;
}
private void addBottomDots(int currentPage) {
dots = new TextView[layouts.length];
int[] colorsActive = getResources().getIntArray(R.array.array_dot_active);
int[] colorsInactive = getResources().getIntArray(R.array.array_dot_inactive);
dotsLayout.removeAllViews();
for (int i = 0; i < dots.length; i++) {
dots[i] = new TextView(getActivity());
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;
}
// 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(R.string.start));
btnSkip.setVisibility(View.GONE);
/**
* bluetooth connection the bot
*/
Toast.makeText(getActivity(), "Finished", Toast.LENGTH_SHORT).show();
} else {
// still pages are left
btnNext.setText(getString(R.string.next));
btnSkip.setVisibility(View.VISIBLE);
/**
* First page
*/
Toast.makeText(getActivity(), "2nd page", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
};
#NonNull
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
//dialog.getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
return dialog;
}
#Override
public void onResume() {
super.onResume();
// getDialog().getWindow().setLayout((7 * width) / 7, (4 * height) / 5);
}
public class BotConnectionDialogAdapter extends PagerAdapter {
/**
* View pager adapter
*/
private LayoutInflater layoutInflater;
public BotConnectionDialogAdapter() {
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
layoutInflater = (LayoutInflater) getActivity().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);
}
}
}
/**
* To disable and enable scrolling on ViewPager, just set shouldScroll to true or false.
*/
public class ScrollableViewPager extends ViewPager {
private boolean shouldScroll = true;
public ScrollableViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setShouldScroll(boolean shouldScroll) {
this.shouldScroll = shouldScroll;
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
return shouldScroll && super.onTouchEvent(ev);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return shouldScroll && super.onInterceptTouchEvent(ev);
}
}
Now use this ScrollableViewPager in place of the default ViewPager and in your onPageSelected() callback
check for the position. If it is the last position, call the setShouldScroll(false) method on your viewPager instance, which will make shouldScroll to false in our ScrollableViewPager class and eventually make the scrolling invalid as we have overridden onTouchEvent() and onInterceptTouchEvent() method, which checks for the value of shouldScroll.

android ViewPager starts at a wrong random location after reload

I am writing a simple view pager test app that loads a bunch of data from a website and creates pages to display them.
For the most part the displaying is pretty much all works. However, it falls apart when I load a new set of data to display. When I get a new set, it loads all the data perfectly well however, instead of starting from view 0 it starts at a random location. It could start at the end or somewhere in the middle.
I want all the data to load from page 1, like a book. If you load a new book the book should start from page 1 not a random page.
Reloading calls
I've tried using GotCampDetails() which sets the local variable in the class.
viewPager.setCurrentItem(0);
in my fragment but it doesn't work. Also called notifydatasetchanged() on my adapter, still didn't work.
What am I missing?
public class ViewPagerFragment extends Fragment implements WebReadResultsListener {
private ArrayList<HashMap<String, String>> campDetails;
CustomPagerAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.camp_viewpager, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
if (campDetails != null && ! campDetails.isEmpty()) {
ViewPager viewPager = (ViewPager) view.findViewById(R.id.viewpager);
adapter = new CustomPagerAdapter(getActivity(), campDetails, viewPager);
viewPager.setAdapter(adapter);
viewPager.setPageTransformer(true, new ZoomOutPageTransformer());
}
}
#Override
public boolean GotCampDetails(ArrayList<HashMap<String, String>> campDetails) {
this.campDetails = campDetails;
return true;
}
#Override
public boolean GotCampList(ArrayList<HashMap<String, String>> campDetails) {
return false;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getFragmentManager().putFragment(outState,"fragmentInstanceSaved",getFragmentManager().findFragmentById(R.id.content));
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Handle orientation changes here
}
}
Adapter:
public class CustomPagerAdapter extends PagerAdapter implements ColorChangeListener {
private ArrayList<HashMap<String, String>> campDetails;
private ViewGroup collection;
private Context mContext;
private boolean isRunning = false;
private ColorChangeListener colorChangeListener;
private int color= pink;
private int currentposition;
private ViewPager viewPager;
public CustomPagerAdapter(Context context, final ArrayList<HashMap<String, String>> campDetails, ViewPager viewPager) {
this.campDetails=campDetails;
this.mContext = context;
this.viewPager = viewPager;
colorChangeListener = (ColorChangeListener) mContext;
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int pos) {
currentposition = pos;
if (campDetails.get(currentposition).get("color").equals("green")) {
color = green;
} else {
color = pink;
}
ColorAppBar(color);
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
#Override
public Object instantiateItem(ViewGroup collection, final int position) {
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.child_item, collection, false);
if (campDetails.size() <= 0) {
Toast.makeText(mContext, "Error in getting camp details", Toast.LENGTH_SHORT).show();
return null;
}
if (campDetails.get(position).get("description").equals("RD") ) {
layout.setBackgroundColor(mContext.getResources().getColor(green));
} else {
layout.setBackgroundColor(mContext.getResources().getColor(pink));
}
collection.addView(layout);
this.collection = collection;
TextView eName = (TextView) layout.findViewById(R.id.en);
TextView nEName= (TextView) layout.findViewById(R.id.nen);
TextView textView6 = (TextView) layout.findViewById(R.id.textView6);
// ImageView nextImg = (ImageView) groupLayout.get(index).findViewById(R.id.nextImg);
eName.setText(campDetails.get(position).get("name"));
if (position+1 < campDetails.size()) {
nEName.setText(campDetails.get(position+1).get("name"));
textView6.setVisibility(View.VISIBLE);
} else {
nEName.setText("You are DONE!!");
textView6.setVisibility(View.INVISIBLE);
}
return layout;
}
#Override
public void destroyItem(ViewGroup collection, int position, Object view) {
collection.removeView((View) view);
}
#Override
public int getCount() {
return campDetails.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public CharSequence getPageTitle(int position) {
return campDetails.get(position).get("name");
}
#Override
public void ColorAppBar(int color) {
colorChangeListener.ColorAppBar(color);
}
}
I finally managed to get it done.
I had to delay the function call setCurrentItem by a few milliseconds. Race condition? I don't know why this is the case but now it works perfectly.
Here is what I added in case someone else may find it useful:
pager.postDelayed(new Runnable() {
#Override
public void run() {
pager.setCurrentItem(pos);
}
}, 100);
I'm having trouble following the details well enough to pinpoint the problem, but this guy seems to have accomplished what you're trying to do: dynamically add and remove view to viewpager
hope it helps

Categories

Resources