Android:移出屏幕时视图中断

时间:2013-08-26 10:39:25

标签: android android-layout android-custom-view

我正在创建一个自定义视图,可以在屏幕上左右移动。我在相对布局中添加此视图。以下是我的自定义视图的一些代码: SubtopicsView类的父视图:

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.RelativeLayout;

import com.example.androidstackedview.R;
import com.example.androidstackedview.views.BaseView.ViewState;

public class StackedView extends RelativeLayout {

    Context context;
    View dashboardView;
    TopicsView topicsView;
    SubTopicsView subtopicsView;
    DetailsView detailsView;
    float widthFactor = 10;
    public static int screenHeight;
    public static int screenWidth;
    public static float xDocked = 0;
    public StackedView(Context context) {
        super(context);
        this.context = context;
        init();
    }

    public StackedView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        init();
    }

    private void init() {
        initScreenDimenstions();
    }

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

        int orientation = context.getResources().getConfiguration().orientation;

        initColumnViews();
        if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
            topicsView.layout(dashboardView.getWidth(), 0, (int) (dashboardView.getWidth()+screenWidth/2 - screenWidth/2 * .30f), screenHeight);
        }
        else {
            topicsView.layout(dashboardView.getWidth(), 0, (int) (dashboardView.getWidth()+screenWidth/2), screenHeight);
        }
        topicsView.setxNormal(dashboardView.getWidth());
        topicsView.setxDocked(xDocked);
        if(!topicsView.isAnimating) {
            topicsView.changeState(topicsView.mViewState, false);
        }

        if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
            subtopicsView.layout((int) (topicsView.getLeft()+topicsView.getWidth()), 0, (topicsView.getLeft()+topicsView.getWidth()) + topicsView.getWidth(), screenHeight);
            subtopicsView.setxNormal(topicsView.getLeft()+topicsView.getWidth());
        }
        else {
            subtopicsView.layout((int) (screenWidth/2), 0, screenWidth, screenHeight);
            subtopicsView.setxNormal(screenWidth/2);
        }

        subtopicsView.setxDocked(xDocked);
        subtopicsView.changeState(subtopicsView.mViewState, false);

        //      detailsView.layout((int) (xDocked), 0, screenWidth, screenHeight);
        //      detailsView.setxNormal(xDocked);
        //      detailsView.setxDocked(xDocked);
        //      detailsView.changeState(detailsView.mViewState, false);
        if(orientation == Configuration.ORIENTATION_PORTRAIT) {
            detailsView.layout((int) (xDocked), 0, screenWidth, screenHeight);
            detailsView.setxNormal(xDocked + topicsView.getWidth());
            detailsView.setxDocked(xDocked);
            detailsView.changeState(ViewState.DOCKED, false);
        }
        else if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
            detailsView.layout((int) (xDocked + topicsView.getWidth()/2), 0, screenWidth, screenHeight);
            detailsView.setxNormal(xDocked + topicsView.getWidth());
            detailsView.setxDocked(xDocked + topicsView.getWidth()/2);
            detailsView.changeState(ViewState.DOCKED, false);
        }



    }

    public void initColumnViews() {
        if(dashboardView == null) {
            dashboardView = findViewWithTag("dashboard");

        }
        if(dashboardView != null) {
            View v = dashboardView.findViewById(R.id.testimg);
            if(v != null) {
                xDocked = v.getLeft() + v.getWidth();
            }
        }
        if(topicsView == null) {
            topicsView = (TopicsView) findViewWithTag("topics");
        }
        if(subtopicsView == null) {
            subtopicsView = (SubTopicsView) findViewWithTag("subtopics");
        }
        if(detailsView == null) {
            detailsView = (DetailsView) findViewWithTag("details");
        }
    }

    private void initScreenDimenstions() {
        DisplayMetrics displaymetrics = new DisplayMetrics();
        ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        screenHeight = displaymetrics.heightPixels;
        screenWidth = displaymetrics.widthPixels;

    }

    public void resetTo1stPhase() {

        topicsView.setVisibility(View.VISIBLE);
        //      if(topicsView.mViewState == ViewState.DOCKED) {
        //          topicsView.changeState(ViewState.NORMAL, true);
        //      } else {
        topicsView.changeState(ViewState.NORMAL, false);
        //      }

        subtopicsView.setVisibility(View.GONE);
        subtopicsView.changeState(ViewState.NORMAL, false);

        detailsView.setVisibility(View.GONE);
        detailsView.changeState(ViewState.NORMAL, false);

    }

    public void resetTo2ndPhase() {
        topicsView.setVisibility(View.VISIBLE);
        int orientation = context.getResources().getConfiguration().orientation;
        if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
            topicsView.changeState(ViewState.NORMAL, false);
        }
        else {
            if(topicsView.mViewState == ViewState.DOCKED) {
                topicsView.changeState(ViewState.DOCKED, false);
            } else {
                topicsView.changeState(ViewState.DOCKED, true);
            }
        }

        subtopicsView.setVisibility(View.VISIBLE);
        subtopicsView.changeState(ViewState.NORMAL, false);

        detailsView.setVisibility(View.GONE);
        detailsView.changeState(ViewState.NORMAL, false);
    }

    public void resetTo3rdPhase() {
        // TODO Auto-generated method stub
        subtopicsView.setVisibility(View.VISIBLE);
        subtopicsView.changeState(ViewState.DOCKED, false);

        detailsView.setVisibility(View.VISIBLE);
        detailsView.changeState(ViewState.NORMAL, false);
    }

    public void loadFragmentInTopicsFrame(Fragment f) {
        initColumnViews();
        FragmentManager fm = ((FragmentActivity)context).getSupportFragmentManager();
        FragmentTransaction t = fm.beginTransaction();
        t.replace(topicsView.findViewById(R.id.fr1).getId(), f);
        t.commit();
        resetTo1stPhase();
    }

    public void loadFragmentInSubtopicsFrame(Fragment f) {
        initColumnViews();
        FragmentManager fm = ((FragmentActivity)context).getSupportFragmentManager();
        FragmentTransaction t = fm.beginTransaction();
        t.replace(subtopicsView.findViewById(R.id.fr2).getId(), f);
        t.commit();
        resetTo2ndPhase();
    }

    public void loadFragmentInDetailsFrame(Fragment f) {
        initColumnViews();
        FragmentManager fm = ((FragmentActivity)context).getSupportFragmentManager();
        FragmentTransaction t = fm.beginTransaction();
        t.replace(detailsView.findViewById(R.id.fr3).getId(), f);
        t.commit();
        resetTo3rdPhase();
    }
}

........... 这是BaseView,即Subtopics类的父级:

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.RelativeLayout;

public class BaseView extends RelativeLayout {

    float xNormal;
    float xDocked;
    float px;
    boolean isAnimating = false;
    public ViewState mViewState = ViewState.NORMAL;
    final float TOUCH_FACTOR = 0.60f;
    final long ANIMATION_DURATION = 100;


    public BaseView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    public BaseView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }

    public BaseView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        if(isAnimating) {
            return true;
        }
        if(mViewState == ViewState.DOCKED) {
            return true;
        }
        if(action == MotionEvent.ACTION_DOWN) {
            px = event.getX();
        }
        else if(action == MotionEvent.ACTION_MOVE) {
            float newX = event.getX();
            float dx = newX - px;
            if(Math.abs(dx) > 0) {
                float value = getLeft()+(dx*TOUCH_FACTOR);
                if(value < 0) {
                    value = 0;
                }
                layout((int)(value), 0, (int)(value+getWidth()), getHeight());
            }

            px = newX;

        }
        else if(action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
            float toX = 0;
            if(mViewState == ViewState.NORMAL) {
                toX =xNormal-getLeft();
            }
            else if(mViewState == ViewState.DOCKED) {
                toX = xDocked-getLeft();
            }
            StackedAnimation anim = new StackedAnimation(this, 0, toX, ANIMATION_DURATION);
            anim.setListener(new OnHAnimationListener() {

                @Override
                public void onStart() {
                    isAnimating = true;
                }

                @Override
                public void onEnd() {
                    isAnimating = false;
                    changeState(mViewState, false);
                }
            });
            anim.start();
        }
        return true;
    }

    public void changeState(ViewState state, boolean animate) {
        mViewState = state;
        if(mViewState == ViewState.NORMAL) {
            if(animate) {
                StackedAnimation anim = new StackedAnimation(this, getLeft(), xNormal, ANIMATION_DURATION);
                anim.setListener(new OnHAnimationListener() {

                    @Override
                    public void onStart() {
                        // TODO Auto-generated method stub
                        isAnimating = true;
                    }

                    @Override
                    public void onEnd() {
                        // TODO Auto-generated method stub
                        isAnimating = false;
                        layout((int) xNormal, 0, (int) (xNormal+getWidth()), getHeight());
                    }
                });
                anim.start();
            } else {
                layout((int) xNormal, 0, (int) (xNormal+getWidth()), getHeight());
            }

        }
        else if(mViewState == ViewState.DOCKED) {
            if(animate) {
                StackedAnimation anim = new StackedAnimation(this, getLeft(), xDocked, ANIMATION_DURATION);
                anim.setListener(new OnHAnimationListener() {

                    @Override
                    public void onStart() {
                        // TODO Auto-generated method stub
                        isAnimating = true;
                    }

                    @Override
                    public void onEnd() {
                        // TODO Auto-generated method stub
                        isAnimating = false;
                        layout((int) xDocked, 0, (int) (xDocked+getWidth()), getHeight());
                    }
                });
                anim.start();
            } else {
                layout((int) xDocked, 0, (int) (xDocked+getWidth()), getHeight());
            }
        }
    }

    public float getxNormal() {
        return xNormal;
    }

    public void setxNormal(float xNormal) {
        this.xNormal = xNormal;
    }

    public float getxDocked() {
        return xDocked;
    }

    public void setxDocked(float xLocked) {
        this.xDocked = xLocked;
    }

    public boolean isAnimating() {
        return isAnimating;
    }

    public void setAnimating(boolean isAnimating) {
        this.isAnimating = isAnimating;
    }

    public enum ViewState {
        NORMAL,
        DOCKED,
        NONE;
    }

    public enum ColumnType {
        TOPIC,
        SUBTOPIC,
        DETAILS;
    }




}

...... 这是Subtopics类:

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.FrameLayout;

public class SubTopicsView extends BaseView {

    StackedView stackView;
    Context context;
    private int screenHeight;
    private int screenWidth;

    public SubTopicsView(Context context) {
        super(context);
        this.context = context;
        // TODO Auto-generated constructor stub
        setBackgroundColor(0xFF888888);
        initScreenDimenstions();
    }

    public SubTopicsView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
        // TODO Auto-generated constructor stub
        setBackgroundColor(0xFF888888);
        initScreenDimenstions();
    }

    public SubTopicsView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.context = context;
        // TODO Auto-generated constructor stub
        setBackgroundColor(0xFF888888);
        initScreenDimenstions();
    }

    private void initScreenDimenstions() {
        DisplayMetrics displaymetrics = new DisplayMetrics();
        ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        screenHeight = displaymetrics.heightPixels;
        screenWidth = displaymetrics.widthPixels;

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // TODO Auto-generated method stub
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(findViewById(R.id.parent) != null) {
            int orientation = context.getResources().getConfiguration().orientation;
            FrameLayout.LayoutParams params;
            if(orientation == Configuration.ORIENTATION_LANDSCAPE) {
                params = new FrameLayout.LayoutParams((int) (screenWidth/2 - screenWidth/2 * .30f), screenHeight);
            }
            else {
                params = new FrameLayout.LayoutParams((int) (screenWidth/2), screenHeight);
            }
            findViewById(R.id.parent).setLayoutParams(params);

        }
    }

}

视图在触摸时正常移动,但当视图从左侧或右侧开始离开屏幕时,它开始从另一侧切断,如下面的屏幕截图所示。 enter image description here 知道为什么视图表现得像这样吗?

0 个答案:

没有答案