Вопрос

Я пытаюсь анимировать простой ImageView в своем приложении, и я хочу, чтобы он скользил из нижней части экрана и приходил в исходное положение, когда верхние 50 пикселей вида находятся вне верхней части экрана (напримерконечная позиция ImageView должна быть -50px в X).Я пытался использовать AbsoluteLayout для этого, но это фактически отсекает верхние 50 пикселей ImageView, так что верхние 50 пикселей никогда не отображаются.Мне нужно, чтобы верхние 50 пикселей ImageView были видны / визуализированы во время анимации, а затем просто немного переместились за пределы экрана.Надеюсь, я объяснил это достаточно хорошо.

Вот что я в настоящее время использую в качестве макета и анимации слайдов (в настоящее время это не отображает верхние 50 пикселей ImageView):

Планировка:

<?xml version="1.0" encoding="utf-8"?>
   <AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_height="fill_parent" 
      android:layout_width="fill_parent" 
      android:id="@+id/QuickPlayClipLayout">
      <ImageView android:id="@+id/Clip"
         android:background="@drawable/clip" 
         android:layout_width="fill_parent" 
         android:layout_height="wrap_content" 
         android:layout_y="-50dp">
      </ImageView>
   </AbsoluteLayout>

Анимация:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
   <translate android:fromYDelta="100%p" 
       android:toYDelta="0"
       android:duration="1000"/>
   <alpha android:fromAlpha="0.0" 
       android:toAlpha="1.0"
       android:duration="1000" />
</set>

Заранее благодарю.

Это было полезно?

Решение

Я нашел решение этой проблемы, которое должно быть легко реализовать.Это включает в себя изменение макета и Действие, раздувающее макет...смотрите ниже:

Активность (QuickPlay.java):

public class QuickPlay extends Activity implements AnimationListener
{
    private ImageView myImageView;
    private LinearLayout LL;

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

        myImageView = (ImageView) this.findViewById(R.id.Clip);
        LL = (LinearLayout) this.findViewById(R.id.QuickPlayClipLayout);

        //finally
        Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide_in_quickplay);
        anim.setAnimationListener(this);
        LL.startAnimation(anim);
    }
    @Override
    public void onAnimationEnd(Animation animation){}

    @Override
    public void onAnimationRepeat(Animation animation){}

    @Override
    public void onAnimationStart(Animation animation)
    {
        // This is the key...
        //set the coordinates for the bounds (left, top, right, bottom) based on the offset value (50px) in a resource XML
        LL.layout(0, -(int)this.getResources().getDimension(R.dimen.quickplay_offset), 
                LL.getWidth(), LL.getHeight() + (int)this.getResources().getDimension(R.dimen.quickplay_offset));
    }
}

Новое линейное описание (CustomLinearLayout.java):

public class CustomLinearLayout extends LinearLayout
{
    private Context myContext;

    public CustomLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        myContext = context;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec+((int)myContext.getResources().getDimension(R.dimen.quickplay_offset)));
    }
}

Расположение (/res/layout/quick_play_screen.xml):

<?xml version="1.0" encoding="utf-8"?>
   <com.games.mygame.CustomLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_height="fill_parent" 
      android:layout_width="fill_parent" 
      android:id="@+id/QuickPlayClipLayout">
      <ImageView android:id="@+id/Clip"
         android:background="@drawable/clip" 
         android:layout_width="fill_parent" 
         android:layout_height="wrap_content">
      </ImageView>
   </com.games.mygame.CustomLinearLayout>

Ресурс (/res/values/constants.xml):

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="quickplay_offset">50dp</dimen>
</resources>

Анимация (/res/anim/slide_in_quickplay.xml):

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
   <translate android:fromYDelta="100%p" 
       android:toYDelta="0"
       android:duration="1000"/>
   <alpha android:fromAlpha="0.0" 
       android:toAlpha="1.0"
       android:duration="1000" />
</set>

Теперь программа делает именно то, что мне нужно, чтобы она делала.Весь макет начинается с экрана внизу, скользит в течение 1 секунды и останавливается там, где верхняя часть макета фактически находится на расстоянии 50 пикселей от верхней части экрана (т. Е. LL.getTop() = -50) и нижняя часть макета находится в нижней части экрана (т.е. LL.getBottom() = 530 = 480 + 50).

Другие советы

Вместо этого мы можем просто присвоить layout_margin отрицательные значения (вверху / слева / справа / внизу) например:Если вы хотите, чтобы ваш вид был отключен от верхней части экрана, вы можете указать

android:layout_marginTop="-40dp"

Чтобы расположить свой вид за кадром, я использовал следующий код:

View myView = /* view you want to position offscreen */
int amountOffscreen = (int)(myView.getWidth() * 0.8); /* or whatever */
boolean offscreen = /* true or false */


int xOffset = (offscreen) ? amountOffscreen : 0;
RelativeLayout.LayoutParams rlParams = 
    (RelativeLayout.LayoutParams)myView.getLayoutParams();
rlParams.setMargins(-1*xOffset, 0, xOffset, 0);
myView.setLayoutParams(rlParams);

Этот код расположит MyView за кадром по amountOffscreen , что в данном случае приводит к удалению 80% вида за кадром, оставляя на экране только 20%.

Не используйте метод layout() напрямую - Android будет выполнять последующие вызовы для аннулирования вашего представления по случайным причинам, и только LayoutParams сохраняются при вызовах invalidate.Если вам интересно, ознакомьтесь с линиями с 904 по 912 этого файла чтобы понять, почему вы должны изменить параметры layout.

Это легко сделать, если вы перейдете к использованию Canvas;они поддерживают вывод изображения с экрана без каких-либо проблем.Однако реализовать это будет сложнее.Вам нужно было бы реализовать пользовательский View и напишите свою собственную анимацию в коде.По сути, это сводится к простой обработке 2D-графики, а не к просмотру с использованием встроенной XML-анимации.Возможно, есть способ сделать это с помощью XML, но я гораздо больше знаком с canvases .Очень хорошее место, чтобы увидеть, как это обрабатывается в коде, - это пример игры Lunar Lander, которая поставляется вместе с SDK.

Примерно следующие шаги, которые вам нужно будет выполнить::

  1. Поместите пользовательское представление в XML-файл, используя что-то вроде <your.package.AnimatingView>, установив его размер на fill-parent.

  2. Затем определите класс AnimatingView, который extends SurfaceView and implements SurfaceHolder.Callback.(Это дает вам доступ к чертежу Canvas немедленно, а не с помощью invalidate() способ.Это важно, потому что invalidate() обновляется только тогда, когда поток простаивает, напримерв конце цикла.Чтобы реализовать вашу анимацию, вам нужно, чтобы она была нарисована немедленно.)

  3. Затем вы можете реализовать цикл, который рисует ваше движущееся изображение по экрану.Цикл должен начинаться с рисования всего фона (поскольку холст автоматически не стирается), а затем рисовать изображение в его новом положении в зависимости от прошедшего времени.Например, если вы хотите, чтобы выполнение вашей анимации заняло 1 секунду, то вы знаете, что если прошло 200 мс, вид должен был переместиться только на 200/1000, или 1/5, пути от начальной позиции до конечной.

Вы можете увидеть некоторые примеры того, что я имею в виду, в моих других ответах на вопросы по анимации:основной ответ о полезность использования SurfaceView и и пример цикла для использования.Примечание:второй вопрос касался ротации, и, следовательно, некоторые из трудностей, о которых я говорил, не будут иметь к вам отношения.Удачи вам!

С android:translationX и android:translationY

<RelativeLayout
        android:translationX="-600dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent">

У меня была viewgroup с дочерними элементами, и я перетаскивал вид на экран снизу - что-то вроде выдвижного ящика.Затем я бы отпустил, и если бы верхнее поле viewgroup находилось в верхней половине экрана, я бы анимировал его вверху после того, как пользователь отпустил касание.

Когда это происходило, изображения в дочерних элементах viewgroup обрезались во время анимации, но затем показывались после анимации.

Проблема:высота viewgroup была wrap_content .Я решил эту проблему, установив высоту на значение, которое простиралось за пределы экрана до начала анимации.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top