Probably many of you (as me), have problem with creating ViewPager with bottom dots, like this:
How do you create such an Android ViewPager?
All we need are: ViewPager, TabLayout and 2 drawables for selected and default dots.
Firstly, we have to add TabLayout to our screen layout, and connect it with ViewPager. We can do this in two ways:
Nested TabLayout in ViewPager
<androidx.viewpager.widget.ViewPager
android:id="#+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.viewpager.widget.ViewPager>
In this case TabLayout will be automatically connected with ViewPager, but TabLayout will be next to ViewPager, not over it.
Separate TabLayout
<androidx.viewpager.widget.ViewPager
android:id="#+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
In this case, we can put TabLayout anywhere, but we have to connect TabLayout with ViewPager programmatically
ViewPager pager = (ViewPager) view.findViewById(R.id.photos_viewpager);
PagerAdapter adapter = new PhotosAdapter(getChildFragmentManager(), photosUrl);
pager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(pager, true);
Once we created our layout, we have to prepare our dots. So we create three files: selected_dot.xml, default_dot.xml and tab_selector.xml.
selected_dot.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="#color/colorAccent"/>
</shape>
</item>
</layer-list>
default_dot.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="#android:color/darker_gray"/>
</shape>
</item>
</layer-list>
tab_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/selected_dot"
android:state_selected="true"/>
<item android:drawable="#drawable/default_dot"/>
</selector>
Now we need to add only 3 lines of code to TabLayout in our XML layout.
app:tabBackground="#drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
First Create a layout, in that give one LinerLayout for Dots which show over your View Pager
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="#+id/pager_dots"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:background="#android:color/transparent"
android:gravity="center_horizontal"
android:orientation="horizontal">
</LinearLayout>
</RelativeLayout>
After that create 2 drawables
1. Unselected Drawable
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#android:color/transparent"/>
<size android:width="12dp" android:height="12dp"/>
<stroke android:width="1dp" android:color="#ffffff"/>
</shape>
2. Selected Drawable
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#android:color/transparent"/>
<size android:width="12dp" android:height="12dp"/>
<stroke android:width="1dp" android:color="#000000"/>
</shape>
After that set adapter
private LinearLayout llPagerDots;
private ViewPager viewPager;
private ArrayList<String> eventImagesUrl;
private HomeViewPagerAdapter homeViewPagerAdapter;
private ImageView[] ivArrayDotsPager;
public void setUpViewPager() {
viewPager = (ViewPager) findViewById(R.id.view_pager);
llPagerDots = (LinearLayout) findViewById(R.id.pager_dots);
homeViewPagerAdapter = new HomeViewPagerAdapter(mContext, eventImagesUrl);
viewPager.setAdapter(homeViewPagerAdapter);
setupPagerIndidcatorDots();
ivArrayDotsPager[0].setImageResource(R.drawable.page_indicator_selected);
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 < ivArrayDotsPager.length; i++) {
ivArrayDotsPager[i].setImageResource(R.drawable.page_indicator_unselected);
}
ivArrayDotsPager[position].setImageResource(R.drawable.page_indicator_selected);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
Create a method setupPagerIndidcatorDots() :
private void setupPagerIndidcatorDots() {
ivArrayDotsPager = new ImageView[eventImagesUrl.size()];
for (int i = 0; i < ivArrayDotsPager.length; i++) {
ivArrayDotsPager[i] = new ImageView(getActivity());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(5, 0, 5, 0);
ivArrayDotsPager[i].setLayoutParams(params);
ivArrayDotsPager[i].setImageResource(R.drawable.page_indicator_unselected);
//ivArrayDotsPager[i].setAlpha(0.4f);
ivArrayDotsPager[i].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
view.setAlpha(1);
}
});
llPagerDots.addView(ivArrayDotsPager[i]);
llPagerDots.bringToFront();
}
You can check out my library to handle your request : https://github.com/tommybuonomo/dotsindicator
In your XML layout
<com.tbuonomo.viewpagerdotsindicator.DotsIndicator
android:id="#+id/dots_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
app:dotsColor="#color/colorPrimary"
app:dotsSize="16dp"
app:dotsWidthFactor="3"
/>
In your Java code
dotsIndicator = (DotsIndicator) findViewById(R.id.dots_indicator);
viewPager = (ViewPager) findViewById(R.id.view_pager);
adapter = new ViewPagerAdapter();
viewPager.setAdapter(adapter);
dotsIndicator.setViewPager(viewPager);
When you want something similar to this with the latest ViewPager2 and Kotlin
Everything is self-explaining, no need to explain!
1. Your Activity or Fragment
val imageList = listOf(
ImageModel(R.drawable.offer1),
ImageModel(R.drawable.splash),
ImageModel(R.drawable.offer1),
ImageModel(R.drawable.splash2)
)
val adapter = HomeOffersAdapter()
adapter.setItem(imageList)
photos_viewpager.adapter = adapter
TabLayoutMediator(tab_layout, photos_viewpager) { tab, position ->
}.attach()
}
2. Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="#dimen/dp_200">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="#dimen/dp_200" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom|center"
app:tabBackground="#drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabSelectedTextColor="#android:color/transparent"
app:tabTextColor="#android:color/transparent" />
3. Drawable: tab_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/dot_selected" android:state_selected="true" />
<item android:drawable="#drawable/dot_default" />
4. Drawable: dot_selected.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thickness="#dimen/dp_8"
android:useLevel="false">
<solid android:color="#color/colorPrimary" />
<stroke
android:width="#dimen/dp_1"
android:color="#android:color/white" />
5. Drawable: dot_default.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thickness="#dimen/dp_8"
android:useLevel="false">
<solid android:color="#android:color/transparent" />
<stroke
android:width="#dimen/dp_1"
android:color="#android:color/white" />
6. Adapter
class HomeOffersAdapter : RecyclerView.Adapter<HomeOffersAdapter.HomeOffersViewHolder>() {
private var list: List<ImageModel> = listOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeOffersViewHolder {
return HomeOffersViewHolder(parent)
}
override fun onBindViewHolder(holder: HomeOffersViewHolder, position: Int) {
holder.bind(list[position])
}
fun setItem(list: List<ImageModel>) {
this.list = list
notifyDataSetChanged()
}
override fun getItemCount(): Int = list.size
class HomeOffersViewHolder constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
constructor(parent: ViewGroup) : this(
LayoutInflater.from(parent.context).inflate(
R.layout.pager_item,
parent, false
)
)
fun bind(imageModel: ImageModel) {
itemView.offerImage.setImageResource(imageModel.image)
}
}
}
7. Layout: pager_item.xml
<LinearLayout 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:fitsSystemWindows="true"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/offerImage"
android:layout_width="match_parent"
android:layout_height="#dimen/dp_200"
android:adjustViewBounds="true"
android:scaleType="fitXY"
tools:src="#drawable/offer1" />
2021, how to actually do it. ViewPager2 only.
Refer to this excellent short article, which has a couple of problems:
https://medium.com/#adrian.kuta93/android-viewpager-with-dots-indicator-a34c91e59e3a
Starting with a normal Android Studio default project as of 2021, with a reasonably new minimum (24 currently)...
General concept:
Make a standard TabLayout, but replace each "tab unit" with "a little dot" rather than the usual text.
In TabLayout, you can indeed replace each "tab unit" using "tabBackground":
app:tabBackground="#drawable/tab_selector"
So add the following to the XML of your screen, which has a ViewPager2:
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:background="#00FFFFFF"
app:tabBackground="#drawable/tab_selector"
app:tabIndicatorGravity="center"
app:tabIndicatorHeight="0dp"/>
Notice carefully we are replacing each and every one of the "tab units" in the TabLayout, with our own "tab_selector".
To be completely clear, "tabBackground" means the individual little "tab units", not the whole tab bar system.
(Aside, note that the two tricks tabIndicatorGravity and tabIndicatorHeight will indeed get rid of the "boxes" that are the usual "tab units".)
Next create three drawables in the obvious way, tab_selector and the two different dots. See the above article or 100s of examples on this page.
The magic code:
In your onCreate have the expected code ...
viewPager = findViewById(R.id.simple_slide_pager);
tab_layout = findViewById(R.id.tab_layout);
viewPager.setAdapter(new ScreenSlidePagerAdapter(this));
and then here at last is the magic code fragment to make it work. Follow the above by:
Up to date for 2021:
TabLayoutMediator tabLayoutMediator =
new TabLayoutMediator(tab_layout, viewPager, true,
new TabLayoutMediator.TabConfigurationStrategy() {
#Override public void onConfigureTab(
#NonNull TabLayout.Tab tab, int position) { }
}
);
tabLayoutMediator.attach();
It's done.
(Inside onConfigureTab you can do any sound effects or whatever the heck might be needed. For shorter syntax see the key comment by #F1iX above.)
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.viewpager.widget.ViewPager
android:id="#+id/vpImage"
android:layout_width="match_parent"
android:layout_height="#dimen/_150sdp" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tlImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="#drawable/selector_product_image"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabMaxWidth="12dp"
app:tabRippleColor="#null" />
</androidx.appcompat.widget.LinearLayoutCompat>
ImageAdapter imageAdapter = new ImageAdapter(getActivity(), arrayListSlider);
binding.vpImage.setOffscreenPageLimit(1);
binding.vpImage.setAdapter(imageAdapter);
binding.tlImage.setupWithViewPager(binding.vpImage);
selector_product_image.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/image_selected" android:state_selected="true" />
<item android:drawable="#drawable/image_unselected" />
</selector>
image_selected.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
<solid android:color="#color/colorAccent" />
</shape>
</item>
</layer-list>
image_unselected.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
<solid android:color="#color/colorPrimary" />
</shape>
</item>
</layer-list>
ImageAdapter.java
class ImageAdapter extends PagerAdapter {
private Context context;
private ArrayList<ImageModel> arrayList;
private LayoutInflater layoutInflater;
public ImageAdapter(Context context, ArrayList<ImageModel> arrayList) {
this.context = context;
this.arrayList = arrayList;
this.layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public boolean isViewFromObject(#NonNull View view, #NonNull Object o) {
return view == ((View) o);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view = layoutInflater.inflate(R.layout.row_slider_image, container, false);
AppCompatImageView ivProductImage = view.findViewById(R.id.ivProductImage);
if (!TextUtils.isEmpty(arrayList.get(position).getImage())) {
Glide.with(context)
.load(arrayList.get(position).getImage())
.apply(new RequestOptions().placeholder(R.drawable.no_image).error(R.drawable.no_image))
.into(ivProductImage);
}
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
row_slider_image.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/ivProductImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="#drawable/no_image" />
</androidx.appcompat.widget.LinearLayoutCompat>
For Viewpager2, follow the same steps which suggested by #RediOne1 and in the activity or fragment use below code to attach tablayout with viwpager2
val tabLayoutMediator = TabLayoutMediator(binding.tabLayout,binding.offersVp) { _, _ -> }
tabLayoutMediator.attach()
Your xml
<RelativeLayout
android:id="#+id/rl_speed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/ll_dashboard_buttons"
android:layout_below="#+id/ib_menu">
<com.smart.gps.speedometer.app.utils.SmartViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</com.smart.gps.speedometer.app.utils.SmartViewPager>
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="#drawable/tab_selector"
app:tabIndicatorHeight="0dp"
app:tabGravity="center"
/>
create a drawable. right click on drawable -> new -> Drawable file resource
name that file
tab_selector.xml
<item android:drawable="#drawable/selected_tab"
android:state_selected="true"/>
<item android:drawable="#drawable/unselected_tab"/>
Now there is two more xml files. create two more xml files with respected name. these are the selecter indicator and unselected indicator
selected_tab.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
<solid android:color="#color/highspeed"/>
</shape>
</item>
</layer-list>
unselected_tab.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="2dp"
android:useLevel="false">
<solid android:color="#android:color/darker_gray"/>
</shape>
</item>
</layer-list>
Place ViewFlipper and viewFlipper_linear_dot_lay(Linearlayout) on samebaseline and follow the below one
viewFlipper_linear_dot_lay= (LinearLayout) findViewById(R.id.dots_lay);
setupDotsOnViewPager(images_viewFlipper);
for (int i = 0; i < images_viewFlipper.size(); i++) {
//Add Images to ViewFlipper
}
private void setupDotsOnViewPager(ArrayList images_viewFlipper) {
images_linear = new ImageView[images_viewFlipper.size()];
for (int i = 0; i < images_linear.length; i++) {
images_linear[i] = new ImageView(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(5, 0, 5, 0);
params.gravity = Gravity.BOTTOM | Gravity.CENTER;
images_linear[i].setLayoutParams(params);
images_linear[i].setImageResource(R.drawable.unselected);
viewFlipper_linear_dot_lay.addView(images_linear[i]);
viewFlipper_linear_dot_lay.bringToFront();
}
}
And OnRight & OnLeft getsures place the below code
for (int i = 0; i < images_linear.length; i++) {
images_linear[i].setImageResource(R.drawable.unselected);
}
images_linear[viewFlipper.getDisplayedChild()].setImageResource(R.drawable.selected);
Add dependencies > Sync the Gradle
implementation 'com.tbuonomo.andrui:viewpagerdotsindicator:4.1.2'
In your java code
dotsIndicator = (DotsIndicator) findViewById(R.id.dots_indicator3);
myViewPagerAdapter = new MyViewPagerAdapter();
viewPager.setAdapter(myViewPagerAdapter);
viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
dotsIndicator.setViewPager(viewPager);
In your layout
<com.tbuonomo.viewpagerdotsindicator.SpringDotsIndicator
android:id="#+id/spring_dots_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:dampingRatio="0.5"
app:dotsColor="#color/material_white"
app:dotsStrokeColor="#color/material_yellow"
app:dotsCornerRadius="2dp"
app:dotsSize="16dp"
app:dotsSpacing="6dp"
app:dotsStrokeWidth="2dp"
app:stiffness="300"
/>
Related
Applying the solution of this link
Android ViewPager with bottom dots
I found that in androidx, with implementation "com.google.android.material:material:1.0.0"
I cannot adjust the width of the dots and I cannot adjust the margin between the dots.
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- activity_screen_slide.xml -->
<androidx.viewpager.widget.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/viewPagerDots"
app:tabIndicatorFullWidth="false"
app:tabPaddingStart="16dp"
app:tabPaddingEnd="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:tabBackground="#drawable/tab_dot_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp" />
</RelativeLayout>
drawable/viewpager_dot_indicator_default.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval"
>
<solid
android:color="#color/colorPrimary" />
</shape>
drawable/viewpager_dot_indicator_selected.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<size android:height="160dp"
android:width="160dp"/>
<solid
android:color="#color/red" />
</shape>
This is what i want
this is what i have
If you want dots in for your viewpager I suggest you to use this code.
It will give you perfect dots as you choose.
First create a linear layout for the dots and set its orientation to horizontal.
Then in your Java file declare the array of textview
TextView[] setDots;
Now add the following code snippet.
private void addDots(int position){
setDots = new TextView[3]; // No. of dots. Here you'll get three dots.
dots.removeAllViews();
for (int i = 0; i<setDots.length; i++){
setDots[i] = new TextView(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setDots[i].setText(HtmlCompat.fromHtml("•", HtmlCompat.FROM_HTML_MODE_LEGACY));
}
setDots[i].setTextSize(35); //Dots size.
dots.addView(setDots[i]);
}
if (setDots.length > 0){
setDots[position].setTextColor(getResources().getColor(R.color.colorPrimaryDark, getTheme())); //Change the color as your need.
}
}
Then inside the ViewPager.OnPageChangedListener add the dots.
#Override
public void onPageSelected(int position) {
addDots(position);
}
I have a viewPager with tabLayout like this:
I need to animate dots when sliding pages with zoom in animation (scale selected dot to her original size).
I have TabLayout element with app:tabBackground drawable xml file:
<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="#+id/on"
android:drawable="#drawable/selected_dot"
android:state_selected="true" />
<item
android:id="#+id/off"
android:drawable="#drawable/default_dot" />
<transition
android:fromId="#id/off"
android:toId="#+id/on">
<animation-list>
<!-- here I stuck -->
</animation-list>
</transition>
</animated-selector>
And tabLayout is connected with viewPager in this way:
tabLayout.setupWithViewPager(viewPager);
The dot is just a shape element, so selected_dot.xml looks like this:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="#FFFFFF"/>
</shape>
</item>
I think that I need animation resource file this to create zoom-in and zoom-out animation, so I created scale.xml file as anim resource
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true" >
<scale
xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXScale="0.5"
android:fromYScale="0.5"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" >
</scale>
</set>
But how I can apply it to the dots? I thought that I can add animation inside transition tag in tabLayout drawable, but no success. Also I tried to do it programmatically in viewPager's onPageChangeListener, but I don't know how to represent shape (selected dot) as a view to start animation. I tried tabLayout.getTabAt(position).getCustomView().startAnimation(...); but getCustomView() returns null.
Thanks for any help and sorry for my English!
Thanks for your answers, I finally found a solution which may be not so perfect but fully working. Now all dots have same xml layout (selected_dot.xml) and I adjust dot's size by scaling it
tabLayout = findViewById(R.id.tab_layout) as TabLayout
tabLayout.setupWithViewPager(viewPager)
val vg = tabLayout.getChildAt(0) as ViewGroup
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab) {
val a = vg.getChildAt(tab.position)
a.animate()
.scaleX(1f)
.scaleY(1f)
.setInterpolator(FastOutSlowInInterpolator())
.setDuration(resources.getInteger(android.R.integer.config_mediumAnimTime).toLong())
.start()
}
override fun onTabUnselected(tab: TabLayout.Tab) {
val a = vg.getChildAt(tab.position)
a.animate()
.scaleX(0.5f)
.scaleY(0.5f)
.setInterpolator(FastOutSlowInInterpolator())
.setDuration(1) // See explanation below
.start()
}
override fun onTabReselected(tab: TabLayout.Tab) {
}
})
I don't need animation on unselecting so I make animation with duration 1ms. I don't know why, but simple
a.clearAnimation()
a.scaleX = 0.5f
a.scaleY = 0.5f
gives me bugs. So I choose 1ms animation.
And because of all dots use selected_dot.xml layout, I need to scale down dots on 2, 3 and 4 positions when user is launching activity
private fun initializeDots() {
val vg = tabLayout.getChildAt(0) as ViewGroup
for (i in 0 until vg.childCount) {
if (i == tabLayout.selectedTabPosition) {
continue
}
val a = vg.getChildAt(i)
a.scaleX = 0.5f
a.scaleY = 0.5f
}
Probably I should call it inside onCreate method, but vg.childCount returns me 0. Because of that I call this function in onResume.
It works perfect now.
Look what i would suggest is that you make different images of every instance of the bigger(selected) dot with other smaller (dis-selected) dots and Use ImageView to set these images...
Now change the images accordingly with every change of ViewPager...
Hope it helps...
you can try this
1. add a linear layout below your view pager like this
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="wrap_content"
android:layout_marginTop="160dp"
android:layout_marginBottom="190dp"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center">
</android.support.v4.view.ViewPager>
<LinearLayout
android:id="#+id/viewPagerCountDots"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_gravity="bottom|center"
android:layout_marginTop="-20dp"
android:gravity="center"
android:orientation="horizontal" />
2. crate two image thumb for selected and unselected like this
nonselected_thumb
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" android:useLevel="true"
android:dither="true">
<size android:height="6dip" android:width="6dip"/>
<solid android:color="#color/colorPrimaryDark"/>
</shape>
selected thumb
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval" android:useLevel="true"
android:dither="true">
<size android:height="12dip" android:width="12dip"/>
<solid android:color="#color/colorPrimary"/>
</shape>
now in your java file add this code
declare your variables like this
private LinearLayout pager_indicator;
private int dotsCount;
private ImageView[] dots;
add this code in your onCreate() method
setIndicator();
viewPager = (ViewPager) findViewById(R.id.view_pager);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
for (int i = 0; i < dotsCount; i++) {
dots[i].setImageDrawable(getResources().getDrawable(R.drawable.nonselected_item));
}
dots[position].setImageDrawable(getResources().getDrawable(R.drawable.selected_item));
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
now create the setIndicator() method like this
private void setIndicator() {
pager_indicator = (LinearLayout) findViewById(R.id.viewPagerCountDots);
dotsCount = adapter.getCount();
dots = new ImageView[dotsCount];
for (int i = 0; i < dotsCount; i++) {
dots[i] = new ImageView(this);
dots[i].setImageDrawable(getResources().getDrawable(R.drawable.nonselected_item));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins(4, 0, 4, 0);
pager_indicator.addView(dots[i], params);
}
dots[0].setImageDrawable(getResources().getDrawable(R.drawable.selected_item));
}
ask me in case of any query
I want to create a drawable like this for my progress bar
and I've tried this code, but I didnt get what I want
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/progress">
<shape
android:innerRadiusRatio="3"
android:shape="ring"
android:useLevel="false">
<gradient
android:centerColor="#ffff00"
android:endColor="#00ff00"
android:startColor="#fb0000"
android:type="sweep" />
</shape>
</item>
</layer-list>
This is what I've got
Is it possible to do this with only xml?
Or this is should be done with java code?
Since you asked in comments how do you do that and I can't put these links in a comment, I'll suggest you these three links. Read them and extract what you want:
how to draw a half circle in android
Draw a semicircle in the background of a View
https://github.com/devadvance/circularseekbar
Here's the solution for your question.
DifferentColorCircularBorder.java
public class DifferentColorCircularBorder {
private RelativeLayout parentLayout;
public DifferentColorCircularBorder(RelativeLayout parentLayout) {
this.parentLayout = parentLayout;
}
public void addBorderPortion(Context context, int color, int startDegree, int endDegree) {
ProgressBar portion = getBorderPortion(context, color, startDegree, endDegree);
parentLayout.addView(portion);
}
private ProgressBar getBorderPortion(Context context, int color, int startDegree, int endDegree) {
LayoutInflater inflater = LayoutInflater.from(context);
ProgressBar portion = (ProgressBar) inflater.inflate(R.layout.border_portion, parentLayout, false);
portion.setRotation(startDegree);
portion.setProgress(endDegree - startDegree);
portion.getProgressDrawable().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) portion.getLayoutParams();
params.addRule(RelativeLayout.CENTER_IN_PARENT);
portion.setLayoutParams(params);
return portion;
}
}
border_portion.xml
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="220dp"
android:layout_height="220dp"
android:progressDrawable="#drawable/circle_exterior"
android:layout_centerInParent="true"
android:max="360"/>
circle_exterior.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadius="100dp"
android:thickness="10dp" >
<solid android:color="#ff111111" />
</shape>
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout interiorLayout = (RelativeLayout) findViewById(R.id.interior);
DifferentColorCircularBorder border = new DifferentColorCircularBorder(interiorLayout);
border.addBorderPortion(getApplicationContext(), ContextCompat.getColor(com.diffcolorborder.MainActivity.this, R.color.colorGoogleBlue), 0, 50);
border.addBorderPortion(getApplicationContext(), ContextCompat.getColor(com.diffcolorborder.MainActivity.this, R.color.colorGoogleGreen), 50, 120);
border.addBorderPortion(getApplicationContext(), ContextCompat.getColor(com.diffcolorborder.MainActivity.this, R.color.colorGoogleYellow), 120, 220);
border.addBorderPortion(getApplicationContext(), ContextCompat.getColor(com.diffcolorborder.MainActivity.this, R.color.colorGoogleRed), 220, 360);
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#2d2d2d">
<RelativeLayout
android:id="#+id/interior"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:background="#drawable/profilepic" />
</RelativeLayout>
</RelativeLayout>
Probably many of you (as me), have problem with creating ViewPager with bottom dots, like this:
How do you create such an Android ViewPager?
All we need are: ViewPager, TabLayout and 2 drawables for selected and default dots.
Firstly, we have to add TabLayout to our screen layout, and connect it with ViewPager. We can do this in two ways:
Nested TabLayout in ViewPager
<androidx.viewpager.widget.ViewPager
android:id="#+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.viewpager.widget.ViewPager>
In this case TabLayout will be automatically connected with ViewPager, but TabLayout will be next to ViewPager, not over it.
Separate TabLayout
<androidx.viewpager.widget.ViewPager
android:id="#+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
In this case, we can put TabLayout anywhere, but we have to connect TabLayout with ViewPager programmatically
ViewPager pager = (ViewPager) view.findViewById(R.id.photos_viewpager);
PagerAdapter adapter = new PhotosAdapter(getChildFragmentManager(), photosUrl);
pager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(pager, true);
Once we created our layout, we have to prepare our dots. So we create three files: selected_dot.xml, default_dot.xml and tab_selector.xml.
selected_dot.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="#color/colorAccent"/>
</shape>
</item>
</layer-list>
default_dot.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="#android:color/darker_gray"/>
</shape>
</item>
</layer-list>
tab_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/selected_dot"
android:state_selected="true"/>
<item android:drawable="#drawable/default_dot"/>
</selector>
Now we need to add only 3 lines of code to TabLayout in our XML layout.
app:tabBackground="#drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
First Create a layout, in that give one LinerLayout for Dots which show over your View Pager
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v4.view.ViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="#+id/pager_dots"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:background="#android:color/transparent"
android:gravity="center_horizontal"
android:orientation="horizontal">
</LinearLayout>
</RelativeLayout>
After that create 2 drawables
1. Unselected Drawable
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#android:color/transparent"/>
<size android:width="12dp" android:height="12dp"/>
<stroke android:width="1dp" android:color="#ffffff"/>
</shape>
2. Selected Drawable
<?xml version="1.0" encoding="utf-8"?>
<shape android:shape="oval" xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#android:color/transparent"/>
<size android:width="12dp" android:height="12dp"/>
<stroke android:width="1dp" android:color="#000000"/>
</shape>
After that set adapter
private LinearLayout llPagerDots;
private ViewPager viewPager;
private ArrayList<String> eventImagesUrl;
private HomeViewPagerAdapter homeViewPagerAdapter;
private ImageView[] ivArrayDotsPager;
public void setUpViewPager() {
viewPager = (ViewPager) findViewById(R.id.view_pager);
llPagerDots = (LinearLayout) findViewById(R.id.pager_dots);
homeViewPagerAdapter = new HomeViewPagerAdapter(mContext, eventImagesUrl);
viewPager.setAdapter(homeViewPagerAdapter);
setupPagerIndidcatorDots();
ivArrayDotsPager[0].setImageResource(R.drawable.page_indicator_selected);
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 < ivArrayDotsPager.length; i++) {
ivArrayDotsPager[i].setImageResource(R.drawable.page_indicator_unselected);
}
ivArrayDotsPager[position].setImageResource(R.drawable.page_indicator_selected);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
Create a method setupPagerIndidcatorDots() :
private void setupPagerIndidcatorDots() {
ivArrayDotsPager = new ImageView[eventImagesUrl.size()];
for (int i = 0; i < ivArrayDotsPager.length; i++) {
ivArrayDotsPager[i] = new ImageView(getActivity());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(5, 0, 5, 0);
ivArrayDotsPager[i].setLayoutParams(params);
ivArrayDotsPager[i].setImageResource(R.drawable.page_indicator_unselected);
//ivArrayDotsPager[i].setAlpha(0.4f);
ivArrayDotsPager[i].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
view.setAlpha(1);
}
});
llPagerDots.addView(ivArrayDotsPager[i]);
llPagerDots.bringToFront();
}
You can check out my library to handle your request : https://github.com/tommybuonomo/dotsindicator
In your XML layout
<com.tbuonomo.viewpagerdotsindicator.DotsIndicator
android:id="#+id/dots_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
app:dotsColor="#color/colorPrimary"
app:dotsSize="16dp"
app:dotsWidthFactor="3"
/>
In your Java code
dotsIndicator = (DotsIndicator) findViewById(R.id.dots_indicator);
viewPager = (ViewPager) findViewById(R.id.view_pager);
adapter = new ViewPagerAdapter();
viewPager.setAdapter(adapter);
dotsIndicator.setViewPager(viewPager);
When you want something similar to this with the latest ViewPager2 and Kotlin
Everything is self-explaining, no need to explain!
1. Your Activity or Fragment
val imageList = listOf(
ImageModel(R.drawable.offer1),
ImageModel(R.drawable.splash),
ImageModel(R.drawable.offer1),
ImageModel(R.drawable.splash2)
)
val adapter = HomeOffersAdapter()
adapter.setItem(imageList)
photos_viewpager.adapter = adapter
TabLayoutMediator(tab_layout, photos_viewpager) { tab, position ->
}.attach()
}
2. Layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="#dimen/dp_200">
<androidx.viewpager2.widget.ViewPager2
android:id="#+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="#dimen/dp_200" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_gravity="bottom|center"
app:tabBackground="#drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabSelectedTextColor="#android:color/transparent"
app:tabTextColor="#android:color/transparent" />
3. Drawable: tab_selector.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/dot_selected" android:state_selected="true" />
<item android:drawable="#drawable/dot_default" />
4. Drawable: dot_selected.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thickness="#dimen/dp_8"
android:useLevel="false">
<solid android:color="#color/colorPrimary" />
<stroke
android:width="#dimen/dp_1"
android:color="#android:color/white" />
5. Drawable: dot_default.xml
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:innerRadius="0dp"
android:shape="ring"
android:thickness="#dimen/dp_8"
android:useLevel="false">
<solid android:color="#android:color/transparent" />
<stroke
android:width="#dimen/dp_1"
android:color="#android:color/white" />
6. Adapter
class HomeOffersAdapter : RecyclerView.Adapter<HomeOffersAdapter.HomeOffersViewHolder>() {
private var list: List<ImageModel> = listOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeOffersViewHolder {
return HomeOffersViewHolder(parent)
}
override fun onBindViewHolder(holder: HomeOffersViewHolder, position: Int) {
holder.bind(list[position])
}
fun setItem(list: List<ImageModel>) {
this.list = list
notifyDataSetChanged()
}
override fun getItemCount(): Int = list.size
class HomeOffersViewHolder constructor(itemView: View) : RecyclerView.ViewHolder(itemView) {
constructor(parent: ViewGroup) : this(
LayoutInflater.from(parent.context).inflate(
R.layout.pager_item,
parent, false
)
)
fun bind(imageModel: ImageModel) {
itemView.offerImage.setImageResource(imageModel.image)
}
}
}
7. Layout: pager_item.xml
<LinearLayout 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:fitsSystemWindows="true"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/offerImage"
android:layout_width="match_parent"
android:layout_height="#dimen/dp_200"
android:adjustViewBounds="true"
android:scaleType="fitXY"
tools:src="#drawable/offer1" />
2021, how to actually do it. ViewPager2 only.
Refer to this excellent short article, which has a couple of problems:
https://medium.com/#adrian.kuta93/android-viewpager-with-dots-indicator-a34c91e59e3a
Starting with a normal Android Studio default project as of 2021, with a reasonably new minimum (24 currently)...
General concept:
Make a standard TabLayout, but replace each "tab unit" with "a little dot" rather than the usual text.
In TabLayout, you can indeed replace each "tab unit" using "tabBackground":
app:tabBackground="#drawable/tab_selector"
So add the following to the XML of your screen, which has a ViewPager2:
<com.google.android.material.tabs.TabLayout
android:id="#+id/tab_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:background="#00FFFFFF"
app:tabBackground="#drawable/tab_selector"
app:tabIndicatorGravity="center"
app:tabIndicatorHeight="0dp"/>
Notice carefully we are replacing each and every one of the "tab units" in the TabLayout, with our own "tab_selector".
To be completely clear, "tabBackground" means the individual little "tab units", not the whole tab bar system.
(Aside, note that the two tricks tabIndicatorGravity and tabIndicatorHeight will indeed get rid of the "boxes" that are the usual "tab units".)
Next create three drawables in the obvious way, tab_selector and the two different dots. See the above article or 100s of examples on this page.
The magic code:
In your onCreate have the expected code ...
viewPager = findViewById(R.id.simple_slide_pager);
tab_layout = findViewById(R.id.tab_layout);
viewPager.setAdapter(new ScreenSlidePagerAdapter(this));
and then here at last is the magic code fragment to make it work. Follow the above by:
Up to date for 2021:
TabLayoutMediator tabLayoutMediator =
new TabLayoutMediator(tab_layout, viewPager, true,
new TabLayoutMediator.TabConfigurationStrategy() {
#Override public void onConfigureTab(
#NonNull TabLayout.Tab tab, int position) { }
}
);
tabLayoutMediator.attach();
It's done.
(Inside onConfigureTab you can do any sound effects or whatever the heck might be needed. For shorter syntax see the key comment by #F1iX above.)
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.viewpager.widget.ViewPager
android:id="#+id/vpImage"
android:layout_width="match_parent"
android:layout_height="#dimen/_150sdp" />
<com.google.android.material.tabs.TabLayout
android:id="#+id/tlImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="#drawable/selector_product_image"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabMaxWidth="12dp"
app:tabRippleColor="#null" />
</androidx.appcompat.widget.LinearLayoutCompat>
ImageAdapter imageAdapter = new ImageAdapter(getActivity(), arrayListSlider);
binding.vpImage.setOffscreenPageLimit(1);
binding.vpImage.setAdapter(imageAdapter);
binding.tlImage.setupWithViewPager(binding.vpImage);
selector_product_image.xml
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/image_selected" android:state_selected="true" />
<item android:drawable="#drawable/image_unselected" />
</selector>
image_selected.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
<solid android:color="#color/colorAccent" />
</shape>
</item>
</layer-list>
image_unselected.xml
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
<solid android:color="#color/colorPrimary" />
</shape>
</item>
</layer-list>
ImageAdapter.java
class ImageAdapter extends PagerAdapter {
private Context context;
private ArrayList<ImageModel> arrayList;
private LayoutInflater layoutInflater;
public ImageAdapter(Context context, ArrayList<ImageModel> arrayList) {
this.context = context;
this.arrayList = arrayList;
this.layoutInflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return arrayList.size();
}
#Override
public boolean isViewFromObject(#NonNull View view, #NonNull Object o) {
return view == ((View) o);
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view = layoutInflater.inflate(R.layout.row_slider_image, container, false);
AppCompatImageView ivProductImage = view.findViewById(R.id.ivProductImage);
if (!TextUtils.isEmpty(arrayList.get(position).getImage())) {
Glide.with(context)
.load(arrayList.get(position).getImage())
.apply(new RequestOptions().placeholder(R.drawable.no_image).error(R.drawable.no_image))
.into(ivProductImage);
}
container.addView(view);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
row_slider_image.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/ivProductImage"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:src="#drawable/no_image" />
</androidx.appcompat.widget.LinearLayoutCompat>
For Viewpager2, follow the same steps which suggested by #RediOne1 and in the activity or fragment use below code to attach tablayout with viwpager2
val tabLayoutMediator = TabLayoutMediator(binding.tabLayout,binding.offersVp) { _, _ -> }
tabLayoutMediator.attach()
Your xml
<RelativeLayout
android:id="#+id/rl_speed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/ll_dashboard_buttons"
android:layout_below="#+id/ib_menu">
<com.smart.gps.speedometer.app.utils.SmartViewPager
android:id="#+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</com.smart.gps.speedometer.app.utils.SmartViewPager>
<android.support.design.widget.TabLayout
android:id="#+id/sliding_tabs"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabBackground="#drawable/tab_selector"
app:tabIndicatorHeight="0dp"
app:tabGravity="center"
/>
create a drawable. right click on drawable -> new -> Drawable file resource
name that file
tab_selector.xml
<item android:drawable="#drawable/selected_tab"
android:state_selected="true"/>
<item android:drawable="#drawable/unselected_tab"/>
Now there is two more xml files. create two more xml files with respected name. these are the selecter indicator and unselected indicator
selected_tab.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="4dp"
android:useLevel="false">
<solid android:color="#color/highspeed"/>
</shape>
</item>
</layer-list>
unselected_tab.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="2dp"
android:useLevel="false">
<solid android:color="#android:color/darker_gray"/>
</shape>
</item>
</layer-list>
Place ViewFlipper and viewFlipper_linear_dot_lay(Linearlayout) on samebaseline and follow the below one
viewFlipper_linear_dot_lay= (LinearLayout) findViewById(R.id.dots_lay);
setupDotsOnViewPager(images_viewFlipper);
for (int i = 0; i < images_viewFlipper.size(); i++) {
//Add Images to ViewFlipper
}
private void setupDotsOnViewPager(ArrayList images_viewFlipper) {
images_linear = new ImageView[images_viewFlipper.size()];
for (int i = 0; i < images_linear.length; i++) {
images_linear[i] = new ImageView(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
params.setMargins(5, 0, 5, 0);
params.gravity = Gravity.BOTTOM | Gravity.CENTER;
images_linear[i].setLayoutParams(params);
images_linear[i].setImageResource(R.drawable.unselected);
viewFlipper_linear_dot_lay.addView(images_linear[i]);
viewFlipper_linear_dot_lay.bringToFront();
}
}
And OnRight & OnLeft getsures place the below code
for (int i = 0; i < images_linear.length; i++) {
images_linear[i].setImageResource(R.drawable.unselected);
}
images_linear[viewFlipper.getDisplayedChild()].setImageResource(R.drawable.selected);
Add dependencies > Sync the Gradle
implementation 'com.tbuonomo.andrui:viewpagerdotsindicator:4.1.2'
In your java code
dotsIndicator = (DotsIndicator) findViewById(R.id.dots_indicator3);
myViewPagerAdapter = new MyViewPagerAdapter();
viewPager.setAdapter(myViewPagerAdapter);
viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
dotsIndicator.setViewPager(viewPager);
In your layout
<com.tbuonomo.viewpagerdotsindicator.SpringDotsIndicator
android:id="#+id/spring_dots_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:dampingRatio="0.5"
app:dotsColor="#color/material_white"
app:dotsStrokeColor="#color/material_yellow"
app:dotsCornerRadius="2dp"
app:dotsSize="16dp"
app:dotsSpacing="6dp"
app:dotsStrokeWidth="2dp"
app:stiffness="300"
/>
I am trying to create a rounded progressbar. This is what I want to achieve
There is a grey color background ring. On top of it, a blue color progressbar appears which moves in a circular path from 0 to 360 in 60 or whatever amount of seconds.
Here is my example code.
<ProgressBar
android:id="#+id/ProgressBar"
android:layout_width="match_parent"
android:layout_height="match_parent"
style="?android:attr/progressBarStyleLarge"
android:indeterminateDrawable="#drawable/progressBarBG"
android:progress="50"
/>
To do this, in the drawable "progressBarBG", I am creating a layerlist and inside that layer list I am giving two items as shown.
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/background">
<shape
android:shape="ring"
android:innerRadius="64dp"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="#color/grey" />
</shape>
</item>
<item android:id="#android:id/progress">
<clip>
<shape
android:shape="ring"
android:innerRadius="64dp"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="#color/blue" />
</shape>
</clip>
</item>
Now, the first grey ring is generated fine. The blue ring however starts from the left of the drawable and goes to the right just like how a linear progressbar works. This is how it shows at 50% progress with the red color arrow showing direction.
I want to move the blue progressbar in circular path as expected.
Here are my two solutions.
Short answer:
Instead of creating a layer-list, I separated it into two files. One for ProgressBar and one for its background.
This is the ProgressDrawable file (#drawable folder): circular_progress_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="270"
android:toDegrees="270">
<shape
android:innerRadiusRatio="2.5"
android:shape="ring"
android:thickness="1dp"
android:useLevel="true"><!-- this line fixes the issue for lollipop api 21 -->
<gradient
android:angle="0"
android:endColor="#007DD6"
android:startColor="#007DD6"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
And this is for its background(#drawable folder): circle_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadiusRatio="2.5"
android:thickness="1dp"
android:useLevel="false">
<solid android:color="#CCC" />
</shape>
And at the end, inside the layout that you're working:
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="200dp"
android:layout_height="200dp"
android:indeterminate="false"
android:progressDrawable="#drawable/circular_progress_bar"
android:background="#drawable/circle_shape"
style="?android:attr/progressBarStyleHorizontal"
android:max="100"
android:progress="65" />
Here's the result:
Long Answer:
Use a custom view which inherits the android.view.View
Here is the full project on github
With the Material Components Library you can use the CircularProgressIndicator:
Something like:
<com.google.android.material.progressindicator.CircularProgressIndicator
app:indicatorColor="#color/...."
app:trackColor="#color/...."
app:indicatorSize="64dp"/>
You can use these attributes:
indicatorSize: defines the radius of the circular progress indicator
trackColor: the color used for the progress track. If not defined, it will be set to the indicatorColor and apply the android:disabledAlpha from the theme.
indicatorColor: the single color used for the indicator in determinate/indeterminate mode. By default it uses theme primary color
Use progressIndicator.setProgressCompat((int) value, true); to update the value in the indicator.
Note: it requires at least the version 1.3.0-alpha04.
I have done with easy way:
Please check screen shot for the same.
CustomProgressBarActivity.java:
public class CustomProgressBarActivity extends AppCompatActivity {
private TextView txtProgress;
private ProgressBar progressBar;
private int pStatus = 0;
private Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_progressbar);
txtProgress = (TextView) findViewById(R.id.txtProgress);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
new Thread(new Runnable() {
#Override
public void run() {
while (pStatus <= 100) {
handler.post(new Runnable() {
#Override
public void run() {
progressBar.setProgress(pStatus);
txtProgress.setText(pStatus + " %");
}
});
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
pStatus++;
}
}
}).start();
}
}
activity_custom_progressbar.xml:
<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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.skholingua.android.custom_progressbar_circular.MainActivity" >
<RelativeLayout
android:layout_width="wrap_content"
android:layout_centerInParent="true"
android:layout_height="wrap_content">
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_centerInParent="true"
android:indeterminate="false"
android:max="100"
android:progress="0"
android:progressDrawable="#drawable/custom_progressbar_drawable"
android:secondaryProgress="0" />
<TextView
android:id="#+id/txtProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/progressBar"
android:layout_centerInParent="true"
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
</RelativeLayout>
custom_progressbar_drawable.xml:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="-90"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="270" >
<shape
android:shape="ring"
android:useLevel="false" >
<gradient
android:centerY="0.5"
android:endColor="#FA5858"
android:startColor="#0099CC"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
Hope this will help you.
I have written detailed example on circular progress bar in android here on my blog demonuts.com. You can also fond full source code and explanation there.
Here's how I made circular progressbar with percentage inside circle in pure code without any library.
first create a drawable file called circular.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#android:id/secondaryProgress">
<shape
android:innerRadiusRatio="6"
android:shape="ring"
android:thicknessRatio="20.0"
android:useLevel="true">
<gradient
android:centerColor="#999999"
android:endColor="#999999"
android:startColor="#999999"
android:type="sweep" />
</shape>
</item>
<item android:id="#android:id/progress">
<rotate
android:fromDegrees="270"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="270">
<shape
android:innerRadiusRatio="6"
android:shape="ring"
android:thicknessRatio="20.0"
android:useLevel="true">
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
<gradient
android:centerColor="#00FF00"
android:endColor="#00FF00"
android:startColor="#00FF00"
android:type="sweep" />
</shape>
</rotate>
</item>
</layer-list>
Now in your activity_main.xml add following:
<?xml version="1.0" encoding="utf-8"?>
<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:background="#color/dialog"
tools:context="com.example.parsaniahardik.progressanimation.MainActivity">
<ProgressBar
android:id="#+id/circularProgressbar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="250dp"
android:layout_height="250dp"
android:indeterminate="false"
android:max="100"
android:progress="50"
android:layout_centerInParent="true"
android:progressDrawable="#drawable/circular"
android:secondaryProgress="100"
/>
<ImageView
android:layout_width="90dp"
android:layout_height="90dp"
android:background="#drawable/whitecircle"
android:layout_centerInParent="true"/>
<TextView
android:id="#+id/tv"
android:layout_width="250dp"
android:layout_height="250dp"
android:gravity="center"
android:text="25%"
android:layout_centerInParent="true"
android:textColor="#color/colorPrimaryDark"
android:textSize="20sp" />
</RelativeLayout>
In activity_main.xml I have used one circular image with white background to show white background around percentage. Here is the image:
You can change color of this image to set custom color around percentage text.
Now finally add following code to MainActivity.java :
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.animation.DecelerateInterpolator;
import android.widget.ProgressBar;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
int pStatus = 0;
private Handler handler = new Handler();
TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Resources res = getResources();
Drawable drawable = res.getDrawable(R.drawable.circular);
final ProgressBar mProgress = (ProgressBar) findViewById(R.id.circularProgressbar);
mProgress.setProgress(0); // Main Progress
mProgress.setSecondaryProgress(100); // Secondary Progress
mProgress.setMax(100); // Maximum Progress
mProgress.setProgressDrawable(drawable);
/* ObjectAnimator animation = ObjectAnimator.ofInt(mProgress, "progress", 0, 100);
animation.setDuration(50000);
animation.setInterpolator(new DecelerateInterpolator());
animation.start();*/
tv = (TextView) findViewById(R.id.tv);
new Thread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
while (pStatus < 100) {
pStatus += 1;
handler.post(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
mProgress.setProgress(pStatus);
tv.setText(pStatus + "%");
}
});
try {
// Sleep for 200 milliseconds.
// Just to display the progress slowly
Thread.sleep(8); //thread will take approx 1.5 seconds to finish
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
If you want to make horizontal progressbar, follow this link, it has many valuable examples with source code:
http://www.skholingua.com/android-basic/user-interface/form-widgets/progressbar
I realized a Open Source library on GitHub CircularProgressBar that does exactly what you want the simplest way possible:
USAGE
To make a circular ProgressBar add CircularProgressBar in your layout XML and add CircularProgressBar library in your projector or you can also grab it via Gradle:
compile 'com.mikhaellopez:circularprogressbar:1.0.0'
XML
<com.mikhaellopez.circularprogressbar.CircularProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:background_progressbar_color="#FFCDD2"
app:background_progressbar_width="5dp"
app:progressbar_color="#F44336"
app:progressbar_width="10dp" />
You must use the following properties in your XML to change your CircularProgressBar.
Properties:
app:progress (integer) >> default 0
app:progressbar_color (color) >> default BLACK
app:background_progressbar_color (color) >> default GRAY
app:progressbar_width (dimension) >> default 7dp
app:background_progressbar_width (dimension) >> default 3dp
JAVA
CircularProgressBar circularProgressBar = (CircularProgressBar)findViewById(R.id.yourCircularProgressbar);
circularProgressBar.setColor(ContextCompat.getColor(this, R.color.progressBarColor));
circularProgressBar.setBackgroundColor(ContextCompat.getColor(this, R.color.backgroundProgressBarColor));
circularProgressBar.setProgressBarWidth(getResources().getDimension(R.dimen.progressBarWidth));
circularProgressBar.setBackgroundProgressBarWidth(getResources().getDimension(R.dimen.backgroundProgressBarWidth));
int animationDuration = 2500; // 2500ms = 2,5s
circularProgressBar.setProgressWithAnimation(65, animationDuration); // Default duration = 1500ms
Fork or Download this library here >> https://github.com/lopspower/CircularProgressBar
Here is a simple customview for display circle progress. You can modify and optimize more to suitable for your project.
class CircleProgressBar #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
private val backgroundWidth = 10f
private val progressWidth = 20f
private val backgroundPaint = Paint().apply {
color = Color.LTGRAY
style = Paint.Style.STROKE
strokeWidth = backgroundWidth
isAntiAlias = true
}
private val progressPaint = Paint().apply {
color = Color.RED
style = Paint.Style.STROKE
strokeWidth = progressWidth
isAntiAlias = true
}
var progress: Float = 0f
set(value) {
field = value
invalidate()
}
private val oval = RectF()
private var centerX: Float = 0f
private var centerY: Float = 0f
private var radius: Float = 0f
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
centerX = w.toFloat() / 2
centerY = h.toFloat() / 2
radius = w.toFloat() / 2 - progressWidth
oval.set(centerX - radius,
centerY - radius,
centerX + radius,
centerY + radius)
super.onSizeChanged(w, h, oldw, oldh)
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas?.drawCircle(centerX, centerY, radius, backgroundPaint)
canvas?.drawArc(oval, 270f, 360f * progress, false, progressPaint)
}
}
Example using
xml
<com.example.androidcircleprogressbar.CircleProgressBar
android:id="#+id/circle_progress"
android:layout_width="200dp"
android:layout_height="200dp" />
kotlin
class MainActivity : AppCompatActivity() {
val TOTAL_TIME = 10 * 1000L
override fun onCreate(savedInstanceState: Bundle?) {
...
timeOutRemoveTimer.start()
}
private var timeOutRemoveTimer = object : CountDownTimer(TOTAL_TIME, 10) {
override fun onFinish() {
circle_progress.progress = 1f
}
override fun onTick(millisUntilFinished: Long) {
circle_progress.progress = (TOTAL_TIME - millisUntilFinished).toFloat() / TOTAL_TIME
}
}
}
Result
I'm new so I can't comment but thought to share the lazy fix. I use Pedram's original approach as well, and just ran into the same Lollipop issue. But alanv over in another post had a one line fix. Its some kind of bug or oversight in API21. Literally just add android:useLevel="true" to your circle progress xml. Pedram's new approach is still the proper fix, but I just thought I share the lazy fix as well.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="#+id/progress_circular_id"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_centerInParent="true"
android:indeterminate="false"
android:progress="30"
android:progressDrawable="#drawable/circular_progress_bar"
android:background="#drawable/circle_shape"
style="?android:attr/progressBarStyleHorizontal"
android:max="100">
</ProgressBar>
<TextView
android:id="#+id/textview_progress_status_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="50%"
android:layout_centerInParent="true"
android:textStyle="bold"
android:textColor="#color/blue"
android:textSize="35dp">
</TextView>
<Button
android:id="#+id/check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="click me"
android:textColor="#color/white"
android:layout_below="#+id/progress_circular_id"
android:layout_centerHorizontal="true"
>
</Button>
</RelativeLayout>
Create a Drawable File with name circle_shape.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="ring"
android:innerRadiusRatio="2.5"
android:thickness="25dp"
android:useLevel="false">
<solid android:color="#CCC" />
</shape>
Create a file with circular_progress_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="270"
android:toDegrees="270">
<shape
android:innerRadiusRatio="2.5"
android:shape="ring"
android:thickness="25dp"
android:useLevel="true"><!-- this line fixes the issue for lollipop api 21 -->
<gradient
android:angle="0"
android:endColor="#007DD6"
android:startColor="#007DD6"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
In java File For example purpose used fragmet.
public class FragmentRegistration extends BaseFragmentHelper {
View registrationFragmentView;
ProgressBar progressBar;
Button button;
int count=0;
#Override
public void onAttachFragment(#NonNull Fragment childFragment) {
super.onAttachFragment(childFragment);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
registrationFragmentView = inflater.inflate(R.layout.new_device_registration, container, false);
progressBar=(ProgressBar)registrationFragmentView.findViewById(R.id.progress_circular_id);
button=(Button) registrationFragmentView.findViewById(R.id.check);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
count=count+10;
progressBar.setProgress(count);
}
});
return registrationFragmentView;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onDetach() {
super.onDetach();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
}
try this method to create a bitmap and set it to image view.
private void circularImageBar(ImageView iv2, int i) {
Bitmap b = Bitmap.createBitmap(300, 300,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
Paint paint = new Paint();
paint.setColor(Color.parseColor("#c4c4c4"));
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(150, 150, 140, paint);
paint.setColor(Color.parseColor("#FFDB4C"));
paint.setStrokeWidth(10);
paint.setStyle(Paint.Style.FILL);
final RectF oval = new RectF();
paint.setStyle(Paint.Style.STROKE);
oval.set(10,10,290,290);
canvas.drawArc(oval, 270, ((i*360)/100), false, paint);
paint.setStrokeWidth(0);
paint.setTextAlign(Align.CENTER);
paint.setColor(Color.parseColor("#8E8E93"));
paint.setTextSize(140);
canvas.drawText(""+i, 150, 150+(paint.getTextSize()/3), paint);
iv2.setImageBitmap(b);
}
#Pedram, your old solution works actually fine in lollipop too (and better than new one since it's usable everywhere, including in remote views) just change your circular_progress_bar.xml code to this:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="270"
android:toDegrees="270">
<shape
android:innerRadiusRatio="2.5"
android:shape="ring"
android:thickness="1dp"
android:useLevel="true"> <!-- Just add this line -->
<gradient
android:angle="0"
android:endColor="#007DD6"
android:startColor="#007DD6"
android:type="sweep"
android:useLevel="false" />
</shape>
</rotate>
https://github.com/passsy/android-HoloCircularProgressBar is one example of a library that does this. As Tenfour04 stated, it will have to be somewhat custom, in that this is not supported directly out of the box. If this library doesn't behave as you wish, you can fork it and modify the details to make it work to your liking. If you implement something that others can then reuse, you could even submit a pull request to get that merged back in!
Change
android:useLevel="false"
to
android:useLevel="true"
for second sahpe with id="#android:id/progress
hope it works
package com.example.ankitrajpoot.myapplication;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ProgressBar;
public class MainActivity extends Activity {
private ProgressBar spinner;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
spinner=(ProgressBar)findViewById(R.id.progressBar);
spinner.setVisibility(View.VISIBLE);
}
}
xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/loadingPanel"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<ProgressBar
android:id="#+id/progressBar"
android:layout_width="48dp"
style="?android:attr/progressBarStyleLarge"
android:layout_height="48dp"
android:indeterminateDrawable="#drawable/circular_progress_bar"
android:indeterminate="true" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<rotate
xmlns:android="http://schemas.android.com/apk/res/android"
android:pivotX="50%"
android:pivotY="50%"
android:fromDegrees="0"
android:toDegrees="1080">
<shape
android:shape="ring"
android:innerRadiusRatio="3"
android:thicknessRatio="8"
android:useLevel="false">
<size
android:width="56dip"
android:height="56dip" />
<gradient
android:type="sweep"
android:useLevel="false"
android:startColor="#android:color/transparent"
android:endColor="#1e9dff"
android:angle="0"
/>
</shape>
</rotate>
Good news is that now material design library supports determinate circular progress bars too:
<com.google.android.material.progressindicator.CircularProgressIndicator
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
For more info about this refer here.
if you want to set progress in an anti-clock direction then use below image for set fromDegree and toDegree's values in progressDrawble xml.
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="270"
android:toDegrees="-90">
<shape
android:innerRadiusRatio="2"
android:shape="ring"
android:thickness="1dp">
<gradient
android:angle="0"
android:endColor="#007DD6"
android:startColor="#007DD6"
android:type="sweep" />
</shape>
</rotate>
This code will let your progress anti-clockwise and from the top.
Change the degrees as per the above image from where you want to rotate your progress bar.
You can use this library https://github.com/xYinKio/ArcCircleProgressBar
This is one of the most flexible circular progress bars
This picture is showing the lib powers