I'm having the problem that I can not add a ViewPager (
Images Carousel) programmatically in my android app using Android Studio. So I built a simpler schema than my production app for testing, except that in this test I discovered that it only works at certain times.
Let's go to the code and explain what I wanted and what's going on.
ViewPagerAdapter.java
public class ViewPagerAdapter extends PagerAdapter{
Context context;
List<Bitmap> images;
LayoutInflater inflater;
public ViewPagerAdapter(Context context, List<Bitmap> images) {
this.context = context;
this.images = images;
}
#Override
public int getCount() {
return images.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
inflater = (LayoutInflater)context.getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.viewpager_item,container,false);
ImageView image;
image = (ImageView)itemView.findViewById(R.id.imageView);
DisplayMetrics dis = new DisplayMetrics();
image.setImageBitmap(images.get(position));
container.addView(itemView);
return itemView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View)object);
}
}
viewpager_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Linear.java
public class Linear extends AppCompatActivity {
ViewPager viewPager;
ViewPagerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.linerar_activity);
NestedScrollView scrollView = (NestedScrollView) findViewById (R.id.scrollView);
scrollView.setFillViewport (true);
ImageView imageView;
List<Bitmap> bitmapList = new ArrayList<>();
Bitmap bitmap;
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.play);
bitmapList.add(bitmap);
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.play2);
bitmapList.add(bitmap);
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.play3);
bitmapList.add(bitmap);
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.play4);
bitmapList.add(bitmap);
bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.play5);
bitmapList.add(bitmap);
LinearLayout ln = findViewById(R.id.ln);
TextView tv = new TextView(Linear.this);
tv.setText("BlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla\n" +
"BlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla\n" +
"BlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla\n" +
"BlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla\n" +
"BlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla\n" +
"BlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla\n" +
"BlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla\n" +
"BlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla");
ln.addView(tv);
viewPager = new ViewPager(Linear.this);
adapter = new ViewPagerAdapter(Linear.this,bitmapList);
viewPager.setAdapter(adapter);
imageView = new ImageView(Linear.this);
imageView.setImageResource(R.drawable.play);
imageView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
//ln.addView(imageView);
imageView = new ImageView(Linear.this);
imageView.setImageResource(R.drawable.play);
imageView.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
//ln.addView(imageView);
ln.addView(viewPager);
//ln.addView(tv);
//ln.addView(imageView);
}
}
linerar_activity.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/ln"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:ignore="MissingConstraints">
</LinearLayout>
</android.support.constraint.ConstraintLayout>
</android.support.v4.widget.NestedScrollView>
So what he really wanted to happen was:
Regardless of where it happened ln.addView (imageView) or ln.addView (tv) or ln.addView (viewPager) appeared in the order that was instantiated in LinearLayout.
What actually occurs:
The TextView and ImageView they can be instantiated as many times as they want, yet they will appear in the order in the scrollView Example:
ln.addView (imageView);
ln.addView (tv);
ln.addView (imageView);
ln.addView (tv);
the end product of this scrollView will be an image, a text, an image and finally a text.
The problem is when I give an ln.addView (viewPager) because it only appears when the scrollView content does not exceed the height of the device, Example:
1 - Only an ln.addView (viewPager): the viewPager will fill the entire screen of the mobile phone without the need to use the scrollView.
2 - Inserting some content + ln.addView (viewPager): in this example I'm using a textView that occupies 50% of the screen and the other 50% is occupied by viewPager, if the textView occupies 80% of the screen the viewPager would occupy 20 % of screen, if the screen was occupied 100% the scrollView would start working and the viewPager regardless of where it was instantiated it would not appear anymore.
Summarizing the problem:
That is, when the scrollView starts to work the viewPager will not work anymore.
Does anyone have any ideas for helping me?
Related
I am working on a simple project and in which I am using RecyclerView to show a grid of some ImageView and TextView using GridLayoutManager in my fragment. I followed some tutorials on Google and made it. But I don't know why there is automatically so much padding between vertical views as if only 2 adjacent views are only showing up. Here is a GIF of it
This is my fragment_home.xml file in which the recylerview is to be shown:
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/gridrecyle
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="220dp"
android:gravity="center"
android:numColumns="2"
android:columnWidth="180dp"/>
This is my single_item.xml file for each view:
<LinearLayout
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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imagessssss"
android:layout_width="180dp"
android:layout_margin="10dp"
android:layout_marginBottom="30dp"
android:background="#drawable/grid_image"
android:layout_height="180dp" />
<TextView
android:id="#+id/texttsss"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lines="1"
android:maxLines="1"
android:textSize="25sp" />
</LinearLayout>
This is my fragment_home java class :
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
final View vii = inflater.inflate(R.layout.fragment_home, null);
context = getActivity();
RecyclerView recyclerView = vii.findViewById(R.id.gridrecyle);
CustomRecycleAdaptor adaptor = new CustomRecycleAdaptor(context);
recyclerView.setAdapter(adaptor);
recyclerView.setLayoutManager(new GridLayoutManager(context , 2 , GridLayoutManager.VERTICAL , false ));
This is my CustomRecycleAdaptor java class for the adaptor :
public class CustomRecycleAdaptor extends RecyclerView.Adapter <CustomRecycleAdaptor.Viewholder>{
private final Context mcontext;
public CustomRecycleAdaptor(Context mcontext) {
this.mcontext = mcontext;
}
//This is a method for giving padding to imageviews with converting dp to pixels
public static float convertDpToPixel(float dp, Context context){
return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}
public Integer[] mimg = {
R.drawable.cake, R.drawable.donut, R.drawable.ice_creame, R.drawable.smoothie
};
public String[] mstrng = {
"Cakes" , "Donuts" , "Ice Creams" , "Smoothies"
};
#NonNull
#Override
public CustomRecycleAdaptor.Viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(mcontext);
View vii = layoutInflater.inflate(R.layout.single_item , parent , false);
Viewholder viewHolder = new Viewholder(vii);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull CustomRecycleAdaptor.Viewholder holder, int position) {
TextView textView = holder.texts;
ImageView imageView = holder.images;
textView.setText(mstrng[position]);
imageView.setImageResource(mimg[position]);
int imgpadding = Math.round(convertDpToPixel(10 , mcontext));
int txtpadding = Math.round(convertDpToPixel(40 , mcontext));
imageView.setPadding(imgpadding , imgpadding , imgpadding , imgpadding);
textView.setPadding(txtpadding , 0 , 0 , 0);
}
#Override
public int getItemCount() {
return mstrng.length;
}
public class Viewholder extends RecyclerView.ViewHolder {
public TextView texts;
public ImageView images;
public Viewholder(#NonNull View itemView) {
super(itemView);
texts = itemView.findViewById(R.id.texttsss);
images = itemView.findViewById(R.id.imagessssss);
}
}}
Kindly Assist me , Thanks in advance!
Update: Uploaded full single_actvity.xml
Could you please try the following code in your recyclerview XML
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
Change the height to wrap content and add the second the line. This way the recyclerview should have the height same as its content but never exceeds the guideline/contraint.
The answer is as #i_A_mok said , the linear layout's height in single_item.xml should be set to "wrap content" in order to just consider the single view not the full screen (of match_parent). Thank You!
I am facing problem while loading an Image in ViewPager. The image gets loaded with 5px gap at right and left side. Here is my code:
#Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(mContext);
imageView.setImageResource(PoemActivity.mPoems[position]);
container.addView(imageView);
return imageView;
}
Here is my xml file as asked by Hari.
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
I want to implement the following screen :
In the screen shot you can see that below MyAdvisor TextView i have an image.On swiping this image different image will be displayed .To create Swipe Gallery i am using view pager here.I am using an Adapter which is providing images to display through view pager.
Adapter:
public class ImageAdapter extends PagerAdapter {
private Context context;
private int[] images = new int[]{R.drawable.imgone,
R.drawable.img2,
R.drawable.img3};
public ImageAdapter(Context context) {
this.context = context;
}
#Override
public int getCount() {
return images.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == (ImageView) object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(context);
int padding = context.getResources().getDimensionPixelSize(R.dimen.activity_horizontal_margin);
imageView.setPadding(padding, padding, padding, padding);
imageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
imageView.setImageResource(images[position]);
((ViewPager) container).addView(imageView, 0);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((ImageView) object);
}
}
Below is the xml file of demo project of mine which contains two text view and a view pager.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello"
android:layout_above="#+id/txt"
android:layout_marginTop="15sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/txt"
android:text="Hello2"
android:layout_above="#+id/pager"
android:layout_marginTop="15sp"/>
<android.support.v4.view.ViewPager
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height = "wrap_content"
></android.support.v4.view.ViewPager>
My problem is that the view pager is having height as match_parent.Even after changing it as wrap_content ,the other views are not displayed .Please guide me how can i implement this screen.
I suggest you to use Heterogenous Layouts inside RecyclerView for that approach.If you're not familiar with the concept, go thru this tutorial.And for the viewpager part, there is this awesome library which comes up with so many built in features that you will absolutely love.Just inflate the Sliderlayout of this library inside onCreateViewHolder() of adapter and provide corresponding data.No need to write your own custom pageradapter and handle events.You just have to know how to use Recyclerview and you're pretty much done.
I'm using ViewPager. I want to put a button on each page, but in doing so fills the entire page. I would like to determine the width and height of button but do not know how.
This is my code:
Pager Activity
public class PagerActivity extends Activity {
PagerContainer mContainer;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContainer = (PagerContainer) findViewById(R.id.pager_container);
ViewPager pager = mContainer.getViewPager();
PagerAdapter adapter = new MyPagerAdapter();
pager.setAdapter(adapter);
//Necessary or the pager will only have one extra page to show
// make this at least however many pages you can see
pager.setOffscreenPageLimit(adapter.getCount());
//A little space between pages
pager.setPageMargin(15);
//If hardware acceleration is enabled, you should also remove
// clipping on the pager for its children.
pager.setClipChildren(false);
}
//Nothing special about this adapter, just throwing up colored views for demo
private class MyPagerAdapter extends PagerAdapter {
#Override
public Object instantiateItem(ViewGroup container, int position) {
TextView view = new TextView(PagerActivity.this);
view.setText("Item "+position);
view.setGravity(Gravity.CENTER);
view.setBackgroundColor(Color.argb(255, position * 50, position * 10, position * 50));
view.setTextColor(Color.parseColor("#CA2C68"));
Button buttonView = new Button(PagerActivity.this);
buttonView.setBackgroundResource(R.drawable.button_states_azul);
container.addView(buttonView);
return buttonView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
}
#Override
public int getCount() {
return 5;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="80dp"
android:background="#FF7CB8"
android:id="#+id/linear" >
<View
android:layout_width="match_parent"
android:layout_height="4dp"
android:background="#CA2C68"
android:layout_gravity="bottom"/>
</LinearLayout>
<com.example.slidee.PagerContainer
android:id="#+id/pager_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/linear"
android:layout_alignParentBottom="true"
android:layout_below="#+id/linear"
android:background="#29C5FF" >
<android.support.v4.view.ViewPager
android:layout_width="234dp"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal"
android:background="#29C5FF" />
</com.example.slidee.PagerContainer>
ViewPager expects the contained view to occupy the whole container.
Use some layout to contain a button:
LinearLayout lay = new LinearLayout(PagerActivity.this);
LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
buttonView.setLayoutParams(lp);
lay.addView(buttonView);
container.addView(lay);
an other way to do it is to make a new xml file and inflate it.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/viewpager_button"
android:background="#drawable/button_states_azul"/>
</LinearLayout>
and in instantiateItem
LayoutInflater inflater = MainActivity.this.getLayoutInflater();
View pagerView = inflater.inflate(R.layout.viewpager_layout, null);
Button button = (Button) pagerView.findViewById(R.id.viewpager_button);
container.addView(button);
You are creating the button dynamically and hence by default it does a match_parent for width and height.
Add this line:
buttonView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
This is how i do it, create a xml layout you want to inflate. Add all the view you are intending. Then inside your adapter class, inside instantiateItem override do something like this. remember to adjust your xml views to fit parents width and height as you wish.
#Override
public Object instantiateItem(ViewGroup container, final int position) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.your_view, container, false);
// get reference to your button over here if you have one
Button b = (Button) view.findViewById(R.id.enter_button);
container.addView(view);
return view;
}
I have a viewpager in my main_layout. The view pager contains only an ImageView wrapped by RelativeLayout
What i would like to do is when a user click on a button, it will add an image to that particular viewpager.
I found this answer here on stackoverflow (which i think it is relevant to my question), however i am completely lost with that code.
Dynamically Adding View to viewpager
So far this is my code:
MainActivity.Java
private PagerAdapter pAdapter;
private ViewPager photoPager;
...
pAdapter = new GalleryPagerAdapter(getApplicationContext());
photoPager.setAdapter(pAdapter);
GalleryPagerAdapter.java
public class GalleryPagerAdapter extends PagerAdapter{
private final Context context;
LayoutInflater inflater;
private final int[] GalImages = new int[] {
R.drawable.ic_launcher,
R.drawable.ic_launcher,
R.drawable.ic_launcher
};
public GalleryPagerAdapter(Context context){
this.context=context;
}
#Override
public int getCount() {
return GalImages.length;
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(context);
int padding = 10;
imageView.setPadding(padding, padding, padding, padding);
imageView.setScaleType(ImageView.ScaleType.MATRIX);
imageView.setImageResource(GalImages[position]);
container.addView(imageView, 0);
return imageView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((ImageView) object);
}
}
This is the view that i would like to add dynamically
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:padding="10dp" >
<ImageView
android:id="#+id/photo_thumb"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#000000"
android:scaleType="fitXY"
android:padding="0dp" />
</RelativeLayout>
And this is my MainActivity where my ViewPager exists
MainActivity.xml
<LinearLayout
android:id="#+id/bannerLayout"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="0.4"
android:layout_margin="0dip"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="#+id/photoPager"
android:layout_width="fill_parent"
android:layout_height="125dp"
android:background="#4F4E4F"/>
</LinearLayout>
So my question is how do i improve the code i am using so that i can dynamically add new image to my ViewPager
ps: On the reference link (which i strongly believe relevant to my question), i am completely lost on this part:
// Create an initial view to display; must be a subclass of FrameLayout.
FrameLayout v0 = (FrameLayout) inflater.inflate (R.layout.one_of_my_page_layouts, null);
pagerAdapter.addView (v0, 0);
What is inflater ?? What should i initialize it to?
I hope someone could direct me. And i am sorry if i sound like asking multiple question here.
Inflater is used to create View object out of your xml layout.
So if your lauout R.layout.one_of_my_page_layouts:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:padding="10dp" >
<ImageView
android:id="#+id/photo_thumb"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="#000000"
android:scaleType="fitXY"
android:padding="0dp" />
</RelativeLayout>
Inflater will do something like this(Just an example)
ImageView iv=new ImageView(context);
RelativeLayout rl=new RelativeLayout(context);
rl.add(iv)
return rl;
Just the minimal code but inflater will set all the layout params as well.
So instead of create a view dynamically like you are doing in instantiateItem if you have an xml you can simply inflate it and get an object of Type view.
So you can change instantiateItem to:
public Object instantiateItem(ViewGroup container, int position) {
RelativeLayout v0 = (RelativeLayout ) inflater.inflate (R.layout.one_of_my_page_layouts, null);
ImageView imageView = vo.findViewById(R.id.photo_thumb);
int padding = 10;
imageView.setPadding(padding, padding, padding, padding);
imageView.setScaleType(ImageView.ScaleType.MATRIX);
imageView.setImageResource(GalImages[position]);
container.addView(v0, 0);
return v0;
}