Architecture technique d'un carrousel publicitaire
La mise en place d'un composant publicitaire dynamique sur Android repose sur trois piliers : un ViewPager pour l'affichage des images, des indicateurs de position pour l'utilisateur et un mécanisme de défilement automatique. Cette approche utilise un adaptateur personnalisé et des handlers pour l'animation.
Configuration des ressources graphiques
Préparez quatre images pour le contenu et deux images de points pour les indicateurs (active et inactive). Créez un sélecteur d'état dans res/drawable/dot_state.xml :
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/dot_blue"/>
<item android:drawable="@drawable/dot_white"/>
</selector>
Conception de l'interface utilisateur
Utilisez un ConstraintLayout pour organiser le ViewPager et la barre d'indicateurs. La structure XML définit la position et le comportement des éléments :
<ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ViewPager
android:id="@+id/banner_pager"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<LinearLayout
android:id="@+id/dot_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="24dp">
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:background="@drawable/dot_state"
android:layout_marginEnd="8dp"/>
<!-- Répéter pour chaque image -->
</LinearLayout>
</ConstraintLayout>
Adaptateur pour le ViewPager
Implémentez un PagerAdapter personnalisé pour gérer la création et la suppression des vues d'images. L'adaptateur maintient une liste de vues et les lie au conteneur :
public class BannerAdapter extends PagerAdapter {
private final List<ImageView> pageViews;
public BannerAdapter(List<ImageView> views) {
this.pageViews = views;
}
@Override
public int getCount() {
return pageViews.size();
}
@Override
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
return view == object;
}
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position) {
ImageView view = pageViews.get(position);
container.addView(view);
return view;
}
@Override
public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
container.removeView((View) object);
}
}
Logique de l'atcivité principale
L'activité orchestre le défilement automatique et la synchronisation des indicateurs. Elle utilise un Handler pour exécuter périodiquement le changement d'image :
public class BannerActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener {
private ViewPager pagerView;
private ImageView[] indicatorDots;
private int activeIndex = 0;
private boolean forwardDirection = true;
private final Handler schedulerHandler = new Handler();
private final Runnable autoScrollTask = new Runnable() {
@Override
public void run() {
int nextIndex = calculateNextIndex();
pagerView.setCurrentItem(nextIndex, true);
schedulerHandler.postDelayed(this, 3000);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_banner);
setupBanner();
startAutoScroll();
}
private void setupBanner() {
pagerView = findViewById(R.id.banner_pager);
int[] drawableIds = {R.drawable.banner1, R.drawable.banner2, R.drawable.banner3, R.drawable.banner4};
List<ImageView> views = new ArrayList<>();
for (int resId : drawableIds) {
ImageView img = new ImageView(this);
img.setImageResource(resId);
img.setScaleType(ImageView.ScaleType.CENTER_CROP);
views.add(img);
}
BannerAdapter adapter = new BannerAdapter(views);
pagerView.setAdapter(adapter);
pagerView.addOnPageChangeListener(this);
initIndicators(drawableIds.length);
}
private void initIndicators(int count) {
LinearLayout container = findViewById(R.id.dot_container);
indicatorDots = new ImageView[count];
for (int i = 0; i < count; i++) {
ImageView dot = new ImageView(this);
dot.setBackgroundResource(R.drawable.dot_state);
dot.setTag(i);
dot.setOnClickListener(v -> {
int pos = (int) v.getTag();
pagerView.setCurrentItem(pos, true);
});
indicatorDots[i] = dot;
container.addView(dot);
}
updateIndicatorState(0);
}
private void updateIndicatorState(int selected) {
for (int i = 0; i < indicatorDots.length; i++) {
indicatorDots[i].setSelected(i == selected);
}
activeIndex = selected;
}
private int calculateNextIndex() {
if (activeIndex == indicatorDots.length - 1) {
forwardDirection = false;
} else if (activeIndex == 0) {
forwardDirection = true;
}
return forwardDirection ? activeIndex + 1 : activeIndex - 1;
}
private void startAutoScroll() {
schedulerHandler.postDelayed(autoScrollTask, 3000);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}
@Override
public void onPageSelected(int position) {
updateIndicatorState(position);
}
@Override
public void onPageScrollStateChanged(int state) {
if (state == ViewPager.SCROLL_STATE_IDLE) {
schedulerHandler.postDelayed(autoScrollTask, 3000);
} else {
schedulerHandler.removeCallbacks(autoScrollTask);
}
}
}
Cette implémentation fournit un carrousel publicitaire avec navigation manuelle et défilement cyclique. Les indicateurs se mettent à jour en temps réel pour refléter la position courante.