2016-03-22 16 views
7

RecyclerView'den nasıl bir alt görünüm alınabilir?

Ben animasyonlar elle bu tür kod çalışıyorum [ALT AT DÜZENLENECEK]: dikkatle bu görüşleri görürseniz

Google Calendar

, bir List veya RecyclerView aittir, ancak ana'un sınırlarının dışına animasyonludur (boyut animasyonu, çeviri animasyonu).

Bunu yapmaya çalışırsam, sonuç benim görüşümün ebeveynlerimin sınırlarının altına düşmesidir.


Bu

https://drive.google.com/file/d/0B-V0KHNRjbE_bkJEekExNGNLbDA/view?usp=sharing

dikkatlice çocuk görünümü ebeveynden alınmış olduğunu görmek için sadece durdu, bir kare olduğunu ve bütün görünümüne genişleyen başlıyor:

enter image description here

ve neredeyse% 100 genişletilmiş olduğu yer burasıdır:

enter image description here


Sadece bunu başka bir şekilde yeniden işaret etmek istedim. Bu Activity Transitions ile ilişkili bir şey mi? Çünkü eğer öyleyse, nasıl yapılacağına dair hiçbir fikrim yok.

bir yolu Paylaşılan Eleman Aktivite Geçiş kullanıyor:

cevap

1

