0

親ビューのサイズ変更後にカスタムViewGroupで子ビューの配置中に望ましくない遷移を避けるためにいくつか問題があります。この問題は、setContentView()の代わりにWindowManagerを使用した場合にのみ存在するようです。ここで簡単な例である:Androidビューのサイズ変更とWindowManager:子ビューの配置中の不要な切り替え

MainActivity

public class MainActivity extends AppCompatActivity { 

    private static final int MY_PERMISSIONS_DRAW_OVER_OTHER_APPS = 1; 
    CustomViewGroup mCustomViewGroup; 
    WindowManager mWindowManager; 

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


     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) { 

      Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, 
        Uri.parse("package:" + getPackageName())); 
      startActivityForResult(intent, MY_PERMISSIONS_DRAW_OVER_OTHER_APPS); 
     } 


     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) { 
      if (ContextCompat.checkSelfPermission(this, 
        android.Manifest.permission.SYSTEM_ALERT_WINDOW) 
        != PackageManager.PERMISSION_GRANTED) { 

       if (ActivityCompat.shouldShowRequestPermissionRationale(this, 
         android.Manifest.permission.SYSTEM_ALERT_WINDOW)) { 


       } else { 

        ActivityCompat.requestPermissions(this, 
          new String[]{android.Manifest.permission.SYSTEM_ALERT_WINDOW}, 
          MY_PERMISSIONS_DRAW_OVER_OTHER_APPS); 
       } 
      } 
     } 

     mCustomViewGroup = 
       (CustomViewGroup) LayoutInflater.from(this).inflate(R.layout.activity_main,null); 

     final WindowManager.LayoutParams floatingViewLayoutParams = new WindowManager.LayoutParams(
       WindowManager.LayoutParams.WRAP_CONTENT, 
       WindowManager.LayoutParams.WRAP_CONTENT, 
       WindowManager.LayoutParams.TYPE_PHONE, 
       WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, 
       PixelFormat.TRANSLUCENT 
     ); 
     floatingViewLayoutParams.gravity = Gravity.BOTTOM | Gravity.LEFT; 
     mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE); 
     mWindowManager.addView(mCustomViewGroup,floatingViewLayoutParams); 


    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
     if (requestCode == MY_PERMISSIONS_DRAW_OVER_OTHER_APPS) { 
      //Check if the permission is granted or not. 
      if (resultCode == RESULT_OK) { 
      } else { 
       Toast.makeText(this, 
         "Draw over other app permission not available. Closing the application", 
         Toast.LENGTH_SHORT).show(); 

       finish(); 
      } 
     } else { 
      super.onActivityResult(requestCode, resultCode, data); 
     } 
    } 

} 

CustomViewGroup

public class CustomViewGroup extends ViewGroup { 

    private boolean mIsTouchEventActive; 

    public CustomViewGroup(Context context) { 
     this(context,null,0); 
    } 

    public CustomViewGroup(Context context, AttributeSet attrs) { 
     this(context,attrs,0); 
    } 

    public CustomViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
     init(context); 
    } 

    private void init(Context context) { 

     mIsTouchEventActive = false; 
     setWillNotDraw(false); 

     // Add the fab view 
     LayoutInflater layoutInflater = LayoutInflater.from(context); 
     View fabView = layoutInflater.inflate(R.layout.fab_view,null,false); 
     this.addView(fabView); 
    } 

    @Override 
    public boolean shouldDelayChildPressedState() { 
     return false; 
    } 

    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     return true; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 


     switch (event.getAction()) { 

      case MotionEvent.ACTION_DOWN: 
       mIsTouchEventActive = true; 
       requestLayout(); 
       return true; 

      case MotionEvent.ACTION_UP: 
       mIsTouchEventActive = false; 
       requestLayout(); 
       return true; 

     } 
     return false; 

    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 


     int maxHeight = 0; 
     int maxWidth = 0; 
     int childState = 0; 

     final View child = getChildAt(0); 
     if (child.getVisibility() != GONE) { 

      measureChild(child, widthMeasureSpec, heightMeasureSpec); 
      maxWidth = Math.max(maxWidth, child.getMeasuredWidth()); 
      maxHeight = Math.max(maxHeight, child.getMeasuredHeight()); 
      childState = combineMeasuredStates(childState, child.getMeasuredState()); 

     } 

     maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight()); 
     maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth()); 
     if (mIsTouchEventActive == true) { 

      final Display display = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 
      Point deviceDisplay = new Point(); 
      display.getSize(deviceDisplay); 

      maxHeight = deviceDisplay.x; 
      maxWidth = deviceDisplay.y; 
     } 


     setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState), 
       resolveSizeAndState(maxHeight, heightMeasureSpec, childState << MEASURED_HEIGHT_STATE_SHIFT)); 

    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 

     final Rect fabChildRect = new Rect(); 
     final View child = getChildAt(0); 
     if (child.getVisibility() != GONE) { 

      final int width = child.getMeasuredWidth(); 
      final int height = child.getMeasuredHeight(); 

      fabChildRect.left = 0; 
      fabChildRect.right = width; 
      fabChildRect.top = 0; 
      fabChildRect.bottom = height; 

      child.layout(fabChildRect.left, fabChildRect.top, 
        fabChildRect.right, fabChildRect.bottom); 

     } 
    } 
} 

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<packagename.CustomViewGroup 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/custom_view_group" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_alignParentBottom="true" 
    android:layout_alignParentLeft="true"/> 

