web-dev-qa-db-ja.com

Android-ビューを画面外に配置する方法は?

私はアプリケーションで簡単なImageViewをアニメーション化しようとしていますが、画面の下部からスライドさせて、ビューの上部50pxが画面の上部から外れた静止位置に来るようにします(たとえば、最終位置ImageViewのXで-50pxである必要があります。これを行うためにAbsoluteLayoutを使用しようとしましたが、実際にはImageViewの上部50ピクセルが切り取られるため、上部50ピクセルはレンダリングされません。 ImageViewの上位50ピクセルをアニメーション化しながら表示/レンダリングし、画面から少し休めるようにする必要があります。これで十分に説明できたと思います。

以下は、現在レイアウトとスライドインアニメーションとして使用しているものです(現在、ImageViewの上位50ピクセルはレンダリングされていません)。

レイアウト:

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

前もって感謝します。

59
RyanM

これを簡単に実装できる解決策を見つけました。これには、レイアウトの変更とアクティビティのレイアウトの拡張が含まれます。以下を参照してください。

アクティビティ(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));
    }
}
_

新しい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)));
    }
}
_

レイアウト(/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秒でスライドインし、レイアウトの一番上が実際に画面の上部から50px(LL.getTop() = -50)と下部のレイアウトは画面の一番下にあります(つまり、LL.getBottom() = 530 = 480 + 50)。

33
RyanM

代わりに、layout_margin(Top/left/right/bottom)に単純に負の値を与えることができます。例:ビューを画面の上部から外したい場合は、指定できます

Android:layout_marginTop="-40dp"
31
arun

ビューを画面外に配置するには、次のコードを使用しました。

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のみが保持されます。 このファイルの904〜912 は、layoutParamsを変更する必要がある理由を確認します。

30
esilver

Canvasを使用して跳躍する場合、これは簡単です。それらは、問題なく画面からの描画をサポートします。ただし、実装はより複雑になります。カスタムViewを実装し、コードで独自のアニメーションを記述する必要があります。基本的に、これは組み込みのXMLアニメーションを使用したビューではなく、単純な2Dグラフィックス処理になります。 XMLでそれを行う方法はあるかもしれませんが、私はキャンバスにずっと精通しています。これがコードでどのように処理されるかを確認するには、SDKに付属するLunar Landerのサンプルゲームをご覧ください。

従う必要があるおおよその手順は次のとおりです。

  1. _<your.package.AnimatingView>_のようなものを使用してXMLファイルにカスタムビューを配置し、サイズをfill-parentに設定します。

  2. 次に、_extends SurfaceView and implements SurfaceHolder.Callback_というAnimatingViewクラスを定義します。 (これにより、invalidate()メソッドを使用するのではなく、すぐに図面Canvasにアクセスできます。invalidate()は、スレッドがアイドル状態のとき(たとえば、ループ。アニメーションを実装するには、すぐに描画する必要があります。

  3. その後、画面全体に動画を描くループを実装できます。ループは、キャンバス全体が自動的に消去されるわけではないため、背景全体を描画することから開始し、経過した時間に基づいて新しい位置に画像を描画する必要があります。たとえば、アニメーションの実行に1秒かかる場合、200ミリ秒が経過すると、ビューは開始位置から最終位置まで200/1000または1/5だけ移動するはずです。 。

アニメーションの質問に対する他の回答で私が意味するもののいくつかの例を見ることができます: SurfaceViewループの例を使用することの有用性に関する基本的な回答使用する 。注:2番目の質問は回転に関するものであり、したがって、私が話したいくつかの困難はあなたには関係ありません。がんばろう!

9
Steve Haley

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">
3
Pablo Cegarra

私は子供のいるビューグループを持っていて、下から画面にビューをドラッグしていました-引き出しのようなものです。その後、放します。ビューグループの上部マージンが画面の上半分にある場合、ユーザーがタッチを離した後、上部にアニメーション化します。

これが発生すると、ビューグループの子の画像はアニメーション中にトリミングされますが、アニメーションの後に表示されます。

問題:ビューグループの高さはwrap_contentでした。これを解決するには、アニメーションを開始する前に画面の外に広がる値に高さを設定しました。

2
Chris Sprague