Ben bu etkiyi elde etmek için iki yoldan düşünebilirsiniz. 2 aktivitenin kullanılmasını gerektirecektir: biri tam ekran görüntüsü ile ikinci, geri dönüşümlü bir görünüm. Animasyon, etkinlik 1 ile etkinlik iki arasında geçiş arasında otomatik olarak uygulanacaktır. Bu çözüm işe yarayacak ve çok fazla kod gerektirmeyecek, ancak iki aktiviteyi senkronize halde tutma problemine gireceksiniz (RecyclerView'ın tam konumu gibi). Özelleştirme imkansız değildir, ancak çerçeveye sıkı sıkıya bağlı olduğunuzdan zor olabilir.

İkinci yol, aynı etkinlik içinde kalıyor ve geri dönüşümcü öğenizle tam ekran görünümü arasında geçiş yapmak için nesne animatörleri kullanıyor. Hile, RecyclerView öğesinin içinde bulunan görünümü canlandırmak değil, tam ekran görünümünüzü, RecyclerView öğesinin içinde yer alan görünümün sınırlarından hareketlendirmek değildir. Bu şekilde, ebeveynin sınırları tarafından sınırlanmayacaksınız. İleriye gittim ve son derece özelleştirilebilir olduğundan ve tüm animasyonlar üzerinde tam bir kontrol sağladığından ikinci çözümü uyguladım.

Bu örnek uygulama, çeviri ve ölçekleme animatörlerini içerir. Ekranın sol tarafında küçük kare pozisyon görünümünden canlandıracak. Bu davranış kolayca değiştirilebilir.

Demo: proje https://dl.dropboxusercontent.com/u/87080012/device-2016-03-25-160611.mp4

Bağlantı Repo: https://[email protected]/dkarmazi/androidrecyclerviewanimation.git

Etkinlik

public class MainActivity extends AppCompatActivity implements Adapter.ItemClickListener, CustomView.CloseButtonClickListener { 
    public static final int ANIMATION_SPEED = 3000; 
    private RecyclerView recyclerView; 
    private CustomView customView; 
    private RelativeLayout rootView; 
    private Rect lastClickedRecyclerViewItemRect; 

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

     rootView = (RelativeLayout) findViewById(R.id.root_view); 
     recyclerView = (RecyclerView) findViewById(R.id.recycler_view); 
     customView = (CustomView) findViewById(R.id.custom_view); 

     recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext())); 
     recyclerView.setAdapter(new Adapter(getApplicationContext(), this, getSampleData())); 
    } 

    @Override 
    public void onItemClicked(View clickedView, int position, String title) { 
     lastClickedRecyclerViewItemRect = new Rect(); 
     clickedView.getGlobalVisibleRect(lastClickedRecyclerViewItemRect); 

     Rect targetViewRect = new Rect(); 
     rootView.getGlobalVisibleRect(targetViewRect); 

     AnimatorSet animatorSet = getViewToViewScalingAnimator(rootView, customView, lastClickedRecyclerViewItemRect, targetViewRect, ANIMATION_SPEED, 0); 

     customView.setData(position, title, this); 
     customView.setVisibility(View.VISIBLE); 

     animatorSet.start(); 
    } 

    @Override 
    public void onCloseButtonClicked(int position) { 
     Rect clickedViewRect = new Rect(); 
     customView.getGlobalVisibleRect(clickedViewRect); 
     AnimatorSet animatorSet = getViewToViewScalingAnimator(rootView, customView, clickedViewRect, lastClickedRecyclerViewItemRect, ANIMATION_SPEED, 0); 

     animatorSet.addListener(new Animator.AnimatorListener() { 
      @Override 
      public void onAnimationStart(Animator animation) { 
       // no op 
      } 

      @Override 
      public void onAnimationEnd(Animator animation) { 
       customView.setVisibility(View.GONE); 
      } 

      @Override 
      public void onAnimationCancel(Animator animation) { 
       // no op 
      } 

      @Override 
      public void onAnimationRepeat(Animator animation) { 
       // no op 
      } 
     }); 

     animatorSet.start(); 
    } 

    public static AnimatorSet getViewToViewScalingAnimator(final RelativeLayout parentView, 
                  final View viewToAnimate, 
                  final Rect fromViewRect, 
                  final Rect toViewRect, 
                  final long duration, 
                  final long startDelay) { 
     // get all coordinates at once 
     final Rect parentViewRect = new Rect(), viewToAnimateRect = new Rect(); 
     parentView.getGlobalVisibleRect(parentViewRect); 
     viewToAnimate.getGlobalVisibleRect(viewToAnimateRect); 

     viewToAnimate.setScaleX(1f); 
     viewToAnimate.setScaleY(1f); 

     // rescaling of the object on X-axis 
     final ValueAnimator valueAnimatorWidth = ValueAnimator.ofInt(fromViewRect.width(), toViewRect.width()); 
     valueAnimatorWidth.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
      @Override 
      public void onAnimationUpdate(ValueAnimator animation) { 
       // Get animated width value update 
       int newWidth = (int) valueAnimatorWidth.getAnimatedValue(); 

       // Get and update LayoutParams of the animated view 
       RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) viewToAnimate.getLayoutParams(); 

       lp.width = newWidth; 
       viewToAnimate.setLayoutParams(lp); 
      } 
     }); 

     // rescaling of the object on Y-axis 
     final ValueAnimator valueAnimatorHeight = ValueAnimator.ofInt(fromViewRect.height(), toViewRect.height()); 
     valueAnimatorHeight.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
      @Override 
      public void onAnimationUpdate(ValueAnimator animation) { 
       // Get animated width value update 
       int newHeight = (int) valueAnimatorHeight.getAnimatedValue(); 

       // Get and update LayoutParams of the animated view 
       RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) viewToAnimate.getLayoutParams(); 
       lp.height = newHeight; 
       viewToAnimate.setLayoutParams(lp); 
      } 
     }); 

     // moving of the object on X-axis 
     ObjectAnimator translateAnimatorX = ObjectAnimator.ofFloat(viewToAnimate, "X", fromViewRect.left - parentViewRect.left, toViewRect.left - parentViewRect.left); 

     // moving of the object on Y-axis 
     ObjectAnimator translateAnimatorY = ObjectAnimator.ofFloat(viewToAnimate, "Y", fromViewRect.top - parentViewRect.top, toViewRect.top - parentViewRect.top); 

     AnimatorSet animatorSet = new AnimatorSet(); 
     animatorSet.setInterpolator(new DecelerateInterpolator(1f)); 
     animatorSet.setDuration(duration); // can be decoupled for each animator separately 
     animatorSet.setStartDelay(startDelay); // can be decoupled for each animator separately 
     animatorSet.playTogether(valueAnimatorWidth, valueAnimatorHeight, translateAnimatorX, translateAnimatorY); 

     return animatorSet; 
    } 

    private static List<String> getSampleData() { 
     List<String> dataList = new ArrayList<>(); 
     dataList.add("zero"); 
     dataList.add("one"); 
     dataList.add("two"); 
     dataList.add("three"); 
     dataList.add("four"); 
     dataList.add("five"); 
     dataList.add("six"); 
     dataList.add("seven"); 
     dataList.add("eight"); 
     dataList.add("nine"); 
     dataList.add("ten"); 
     dataList.add("eleven"); 
     dataList.add("twelve"); 
     dataList.add("thirteen"); 
     dataList.add("fourteen"); 
     dataList.add("fifteen"); 
     dataList.add("sixteen"); 
     dataList.add("seventeen"); 
     dataList.add("eighteen"); 
     dataList.add("nineteen"); 
     dataList.add("twenty"); 

     return dataList; 
    } 
} 

Etkinlik düzeni

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

    <android.support.v7.widget.RecyclerView 
     android:id="@+id/recycler_view" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:background="@android:color/white"/> 

    <com.dkarmazi.android.myapplication.CustomView 
     android:id="@+id/custom_view" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:visibility="gone"/> 
</RelativeLayout> 

Özel Görünüm tam ekran

gösterilir
public class CustomView extends FrameLayout { 
    public interface CloseButtonClickListener { 
     void onCloseButtonClicked(int position); 
    } 

    private TextView positionView; 
    private TextView titleView; 
    private View closeView; 
    private CloseButtonClickListener closeButtonClickListener; 
    private int position; 

    public CustomView(Context context) { 
     super(context); 
     init(); 
    } 

    public CustomView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

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

