【问题标题】:Android: Width of ImageView not changing from SeekBar listenerAndroid:ImageView 的宽度不会从 SeekBar 侦听器更改
【发布时间】:2021-07-18 15:44:29
【问题描述】:

我正在创建一个简单的 Android 应用,用户可以在其中向左拖动 SeekBar 以显示较少的图像,向右拖动以显示更多图像。这是通过将侦听器附加到SeekBar 来实现的,其中ImageView 的宽度与SeekBar 的进度成比例变化。 问题是无论滑块在什么位置,ImageView的宽度保持不变,如下截图所示:

进度 = 0%:

进度 = 100%

这似乎很奇怪,考虑到在SeekBar 的侦听器中,当我输出我将ImageView 宽度设置为的值时,该值是正确的。

下面是我的代码:

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) {
            }
        });
    }
}

注意:移动滑块时,图像不应调整大小

【问题讨论】:

  • 我为你创造了一些东西。请查看视频,让我看看它的外观 -> streamable.com/1eirol
  • @HarisDautović 这看起来很完美!如果您可以发布您的相应代码,我一定会接受您的回答并奖励赏金。
  • 好的,谢谢,我会在 github 上上传功能示例,以便您拉取代码。谢谢

标签: java android


【解决方案1】:

这可以通过在布局层次结构顶部附加一个View 来完成,其大小与ImageView 相同。我们动态更改顶部 View 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) {
            }
        });
    }
}

布局:

<?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>

代码https://github.com/dautovicharis/sos_android/tree/q_68375499

补充:

  • 在布局中使用 dp 代替 px
  • 我的建议是改用 Kotlin
  • 如果您想获得更好的性能并避免嵌套视图,ConstraintLayout 是一个更好的选择

编辑: 我对第一个解决方案不满意,并做了一个小研究。 更好的方法是使用 ImageView 叠加层

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>

代码https://github.com/dautovicharis/sos_android/commits/q_68375499_v2

编辑:最终解决方案以及 Adam 真正想要实现的是:

代码: https://github.com/dautovicharis/sos_android/tree/q_68375499_v3

【讨论】:

  • 只是出于好奇,有没有办法在不使用 ImageView 之上的单独 View 或 Overlay 的情况下解决这个问题?原因是我正在尝试使用当前图像下方的另一个图像创建图像比较应用程序,这样当您显示较少的当前图像时,会显示更多的下图。如果一个单独的 View 或 Overlay 在 ImageView 的顶部,那会同时遮挡当前和底部的图像。
  • @AdamLee 使用我提供的第二种解决方案,每个 ImageView 都可以为 ImageView 叠加层提供单独的逻辑。
  • 没错,每个 ImageView 都可以有独立的 ImageView 覆盖逻辑,但问题是我想将两个 ImageView 放在一起。 SeekBar 是针对顶部 ImageView 的,当向左或向右拖动 SeekBar 时,分别显示的 ImageView 越来越少,这是预期的。但是,由于Overlay是白色的,即使我没有在底部ImageView上放置任何Overlay逻辑,顶部ImageView的白色Overlay同时覆盖了顶部和底部图像。我的目标是这个 UI:diffchecker.com/image-diffimgur.com/a/lFOyEWc
  • 这是我所针对的 UI 的最佳示例:i.stack.imgur.com/kXvM9.jpg
  • @AdamLee 我有你需要的东西。你还需要这个吗?这是它的外观 -> streamable.com/hxycsg
【解决方案2】:
      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);
            }

【讨论】:

    【解决方案3】:
      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) {
                }
            });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-23
      • 1970-01-01
      相关资源
      最近更新 更多