編輯:關於Android編程
這個動畫效果是把Activity當做一張紙,正反面都有內容,且當點擊正反面的任何一個翻轉按鈕,Activity都會以屏幕中心為翻轉中心點(Z軸的翻轉中心點可以自由設定),進行旋轉。
效果如下圖所示(不懂上傳Gif圖,懂的人請告知哈):
這個動畫效果的思路是這樣的,首先兩個界面的布局都在同一個Layout文件中,因為這裡只有一個Activity,所以兩個界面的布局在同一個layout文件中就要有所設計。
在這裡,我使用的是FrameLayout作為父容器,包裹著兩個RelativeLayout子容器。當然其他布局也可以,只是在初始化時候必須先設置不可見的一面的布局android:visibility=“gone”
布局文件具體代碼如下:
<framelayout android:id="@+id/framelayout" android:layout_height="match_parent" android:layout_width="match_parent">
</framelayout>
注意,在兩個RelativeLayout中必須添加android:focusable=”true”
android:focusableInTouchMode=”true”這兩個屬性來隔離兩個界面的監聽事件,使得當前顯示的一面監聽有效,另一個不顯示的頁面的監聽無效,否則點擊事件會亂套。
接下來就是翻轉效果的設計,首先是確定翻轉中心點的位置,通過傳入X,Y,Z三個軸的中心點來確定。然後使用Camera根據傳入的翻轉度來進行翻轉,翻轉的類Rotate3D代碼如下:
/**
* 實現3D旋轉動畫核心類
* Created by PawN on 2015/6/12.
*/
public class Rotate3D extends Animation{
// 開始角度
private final float mFromDegrees;
// 結束角度
private final float mToDegrees;
// X軸中心點
private final float mCenterX;
// Y軸中心點
private final float mCenterY;
// Z軸中心點
private final float mDepthZ;
//是否需要扭曲
private final boolean mReverse;
//攝像頭
private Camera mCamera;
public Rotate3D(float fromDegrees, float toDegrees,
float centerX,float centerY,
float depthZ, boolean reverse) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mCenterX = centerX;
mCenterY = centerY;
mDepthZ = depthZ;
mReverse = reverse;
}
@Override
public void initialize(int width, int height,
int parentWidth,
int parentHeight) {
super.initialize(width, height, parentWidth,
parentHeight);
mCamera = new Camera();
}
@Override
protected void applyTransformation(float
interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
// 生成中間角度
float degrees = fromDegrees
+ ((mToDegrees - fromDegrees)
* interpolatedTime);
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
final Matrix matrix = t.getMatrix();//取得當前矩陣
camera.save();
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ *
interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f -
interpolatedTime));
}
camera.rotateY(degrees);//翻轉
camera.getMatrix(matrix);// 取得變換後的矩陣
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}
接下來就是在TestRotateActivity中的使用了,整個翻轉過程分為兩個階段操作,第一階段是從當前頁面翻轉到整個Activity垂直於手機屏幕(到這個時刻,正反兩面都是不可見的)。第二階段是從當前的整個Activity垂直於手機屏幕(到這個時刻,正反兩面都是不可見的)狀態翻轉到第二個頁面顯示在手機屏幕上。具體流程如下圖所示:
TestRotateActivity的具體代碼如下:
public class TestRotateActivity extends Activity{
//布局1
private TextView tvOne;
private Button btnRotateNext;
//布局2
private TextView tvTwo;
private Button btnRotateBack;
//頁面翻轉容器FrameLayout
private FrameLayout flContainer;
//布局1界面RelativeLayout
private RelativeLayout relativeLayout1;
//布局2界面RelativeLayout
private RelativeLayout relativeLayout2;
//初始化界面索引(1位布局1,2位布局2)
private int index = 1;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rotate);
initView();
registerClickListener();
}
private void initView(){
tvOne = (TextView)findViewById(R.id.tv_one);
tvTwo = (TextView)findViewById(R.id.tv_two);
flContainer =
(FrameLayout)findViewById(R.id.frame_layout);
relativeLayout1 = (RelativeLayout)findViewById(R.id.relative_layout_one);
relativeLayout2 = (RelativeLayout)findViewById(R.id.relative_layout_two);
btnRotateNext = (Button) findViewById(R.id.rotate_next);
btnRotateBack = (Button)findViewById(R.id.rotate_back);
}
private void registerClickListener(){
tvOne.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(TestRotateActivity.this,"one",Toast.LENGTH_SHORT).show();;
}
});
tvTwo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(TestRotateActivity.this,"two",Toast.LENGTH_SHORT).show();;
}
});
btnRotateNext.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(index==1){
//第一階段翻轉
applyRotation(1,0,90);
index =0;
}else{
//第一階段翻轉
applyRotation(0,0,-90);
index = 1;
}
}
});
btnRotateBack.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(index==1){
//第一階段翻轉
applyRotation(1,0,90);
index =0;
}else{
//第一階段翻轉
applyRotation(0,0,-90);
index = 1;
}
}
});
}
/**
* 執行翻轉第一階段翻轉動畫
* @param tag view索引
* @param start 起始角度
* @param end 結束角度
*/
private void applyRotation(int tag, float start, float end) {
// 得到中心點(以中心翻轉)
//X軸中心點
final float centerX = flContainer.getWidth() / 2.0f;
//Y軸中心點
final float centerY = flContainer.getHeight() / 2.0f;
//Z軸中心點
final float depthZ = 500.0f;
// 根據參數創建一個新的三維動畫,並且監聽觸發下一個動畫
final Rotate3D rotation = new Rotate3D(start, end, centerX, centerY,depthZ, true);
rotation.setDuration(300);//設置動畫持續時間
rotation.setInterpolator(new AccelerateInterpolator());//設置動畫變化速度
rotation.setAnimationListener(new DisplayNextView(tag));//設置第一階段動畫監聽器
flContainer.startAnimation(rotation);
}
/**
* 第一階段動畫監聽器
*
*/
private final class DisplayNextView implements Animation.AnimationListener {
private final int tag;
private DisplayNextView(int tag) {
this.tag = tag;
}
public void onAnimationStart(Animation animation) {
}
public void onAnimationEnd(Animation animation) {
//第一階段動畫結束時,也就是整個Activity垂直於手機屏幕,
//執行第二階段動畫
flContainer.post(new SwapViews(tag));
//調整兩個界面各自的visibility
adjustVisiable();
}
public void onAnimationRepeat(Animation animation) {
}
}
/**
* 執行翻轉第二個階段動畫
*
*/
private final class SwapViews implements Runnable {
private final int tag;
public SwapViews(int position) {
tag = position;
}
public void run() {
if (tag == 0) {
//首頁頁面以90~0度翻轉
showView(relativeLayout1, relativeLayout2, 90, 0);
} else if (tag == 1) {
//音樂頁面以-90~0度翻轉
showView(relativeLayout2, relativeLayout1, -90, 0);
}
}
}
/**
* 顯示第二個視圖動畫
* @param showView 要顯示的視圖
* @param hiddenView 要隱藏的視圖
* @param startDegree 開始角度
* @param endDegree 目標角度
*/
private void showView(RelativeLayout showView, RelativeLayout hiddenView, int startDegree, int endDegree) {
//同樣以中心點進行翻轉
float centerX = showView.getWidth() / 2.0f;
float centerY = showView.getHeight() / 2.0f;
float centerZ = 500.0f;
if (centerX == 0 || centerY == 0) {
//調用該方法getMeasuredWidth(),必須先執行measure()方法,否則會出異常。
showView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
//獲取該view在父容器裡面占的大小
centerX = showView.getMeasuredWidth() / 2.0f;
centerY = showView.getMeasuredHeight() / 2.0f;
}
// Log.e("centerX",centerX + "");
// Log.e("centerY",centerY + "");
hiddenView.setVisibility(View.GONE);
showView.setVisibility(View.VISIBLE);
Rotate3D rotation = new Rotate3D(startDegree, endDegree, centerX, centerY, centerZ, false);
rotation.setDuration(300);//設置動畫持續時間
rotation.setInterpolator(new DecelerateInterpolator());//設置動畫變化速度
flContainer.startAnimation(rotation);
}
/**
* 兩個布局的visibility調節
*/
private void adjustVisiable(){
if(tvOne.getVisibility() == View.VISIBLE){
tvOne.setVisibility(View.GONE);
}else {
tvOne.setVisibility(View.VISIBLE);
}
if(tvTwo.getVisibility() == View.VISIBLE){
tvTwo.setVisibility(View.GONE);
}else {
tvTwo.setVisibility(View.VISIBLE);
}
}
}
這樣就可以實現本章的Activity翻轉動畫效果了~有哪裡不妥的地方歡迎大家指正~
1. 什麼是服務: Android中的四大組件, 是一個可以長時間在後台運行的不提供用戶界面的一個類. 2.服務的特性: 服務一旦被啟動無論啟動它的界面還存不存
最近做了一個百度地圖離線地圖的功能,雖然功能實現了,但過程中也碰到了一些問題。首先,看看效果圖吧。 1、離線地圖相關APIAPI地址:http://wiki.lbsyu
(一)概述: (二)RadioButton的基本用法與事件處理: 效果圖: 實現代碼:xml文件M
當我們用XML中寫完一個布局文件,想在某個Activity中顯示的時候,往往通過setContentView方法加載。在上一篇文章中,我們知道如何通過LayoutInfl