简体   繁体   English

Android:ImageView 的宽度不会从 SeekBar 侦听器改变

[英]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.我正在创建一个简单的 Android 应用程序,其中用户可以向左拖动SeekBar以显示较少的图像,向右拖动以显示更多的图像。 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.这是通过将侦听器附加到SeekBar来实现的,其中 ImageView 的宽度根据SeekBar的进度按比例更改。 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:问题是无论滑块在什么位置,ImageView 的宽度都保持不变,如下面的截图所示:

Progress = 0%:进度 = 0%:

在此处输入图片说明

Progress = 100%进度 = 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.这看起来很奇怪,考虑到在SeekBar的侦听器中,当我输出将ImageView宽度设置为的值时,该值是正确的。

Below is my code:下面是我的代码:

activity_main.xml :活动_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 :主活动.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 .这可以通过在布局层次结构顶部添加一个与ImageView大小相同的附加View来完成。 We dynamically change the top View startMargin to have an image revealing/hiding effect.我们动态更改顶部视图startMargin以具有图像显示/隐藏效果。

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代码https : //github.com/dautovicharis/sos_android/tree/q_68375499

Additional:额外的:

  • Instead of px use dp in layouts在布局中使用dp代替px
  • My suggestion is to switch to Kotlin我的建议是改用 Kotlin
  • ConstraintLayout is a better option if you want to have better performance and avoid nested views如果您想获得更好的性能并避免嵌套视图,则 ConstraintLayout 是更好的选择

EDIT: I was not happy with the first solution and did a small research.编辑:我对第一个解决方案不满意,并进行了一项小型研究。 A better way is to do it using ImageView overlay .更好的方法是使用 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 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 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代码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代码: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) {
            }
        });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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