Android 는 ViewPager 를 이용 하여 미끄럼 확대 및 축소 갤러리 효 과 를 실현 합 니 다.

갤러리 는 많은 App 디자인 에 있 습 니 다.다음 그림 과 같 습 니 다.

이 예 는 제 가 괜 찮 을 때 쓴 작은 항목 입 니 다.구체 적 인 소스 주 소 는 방문 하 십시오https://github.com/AlexSmille/YingMi
이 갤러리 는 표지 와 비슷 한 효과 로 중간 으로 미 끄 러 지 는 그림 이 점점 커지 고 떠 나 는 View 는 점점 줄 어 들 며 미끄럼 감청 과 클릭 감청 을 설정 할 수 있다.
인터넷 에 서 는 Gallery 를 통 해 이 루어 진 사례 가 많 습 니 다.상례 의 실현 은 ViewPager 를 통 해 이 루어 진 것 으로 성능 최적화 문 제 를 해결 하 였 습 니 다.오늘 은 특별히 이 를 뽑 아서 포장 하여 앞으로 편리 하 게 사용 할 수 있 도록 하 겠 습 니 다.최종 실현 효 과 는 다음 과 같다.

사용 방식
레이아웃 에 사용자 정의 컨트롤 추가

<RelativeLayout 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">

 <!--           -->
 <com.mahao.alex.customviewdemo.viewpager.CoverFlowViewPager
 android:id="@+id/cover"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" />

</RelativeLayout>
코드 설정
코드 의 설정 은 다음 과 같은 몇 가지 절차 로 나 뉜 다.
 •찾기 컨트롤
 •데이터 초기 화
 •표시 할 데 이 터 를 컨트롤 에 설정 합 니 다.
 •미끄럼 감청 설정 

public class MainActivity extends AppCompatActivity {

 private CoverFlowViewPager mCover;

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

 mCover = (CoverFlowViewPager) findViewById(R.id.cover);

 //      
 List<View> list = new ArrayList<>();
 for(int i = 0;i<10;i++){
 ImageView img = new ImageView(this);
 img.setBackgroundColor(Color.parseColor("#"+getRandColorCode()));
 list.add(img);
 }
 //       
 mCover.setViewList(list);
 //        ,                 
 mCover.setOnPageSelectListener(new OnPageSelectListener() {
 @Override
 public void select(int position) {
 Toast.makeText(getApplicationContext(),position+"",Toast.LENGTH_SHORT).show();
 }
 });
 }


 /**
 *       ,    
 * @return
 */
 public static String getRandColorCode(){
 String r,g,b;
 Random random = new Random();
 r = Integer.toHexString(random.nextInt(256)).toUpperCase();
 g = Integer.toHexString(random.nextInt(256)).toUpperCase();
 b = Integer.toHexString(random.nextInt(256)).toUpperCase();

 r = r.length()==1 ? "0" + r : r ;
 g = g.length()==1 ? "0" + g : g ;
 b = b.length()==1 ? "0" + b : b ;

 return r+g+b;
 }
}
실현 원리
실현 과정 에서 두 가지 난점 이 있다.
 •어떻게 미끄럼 과정 중의 확대 와 축 소 를 실현 합 니까?
 •ViewPager 에 표시 되 지 않 은 페이지 를 표시 하 는 방법 
어떻게 미끄럼 과정 중의 확대 와 축 소 를 실현 합 니까?
모든 ViewPager 의 페이지 를 설정 할 때 모든 페이지 에 고정 적 인 padding 값 을 설정 하면 모든 페이지 가 축소 상 태 를 표시 합 니 다.이 동시에 ViewPager 는 addOnPageChangeListener()를 설정 하고 슬라이딩 감청 을 하 며 이 슬라이딩 감청 에 서 는 ViewPager 가 미 끄 러 지 는 상태,미 끄 러 지 는 편 이 량 등 을 되 돌려 미 끄 러 지 는 편 이 량 에 따라 확대 축소 합 니 다.padding 값 에 따라 컨트롤 의 디 스 플레이 크기 를 설정 합 니 다.
ViewPager 에 표시 되 지 않 은 페이지 를 표시 하 는 방법
xml 에 자주 사용 되 지 않 는 속성 android:clipChildren 이 있 습 니 다.하위 View 의 표 시 를 제한 할 지 여부 입 니 다.false 로 설정 하면 하위 View 의 디 스 플레이 는 부모 컨트롤 의 제한 을 받 지 않 습 니 다.
코드 구현
컨트롤 의 레이아웃 파일 을 작성 합 니 다.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:clipChildren="false">

 <android.support.v4.view.ViewPager
 android:id="@+id/vp_conver_flow"
 android:layout_width="180dp"
 android:layout_height="260dp"
 android:layout_centerHorizontal="true"
 android:clipChildren="false" />

</RelativeLayout>
 상대 레이아웃 에 ViewPager 를 삽입 합 니 다.상대 레이아웃 은 표시 범 위 를 확인 하 는 데 사 용 됩 니 다.ViewPager 는 미끄럼,확대 축소 등 을 실현 합 니 다.
CoverFlowViewPager 를 만 들 고 레이아웃 을 불 러 옵 니 다.

/**
 *
 *       
 * Created by alex_mahao on 2016/8/25.
 */
public class CoverFlowViewPager extends RelativeLayout implements OnPageSelectListener {
 /**
 *       
 */
 private ViewPager mViewPager;

 public CoverFlowViewPager(Context context, AttributeSet attrs) {
 super(context, attrs);
 inflate(context, R.layout.widget_cover_flow,this);
 mViewPager = (ViewPager) findViewById(R.id.vp_conver_flow);
 //init();
 }
컨트롤 을 찾 고 레이아웃 을 불 러 옵 니 다.
어댑터 를 작성 하여 미 끄 러 지 는 감청 을 실현 합 니 다.
ViewPager 가 생 겼 으 니 어댑터 Adapter 가 있어 야 합 니 다.미끄럼 감청 에서 각 하위 요 소 를 오프셋 에 따라 조작 하고 확대 하거나 축소 해 야 하기 때문에 하위 요 소 는 물론 어댑터 가 가장 쉽게 얻 을 수 있 기 때문에 Adapter 를 ViewPager 의 미끄럼 감청 인 터 페 이 스 를 실현 합 니 다.

/**
 *       
 * Created by alex_mahao on 2016/8/25.
 */
public class CoverFlowAdapter extends PagerAdapter implements ViewPager.OnPageChangeListener {

 /**
 *      padding 
 */
 public static int sWidthPadding;

 public static int sHeightPadding;

 /**
 *       
 */
 private List<View> mViewList;

 /**
 *          
 */
 private OnPageSelectListener listener;

 /**
 *      
 */
 private Context mContext;

 public CoverFlowAdapter(List<View> mImageViewList, Context context) {
 this.mViewList = mImageViewList;
 mContext = context;
 //   padding 
 sWidthPadding = dp2px(24);
 sHeightPadding = dp2px(32);
 }

 @Override
 public void destroyItem(ViewGroup container, int position, Object object) {
 container.removeView(mViewList.get(position));
 }

 @Override
 public Object instantiateItem(ViewGroup container, int position) {
 View view = mViewList.get(position);
 container.addView(view);

 return view;
 }

 @Override
 public int getCount() {
 return mViewList == null ? 0 : mViewList.size();
 }

 @Override
 public boolean isViewFromObject(View view, Object object) {
 return view == object;
 }

 @Override
 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 //      ViewPager       
 if (mViewList.size() > 0 && position < mViewList.size()) {
 //           , 0    1  offset    ,padding    
 Log.i("info", "    padding");
 int outHeightPadding = (int) (positionOffset * sHeightPadding);
 int outWidthPadding = (int) (positionOffset * sWidthPadding);
 //  0     ,  position = 0,       ,  
 mViewList.get(position).setPadding(outWidthPadding, outHeightPadding, outWidthPadding, outHeightPadding);

 // position+1         ,    
 if (position < mViewList.size() - 1) {
 int inWidthPadding = (int) ((1 - positionOffset) * sWidthPadding);
 int inHeightPadding = (int) ((1 - positionOffset) * sHeightPadding);
 mViewList.get(position + 1).setPadding(inWidthPadding, inHeightPadding, inWidthPadding, inHeightPadding);
 }
 }

 }

 @Override
 public void onPageSelected(int position) {
 //        
 if (listener != null) {
 listener.select(position);
 }
 }

 @Override
 public void onPageScrollStateChanged(int state) {

 }

 /**
 *               
 *
 * @param listener
 */
 public void setOnPageSelectListener(OnPageSelectListener listener) {
 this.listener = listener;
 }


 /**
 * dp   px
 *
 * @param dp
 * @return
 */
 public int dp2px(int dp) {
 int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, mContext.getResources().getDisplayMetrics());