fab_view.xml

<?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:orientation="vertical" 
       android:layout_width="wrap_content" 
       android:layout_height="wrap_content"> 

    <android.support.design.widget.FloatingActionButton 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:app="http://schemas.android.com/apk/res-auto" 
     android:id="@+id/fab" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_margin="16dp" 
     app:srcCompat="@android:drawable/ic_dialog_email"/> 

</LinearLayout> 

マニフェストファイルはandroid.permission.SYSTEM_ALERT_WINDOW許可を含まなければならないとbuild.gradleの私の依存関係のリストは以下の通りです:

を私は継承カスタムビューCustomViewGroupを持っています。ここでは

dependencies { 
    compile fileTree(dir: 'libs', include: ['*.jar']) 
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 
     exclude group: 'com.android.support', module: 'support-annotations' 
    }) 
    compile 'com.android.support:appcompat-v7:24.2.1' 
    compile 'com.android.support.constraint:constraint-layout:1.0.2' 
    compile 'com.android.support:design:24.2.1' 
    testCompile 'junit:junit:4.12' 
} 

は私がやっているものですViewGroup私の短い例ではFloatingActionButtonがあり、親ビューの左下隅に配置されています。 CustomViewGroupのデフォルトサイズは、FloatingActionButton:264x264のものです。

ACTION_DOWNイベントの場合にはCustomViewGroupのサイズはディスプレイ全体に拡大されるように、私はCustomViewGrouponClickonMeasureメソッドを実装しました。 ACTION_UPイベントの場合、サイズはデフォルト値に戻ります。 CustomViewGroupFloatingActionButtonの位置は、親ビューのサイズは、ユーザのタッチした後に変更されたとき、したがってボタン自体は異なる位置に配置され、常に

fabChildRect.left = 0; 
fabChildRect.right = width; 
fabChildRect.top = 0; 
fabChildRect.bottom = height; 
widthheightが共に264に等しい

あります。

私の質問は、ユーザータッチイベントの場合のアクションボタンの配置中にアニメーションを削除する方法は?私はボタンビューの垂直方向の動きを意味します。私はすでにすべてのトランジションタイプでdisableTransitionTypeメソッドを試しましたが、何も変わりません。 xmlファイルのトランジションを無効にしようとした場合と同じです。 CustomViewGroupビューは、次のactivity_main.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    android:id="@+id/activity_main" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="packagename.MainActivity"> 

    <packagename.CustomViewGroup 
    xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@+id/custom_view_group" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_alignParentLeft="true"/> 

</RelativeLayout> 

で例えば、XMLから、それを膨らませる代わりにWindowManagerを使用することにより、メインアクティビティビューに追加された場合は、この移行は存在していないあなたが解決する方法上の任意のアドバイスはありますか私の問題と、おそらく私が観察しているものの説明もありますか?おそらく私のコードから推測できるように、私はAndroidプログラミングの初心者なので、このスレッドのトピックに厳密に関連していない一般的なアドバイスは大歓迎です!

ありがとうございます。

UPDATE:私はWindowManagerを使用するViewRootImpl(ライン5415)、不要な可視変化は、この方法の実行中に行われる内

int relayoutResult = mWindowSession.relayout(
    mWindow, mSeq, params, 
    (int) (mView.getMeasuredWidth() * appScale + 0.5f), 
    (int) (mView.getMeasuredHeight() * appScale + 0.5f), 
    viewVisibility, 
    insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0,mWinFrame, 
    mPendingOverscanInsets, mPendingContentInsets, mPendingVisibleInsets, 
    mPendingStableInsets, mPendingOutsets, mPendingConfiguration, mSurface); 

への呼び出しがあることを見つけました。私がCustomViewGroupを主なアクティビティのxmlから膨らませると、上記のメソッドはタッチイベントの場合には呼び出されず、この状態でも遷移は見えないので、私はmWindowSessionデータメンバーのrelayoutメソッドを考えることができると思いますタイプはIWindowSession)です。

答えて

関連する問題