Skip to content Skip to sidebar Skip to footer

Android: Width Of Imageview Not Changing From Seekbar Listener

I am creating a simple Android app, in which the user can drag a SeekBar to the left to reveal less of an image, and right to reveal more of an image. This is accomplished through

Solution 1:

This could be done with an additional View on top of the layout hierarchy with the same size as ImageView. We dynamically change the top View startMargin to have an image revealing/hiding effect.

import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;

import androidx.appcompat.app.AppCompatActivity;
import androidx.constraintlayout.widget.ConstraintLayout;

publicclassMainActivityextendsAppCompatActivity {

    @OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        finalImageViewimageView= findViewById(R.id.iv);
        finalViewdynamicView= ((View) findViewById(R.id.dynamicView));
        finalSeekBarseekbar= findViewById(R.id.simpleSeekBar);
        seekbar.setOnSeekBarChangeListener(newSeekBar.OnSeekBarChangeListener() {
            @OverridepublicvoidonProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                ConstraintLayout.LayoutParamsparams= (ConstraintLayout.LayoutParams) dynamicView.getLayoutParams();
                params.setMarginStart(imageView.getWidth() * progress / 100);
                dynamicView.setLayoutParams(params);
            }

            @OverridepublicvoidonStartTrackingTouch(SeekBar seekBar) {
            }

            @OverridepublicvoidonStopTrackingTouch(SeekBar seekBar) {
            }
        });
    }
}

Layout:

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns: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:background="#ffffff"android:gravity="center"android:orientation="vertical"><SeekBarandroid:id="@+id/simpleSeekBar"android:layout_width="match_parent"android:layout_height="wrap_content" /><androidx.constraintlayout.widget.ConstraintLayoutandroid:layout_height="300dp"android:layout_width="300dp"android:orientation="vertical"><ImageViewandroid:id="@+id/iv"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="matrix"android:src="@drawable/owl"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><Viewandroid:id="@+id/dynamicView"android:layout_width="0dp"android:layout_height="match_parent"android:background="@color/white"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /></androidx.constraintlayout.widget.ConstraintLayout></LinearLayout>

Code: https://github.com/dautovicharis/sos_android/tree/q_68375499

Additional:

  • Instead of px use dp in layouts
  • My suggestion is to switch to Kotlin
  • ConstraintLayout is a better option if you want to have better performance and avoid nested views

EDIT: I was not happy with the first solution and did a small research. A better way is to do it using ImageView overlay.

import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.SeekBar;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.res.ResourcesCompat;

publicclassMainActivityextendsAppCompatActivity {

    @OverrideprotectedvoidonCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        finalImageViewimageView= findViewById(R.id.iv);
        finalSeekBarseekbar= findViewById(R.id.simpleSeekBar);

        seekbar.setOnSeekBarChangeListener(newSeekBar.OnSeekBarChangeListener() {
            @OverridepublicvoidonProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                addOverlay(R.drawable.overlay, imageView, imageView.getWidth() * progress / 100);
            }

            @OverridepublicvoidonStartTrackingTouch(SeekBar seekBar) {
            }

            @OverridepublicvoidonStopTrackingTouch(SeekBar seekBar) {
            }
        });

        // Initial overlay
        imageView.post(() -> addOverlay(R.drawable.overlay, imageView, 0));
    }

    privatevoidaddOverlay(int resourceId, ImageView imageView, int startMargin) {
        imageView.getOverlay().clear();
        Drawabledrawable= ResourcesCompat.getDrawable(getResources(), resourceId, null);
        drawable.setBounds(newRect(startMargin, 0, imageView.getWidth(), imageView.getHeight()));
        imageView.getOverlay().add(drawable);
    }
}

res->drawable-overlay.xml

<?xml version="1.0" encoding="utf-8"?><layer-listxmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:drawable="@color/white" /></layer-list>

res->layout->activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffff"android:gravity="center"android:orientation="vertical"><SeekBarandroid:id="@+id/simpleSeekBar"android:layout_width="match_parent"android:layout_height="wrap_content" /><ImageViewandroid:id="@+id/iv"android:layout_width="300dp"android:layout_height="300dp"android:scaleType="matrix"android:src="@drawable/owl"
        /></LinearLayout>

Code: https://github.com/dautovicharis/sos_android/commits/q_68375499_v2

EDIT: Final solution and what Adam actually wanted to achieve is:

enter image description here

Code:https://github.com/dautovicharis/sos_android/tree/q_68375499_v3

Solution 2:

publicvoidonProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                iv.getLayoutParams().width = 300 * progress/100;
                iv.drawableStateChanged(); //<--- You need to redraw it after you change it.
                System.out.println(300 * progress/100);
            }

Solution 3:

  seekbar.setOnSeekBarChangeListener(newSeekBar.OnSeekBarChangeListener() {
            @OverridepublicvoidonProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                iv.getLayoutParams().width = 200 * progress;
                iv.getLayoutParams().height= 200 * progress;
                iv.setScaleType(ImageView.ScaleType.FIT_XY);
            }
            @OverridepublicvoidonStartTrackingTouch(SeekBar seekBar) {
                //write custom code to on start progress
            }
            @OverridepublicvoidonStopTrackingTouch(SeekBar seekBar) {
            }
        });

Post a Comment for "Android: Width Of Imageview Not Changing From Seekbar Listener"