Android — Как расположить Представление вне экрана?

Я пытаюсь анимировать простой 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>

Заранее спасибо.

61
задан RyanM 31 March 2010 в 16:54
поделиться

2 ответа

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

Activity (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));
    }
}

New LinearLayout (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)));
    }
}

Layout (/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>

Resource (/res/values/constants.xml):

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

Animation (/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 секунду и приходит в состояние покоя, когда верх макета фактически находится на 50px от верха экрана (т.е. LL.getTop() = -50), а низ макета упирается в низ экрана (т.е. LL.getBottom() = 530 = 480 + 50).

33
ответ дан 24 November 2019 в 17:17
поделиться

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

Примерно шаги, которые вам необходимо выполнить:

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

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

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

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

9
ответ дан 24 November 2019 в 17:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: