package com.aincc.lib.ui.widget.flip; import java.util.LinkedList; import android.content.Context; import android.graphics.PixelFormat; import android.opengl.GLSurfaceView; import android.os.Handler; import android.os.Message; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import com.aincc.lib.util.Logger; /* Copyright 2012 Aphid Mobile Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // TODO: ViewPager 와 PagerAdapter 를 참고하여 만들어봅시다. // 사용법 // 1. FlipViewGroup 을 생성하여 레이아웃에 붙이고, // 2. FlipAdapter 를 생성하고, 각 페이지의 레이아웃을 등록하고, // 3. FlipViewGroup 에 어댑터를 연결하고, // 4. FlipAdapter 를 갱신하면 화면을 표시하도록 한다. // 5. FlipViewGroup 에서 터치를 처리하여 페이지 넘김을 발생시키고, // 넘김정보를 FlipAdapter 콜백으로 호출시킨다. // 그럼 getView 처럼 현재 표시되는 페이지를 처리하는 루틴과 // front/back 페이지를 처리하는 루틴과 // 표시되었다가 해제되는 페이지를 처리하는 루틴에 대한 콜백을 호출하면 사용자가 적절하게 처리한다. // FlipViewGroup 에서는 그래피컬한 처리만 담당하므로, // 실질적인 클릭연결등은 콜백 getView 에서 처리하도록 유도한다. /** * * <h3><b>FlipViewGroup</b></h3></br> * * @author aincc@barusoft.com * @version 1.0.0 * @since 1.0.0 */ public class FlipViewGroup extends ViewGroup { private static final int MSG_SURFACE_CREATED = 1; /** * 플립뷰 리스트 */ private LinkedList<View> flipViews = new LinkedList<View>(); /** * 핸들러 */ private Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { if (msg.what == MSG_SURFACE_CREATED) { width = 0; height = 0; requestLayout(); return true; } return false; } }); /** * 어댑터 */ private FlipAdapter adapter; /** * Surface 뷰 */ private GLSurfaceView surfaceView; /** * 렌더러 */ private FlipRenderer renderer; /** * 가로길이 */ private int width; /** * 세로길이 */ private int height; /** * 플립핑 플래그 */ private boolean flipping = false; /** * * @since 1.0.0 * @param context */ public FlipViewGroup(Context context) { super(context); setupSurfaceView(); } /** * Surface 뷰 초기화 * * @since 1.0.0 */ private void setupSurfaceView() { surfaceView = new GLSurfaceView(getContext()); renderer = new FlipRenderer(this); surfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0); surfaceView.setZOrderOnTop(true); surfaceView.setRenderer(renderer); // surfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT); // 레이어 투과 효과 surfaceView.getHolder().setFormat(PixelFormat.OPAQUE); surfaceView.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); addView(surfaceView); } /** * @return the SurfaceView */ public GLSurfaceView getSurfaceView() { return surfaceView; } /** * @return the Renderer */ public FlipRenderer getRenderer() { return renderer; } /** * @return the Adapter */ public FlipAdapter getAdapter() { return adapter; } /** * @param adapter */ public void setAdapter(FlipAdapter adapter) { this.adapter = adapter; } public void addFlipView(View v) { // TODO: 최대 3장의 뷰만 유지하도록 inflate 된 뷰를 받지말고, // 뷰를 만들수있는 플립객체를 관리하는게 어떨까? flipViews.add(v); addView(v); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { Logger.i("onLayout: " + l + ", " + t + ", " + r + ", " + b + "; child " + flipViews.size()); // TODO: 최대 3장의 뷰만 유지하도록 for (View child : flipViews) child.layout(0, 0, r - l, b - t); if (changed || width == 0) { int w = r - l; int h = b - t; surfaceView.layout(0, 0, w, h); if (width != w || height != h) { width = w; height = h; if (flipping && flipViews.size() >= 2) { View frontView = flipViews.get(flipViews.size() - 1); View backView = flipViews.get(flipViews.size() - 2); renderer.updateTexture(frontView, backView); frontView.setVisibility(View.INVISIBLE); backView.setVisibility(View.INVISIBLE); } } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // Logger.i( String.format("onMeasure: %d, %d, ; child %d", widthMeasureSpec, heightMeasureSpec, flipViews.size())); super.onMeasure(widthMeasureSpec, heightMeasureSpec); // TODO: 최대 3장의 뷰만 유지하도록 for (View child : flipViews) child.measure(widthMeasureSpec, heightMeasureSpec); } public void startFlipping() { flipping = true; } public void onResume() { surfaceView.onResume(); } public void onPause() { surfaceView.onPause(); } public void reloadTexture() { handler.sendMessage(Message.obtain(handler, MSG_SURFACE_CREATED)); } @Override public boolean onTouchEvent(MotionEvent event) { return renderer.getCards().handleTouchEvent(event); } }