简体   繁体   中英

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 attaching a listener to the SeekBar , in which the width of the ImageView is changed proportionally to the SeekBar 's progress. The problem is that no matter what position the slider is in, the width of the ImageView remains the same , as shown in the screenshots below:

Progress = 0%:

在此处输入图片说明

Progress = 100%

在此处输入图片说明

This seems strange, considering that in the SeekBar 's listener, when I output the value I am setting the ImageView width to, that value is correct.

Below is my code:

activity_main.xml :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns: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">
    <SeekBar
        android:id="@+id/simpleSeekBar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />


    <LinearLayout
        android:layout_height="300px"
        android:layout_width="300px"
        android:orientation="vertical"
        android:background="#0000FF">

        <ImageView
            android:layout_height="300px"
            android:layout_width="300px"
            android:src="@drawable/android"
            android:scaleType="matrix"
            android:id="@+id/iv"/>

    </LinearLayout>
</LinearLayout>

MainActivity.java :

package com.example.changingimageviewwidth2;

import androidx.appcompat.app.AppCompatActivity;

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

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ImageView iv = findViewById(R.id.iv);

        SeekBar seekbar = findViewById(R.id.simpleSeekBar);
        seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                iv.getLayoutParams().width = 300 * progress/100;
                System.out.println(300 * progress/100);
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                //write custom code to on start progress
            }
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });
    }
}

Note : The image is NOT supposed to be resized when the slider is moved.

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;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ImageView imageView = findViewById(R.id.iv);
        final View dynamicView = ((View) findViewById(R.id.dynamicView));
        final SeekBar seekbar = findViewById(R.id.simpleSeekBar);
        seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) dynamicView.getLayoutParams();
                params.setMarginStart(imageView.getWidth() * progress / 100);
                dynamicView.setLayoutParams(params);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });
    }
}

Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    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:background="#ffffff"
    android:gravity="center"
    android:orientation="vertical">

    <SeekBar
        android:id="@+id/simpleSeekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_height="300dp"
        android:layout_width="300dp"
        android:orientation="vertical">

        <ImageView
            android: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" />

        <View
            android: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;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        final ImageView imageView = findViewById(R.id.iv);
        final SeekBar seekbar = findViewById(R.id.simpleSeekBar);

        seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                addOverlay(R.drawable.overlay, imageView, imageView.getWidth() * progress / 100);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });

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

    private void addOverlay(int resourceId, ImageView imageView, int startMargin) {
        imageView.getOverlay().clear();
        Drawable drawable = ResourcesCompat.getDrawable(getResources(), resourceId, null);
        drawable.setBounds(new Rect(startMargin, 0, imageView.getWidth(), imageView.getHeight()));
        imageView.getOverlay().add(drawable);
    }
}

res->drawable-overlay.xml

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

res->layout->activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns: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">

    <SeekBar
        android:id="@+id/simpleSeekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <ImageView
        android: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:

在此处输入图片说明

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

      public void onProgressChanged(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);
            }
  seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                iv.getLayoutParams().width = 200 * progress;
                iv.getLayoutParams().height= 200 * progress;
                iv.setScaleType(ImageView.ScaleType.FIT_XY);
            }
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                //write custom code to on start progress
            }
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM