我正在创建一个自定义视图,可以在屏幕上左右移动。我在相对布局中添加此视图。以下是我的自定义视图的一些代码: 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);
}
}
}
视图在触摸时正常移动,但当视图从左侧或右侧开始离开屏幕时,它开始从另一侧切断,如下面的屏幕截图所示。 知道为什么视图表现得像这样吗?