 return px;
 }

}
코드 변경 은 두 부분 으로 나 뉘 는데 PagerAdapter 가 이 루어 지고 미끄럼 감청 이 이 루어 집 니 다.Pager Adapter 의 실현 은 더 이상 말 하지 않 고 가장 기본 적 인 것 이다.미끄럼 감청 의 실현 에 중점 을 두다.
미끄럼 감청 에는 세 가지 반전 방법 이 있 습 니 다.그 중에서 onPage Scrolled(int position,float position Offset,int position Offset Pixels)는 ViewPager 의 미끄럼 오프셋 입 니 다.저 희 는 해당 요소 의 padding 값 을 다시 동적 으로 설정 하여 확대 축 소 를 실현 합 니 다.
onPageSelected()는 선택 한 반전 을 위해 사용자 정의 인터페이스 방식 으로 호출 자 에 게 되 돌려 줍 니 다.나중에 얘 기 할 게 요.
ViewPager 초기 화
어댑터 가 생 겼 으 니 자 연 스 럽 게 어댑터 부분 을 만 들 기 시작 합 니 다.

 /**
 *      
 */
 private void init() {
 //      ,     
 mAdapter = new CoverFlowAdapter(mViewList,getContext());
 //        
 mAdapter.setOnPageSelectListener(this);
 //      
 mViewPager.setAdapter(mAdapter);
 //        ,  adpter          ,        adpter
 mViewPager.addOnPageChangeListener(mAdapter);
 //     
 mViewPager.setOffscreenPageLimit(5);

 //          
 setOnTouchListener(new OnTouchListener() {
 @Override
 public boolean onTouch(View v, MotionEvent event) {
 //    ViewPager       
 return mViewPager.dispatchTouchEvent(event);
 }
 });
 }
주석 은 매우 상세 하 며,유일 하 게 설명 해 야 할 것 은 사건 의 배포 이다.
우리 의 ViewPager 의 크기 는 고정 되 어 있 고 중간 에 있 는 디 스 플레이 영역 만 있 습 니 다.그러면 손가락 이 두 측면 에서 미 끄 러 질 때 ViewPager 는 터치 사건 을 자 연 스 럽 게 받 아들 이지 못 합 니 다.바깥쪽 의 상대 적 인 레이아웃 을 설정 한 터치 사건 감청 을 통 해 터치 사건 을 ViewPager 에 전달 하고 ViewPager 이외 의 지역 을 실제 적 으로 미 끄 러 질 때 ViewPager 는 해당 하 는 미끄럼 을 실현 할 수 있 습 니 다.
데이터 원본 포장
어댑터 가 있 습 니 다.ViewPager 도 있 습 니 다.그러면 데이터 원본 만 남 았 습 니 다.
우 리 는 padding 값 설정 에 따라 이 루어 집 니 다.표시 할 컨트롤 에 대해 서 는 배경 이 확대 되 지 않 기 때문에 컨트롤 에 대해 외부 컨트롤 을 포장 합 니 다.이렇게 외부 컨트롤 의 padding 값 을 설정 하면 자 연 스 럽 게 표시 해 야 할 컨트롤 이 확대 되 고 축 소 됩 니 다.

 /**
 *        ,      
 * @param lists
 */
 public void setViewList(List<View> lists){
 if(lists==null){
 return;
 }
 mViewList.clear();
 for(View view:lists){

 FrameLayout layout = new FrameLayout(getContext());
 //   padding  ,    
 layout.setPadding(CoverFlowAdapter.sWidthPadding,CoverFlowAdapter.sHeightPadding,CoverFlowAdapter.sWidthPadding,CoverFlowAdapter.sHeightPadding);
 layout.addView(view);
 mViewList.add(layout);
 }
 //     
 mAdapter.notifyDataSetChanged();
 }
감청 반전 선택
우리 가 미 끄 러 질 때,미 끄 러 짐 에 따라 다른 데 이 터 를 표시 할 수 있 습 니 다.
미끄럼 감청 설정 을 통 해 onPageSelected 에 대해 층 층 의 인터페이스 리 셋 을 실현 합 니 다.
인터페이스의 정의 OnPageSelectListener

public interface OnPageSelectListener {

 void select(int position);
}
CoverFlowAdapter 에 리 셋 추가

 @Override
 public void onPageSelected(int position) {
 //        
 if (listener != null) {
 listener.select(position);
 }
 }

CoverFlowViewPager 에 리 셋 추가

 //      
 @Override
 public void select(int position) {
 if(listener!=null){
 listener.select(position);
 }
 }
이벤트 설정 클릭
데이터 원본 순환 에 대한 감청 을 직접 설정 하면 됩 니 다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기