    @TargetApi(Build.VERSION_CODES.LOLLIPOP) 
    public CustomView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 
     super(context, attrs, defStyleAttr, defStyleRes); 
     init(); 
    } 

    private void init() { 
     inflate(getContext(), R.layout.custom_view, this); 
     positionView = (TextView) findViewById(R.id.custom_view_position); 
     titleView = (TextView) findViewById(R.id.custom_view_title); 
     closeView = findViewById(R.id.custom_view_close_button); 

     closeView.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       if(closeButtonClickListener != null) { 
        closeButtonClickListener.onCloseButtonClicked(position); 
       } 
      } 
     }); 
    } 

    public void setData(int position, String title, CloseButtonClickListener closeButtonClickListener) { 
     this.position = position; 
     this.positionView.setText("" + position); 
     this.titleView.setText(title); 
     this.closeButtonClickListener = closeButtonClickListener; 
    } 
} 

özel görünüm

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="@android:color/holo_red_dark"> 

    <ImageView 
     android:id="@+id/custom_view_close_button" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:src="@android:drawable/ic_menu_close_clear_cancel" 
     android:layout_alignParentTop="true" 
     android:layout_alignParentRight="true"/> 

    <LinearLayout 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="vertical" 
     android:gravity="center" 
     android:layout_marginTop="50dp"> 

     <TextView 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:textColor="@android:color/white" 
      android:textSize="20sp" 
      android:gravity="center" 
      android:layout_gravity="top" 
      android:text="Position:" /> 

     <TextView 
      android:id="@+id/custom_view_position" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:textColor="@android:color/white" 
      android:textSize="25sp" 
      android:gravity="center" 
      android:layout_gravity="top" 
      android:paddingBottom="100dp" /> 

     <TextView 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:textColor="@android:color/white" 
      android:textSize="20sp" 
      android:gravity="center" 
      android:layout_gravity="top" 
      android:text="Title:" /> 

     <TextView 
      android:id="@+id/custom_view_title" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:textColor="@android:color/white" 
      android:gravity="center" 
      android:textSize="25sp" 
      android:layout_gravity="center"/> 
    </LinearLayout> 
</RelativeLayout> 

RecyclerView Adaptörü

public class Adapter extends RecyclerView.Adapter { 
    public interface ItemClickListener { 
     void onItemClicked(View v, int position, String title); 
    } 

    private Context context; 
    private ItemClickListener itemClickListener; 
    private List<String> dataList; 

    public Adapter(Context context, ItemClickListener itemClickListener, List<String> dataList) { 
     this.context = context; 
     this.itemClickListener = itemClickListener; 
     this.dataList = dataList; 
    } 

    @Override 
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View view = LayoutInflater.from(context).inflate(R.layout.recycler_view_item, null, false); 

     return new MyViewHolder(view, new OnRecyclerItemClickListener()); 
    } 


    @Override 
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
     ((MyViewHolder) holder).onRecyclerItemClickListener.updatePosition(position); 
     ((MyViewHolder) holder).position.setText("" + position); 
     ((MyViewHolder) holder).title.setText(dataList.get(position)); 
    } 

    @Override 
    public int getItemCount() { 
     return dataList.size(); 
    } 

    private class MyViewHolder extends RecyclerView.ViewHolder { 
     private OnRecyclerItemClickListener onRecyclerItemClickListener; 
     private TextView position; 
     private TextView title; 

     public MyViewHolder(View itemView, OnRecyclerItemClickListener onRecyclerItemClickListener) { 
      super(itemView); 

      itemView.setOnClickListener(onRecyclerItemClickListener); 
      this.onRecyclerItemClickListener = onRecyclerItemClickListener; 
      this.position = (TextView) itemView.findViewById(R.id.position); 
      this.title = (TextView) itemView.findViewById(R.id.title); 
     } 
    } 


    private class OnRecyclerItemClickListener implements View.OnClickListener { 
     private int position = -1; 

     public void updatePosition(int position) { 
      this.position = position; 
     } 

     @Override 
     public void onClick(View v) { 
      if(itemClickListener != null) { 
       itemClickListener.onItemClicked(v.findViewById(R.id.position), position, dataList.get(position)); 
      } 
     } 
    } 
} 

Recycler görünümü öğesi düzeni

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/recycler_view_item" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:padding="10dp"> 

    <TextView 
     android:id="@+id/position" 
     android:layout_width="30dp" 
     android:layout_height="50dp" 
     android:textColor="@android:color/white" 
     android:gravity="center" 
     android:background="@android:color/holo_green_light" 
     android:layout_alignParentLeft="true"/> 

    <TextView 
     android:id="@+id/title" 
     android:layout_width="match_parent" 
     android:layout_height="50dp" 
     android:textColor="@android:color/white" 
     android:gravity="center" 
     android:background="@android:color/holo_green_dark" 
     android:layout_toRightOf="@id/position" 
     android:layout_alignParentRight="true"/> 
</RelativeLayout> 
+0

için Düzen (Will ödül kelle SO bana bunu yapmak için izin verdiğinde) . Bence bunu bir etkinlikle yapmanın bir yolu yok, bunun benim düşündüğüm şeydi. Yani bu nihayet hile! teşekkür ederim çok mücahit –

İlgili konular