基于Android实现转盘按钮代码

先给大家展示下效果图:

package com.lixu.circlemenu;
 import android.app.Activity;
 import android.os.Bundle;
 import android.view.View;
 import android.widget.TextView;
 import android.widget.Toast;
 import com.lixu.circlemenu.view.CircleImageView;
 import com.lixu.circlemenu.view.CircleLayout;
 import com.lixu.circlemenu.view.CircleLayout.OnItemClickListener;
 import com.lixu.circlemenu.view.CircleLayout.OnItemSelectedListener;
 import com.szugyi.circlemenu.R;
 public class MainActivity extends Activity implements OnItemSelectedListener, OnItemClickListener{
   private  TextView selectedTextView;
   @Override
   protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     setContentView(R.layout.activity_main);
     CircleLayout circleMenu = (CircleLayout)findViewById(R.id.main_circle_layout);
     circleMenu.setOnItemSelectedListener(this);
     circleMenu.setOnItemClickListener(this);
     //这个TextView仅仅作为演示转盘按钮以何为默认的选中项,
     //默认的最底部的那一条被选中,然后显示到该TextView中。
     selectedTextView = (TextView)findViewById(R.id.main_selected_textView);
     selectedTextView.setText(((CircleImageView)circleMenu.getSelectedItem()).getName());
   }
   //圆盘转动到底部,则认为该条目被选中
   @Override
   public void onItemSelected(View view, int position, long id, String name) {
     selectedTextView.setText(name);
   }
   //选择了转盘中的某一条。
   @Override
   public void onItemClick(View view, int position, long id, String name) {
     Toast.makeText(getApplicationContext(), getResources().getString(R.string.start_app) + " " + name, Toast.LENGTH_SHORT).show();
   }
 }

引用两个开源类:

 package com.lixu.circlemenu.view;
 /*
  * Copyright Csaba Szugyiczki
  *
  * Licensed under the Apache License, Version . (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-.
 *
 * 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.
 */
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
 import android.widget.ImageView;
 import com.szugyi.circlemenu.R;
 /**
 *
 * @author Szugyi
 * Custom ImageView for the CircleLayout class.
 * Makes it possible for the image to have an angle, position and a name.
 * Angle is used for the positioning in the circle menu.
 */
 public class CircleImageView extends ImageView {
   private float angle = ;
   private int position = ;
   private String name;
   public float getAngle() {
     return angle;
   }
   public void setAngle(float angle) {
     this.angle = angle;
   }
   public int getPosition() {
     return position;
   }
   public void setPosition(int position) {
     this.position = position;
   }
   public String getName(){
     return name;
   }
   public void setName(String name){
     this.name = name;
   }
   /**
   * @param context
   */
   public CircleImageView(Context context) {
     this(context, null);
   }
   /**
   * @param context
   * @param attrs
   */
   public CircleImageView(Context context, AttributeSet attrs) {
     this(context, attrs, );
   }
   /**
   * @param context
   * @param attrs
   * @param defStyle
   */
   public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
     super(context, attrs, defStyle);
     if (attrs != null) {
       TypedArray a = getContext().obtainStyledAttributes(attrs,
           R.styleable.CircleImageView);
       name = a.getString(R.styleable.CircleImageView_name);
     }
   }
 }

  package com.lixu.circlemenu.view;
  import com.szugyi.circlemenu.R;
  /*
  * Copyright Csaba Szugyiczki
  *
  * Licensed under the Apache License, Version . (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-.
  *
  * 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.
  */
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.util.AttributeSet;
 import android.view.GestureDetector;
 import android.view.GestureDetector.SimpleOnGestureListener;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 /**
  *
  * @author Szugyi
  * Creates a rotatable circle menu which can be parameterized by custom attributes.
  * Handles touches and gestures to make the menu rotatable, and to make the
  * menu items selectable and clickable.
  *
  */
 public class CircleLayout extends ViewGroup {
   // Event listeners
   private OnItemClickListener mOnItemClickListener = null;
   private OnItemSelectedListener mOnItemSelectedListener = null;
   private OnCenterClickListener mOnCenterClickListener = null;
   // Background image
   private Bitmap imageOriginal, imageScaled;
   private Matrix matrix;
   private int mTappedViewsPostition = -;
   private View mTappedView = null;
   private int selected = ;
   // Child sizes
   private int mMaxChildWidth = ;
   private int mMaxChildHeight = ;
   private int childWidth = ;
   private int childHeight = ;
   // Sizes of the ViewGroup
   private int circleWidth, circleHeight;
   private int radius = ;
   // Touch detection
   private GestureDetector mGestureDetector;
   // needed for detecting the inversed rotations
   private boolean[] quadrantTouched;
   // Settings of the ViewGroup
   private boolean allowRotating = true;
   private float angle = ;
   private float firstChildPos = ;
   private boolean rotateToCenter = true;
   private boolean isRotating = true;
   /**
    * @param context
    */
   public CircleLayout(Context context) {
     this(context, null);
   }
   /**
    * @param context
    * @param attrs
    */
   public CircleLayout(Context context, AttributeSet attrs) {
     this(context, attrs, );
   }
   /**
    * @param context
    * @param attrs
    * @param defStyle
    */
   public CircleLayout(Context context, AttributeSet attrs, int defStyle) {
     super(context, attrs, defStyle);
     init(attrs);
   }
   /**
   * Initializes the ViewGroup and modifies it's default behavior by the passed attributes
   * @param attrs  the attributes used to modify default settings
   */
   protected void init(AttributeSet attrs) {
     mGestureDetector = new GestureDetector(getContext(),
         new MyGestureListener());
     quadrantTouched = new boolean[] { false, false, false, false, false };
     if (attrs != null) {
       TypedArray a = getContext().obtainStyledAttributes(attrs,
           R.styleable.Circle);
       // The angle where the first menu item will be drawn
       angle = a.getInt(R.styleable.Circle_firstChildPosition, );
       firstChildPos = angle;
       rotateToCenter = a.getBoolean(R.styleable.Circle_rotateToCenter,
           true);
       isRotating = a.getBoolean(R.styleable.Circle_isRotating, true);
       // If the menu is not rotating then it does not have to be centered
       // since it cannot be even moved
       if (!isRotating) {
         rotateToCenter = false;
       }
       if (imageOriginal == null) {
         int picId = a.getResourceId(
             R.styleable.Circle_circleBackground, -);
         // If a background image was set as an attribute,
         // retrieve the image
         if (picId != -) {
           imageOriginal = BitmapFactory.decodeResource(
               getResources(), picId);
         }
       }
       a.recycle();
       // initialize the matrix only once
       if (matrix == null) {
         matrix = new Matrix();
       } else {
         // not needed, you can also post the matrix immediately to
         // restore the old state
         matrix.reset();
       }
       // Needed for the ViewGroup to be drawn
       setWillNotDraw(false);
     }
   }
   /**
   * Returns the currently selected menu
   * @return the view which is currently the closest to the start position
   */
   public View getSelectedItem() {
     return (selected >= ) ? getChildAt(selected) : null;
   }
   @Override
   protected void onDraw(Canvas canvas) {
     // the sizes of the ViewGroup
     circleHeight = getHeight();
     circleWidth = getWidth();
     if (imageOriginal != null) {
       // Scaling the size of the background image
       if (imageScaled == null) {
         matrix = new Matrix();
         float sx = (((radius + childWidth / ) * ) / (float) imageOriginal
             .getWidth());
         float sy = (((radius + childWidth / ) * ) / (float) imageOriginal
             .getHeight());
         matrix.postScale(sx, sy);
         imageScaled = Bitmap.createBitmap(imageOriginal, , ,
             imageOriginal.getWidth(), imageOriginal.getHeight(),
             matrix, false);
       }
       if (imageScaled != null) {
         // Move the background to the center
         int cx = (circleWidth - imageScaled.getWidth()) / ;
         int cy = (circleHeight - imageScaled.getHeight()) / ;
         Canvas g = canvas;
         canvas.rotate(, circleWidth / , circleHeight / );
         g.drawBitmap(imageScaled, cx, cy, null);
       }
     }
   }
   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     mMaxChildWidth = ;
     mMaxChildHeight = ;
     // Measure once to find the maximum child size.
     int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
         MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST);
     int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
         MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST);
     final int count = getChildCount();
     for (int i = ; i < count; i++) {
       final View child = getChildAt(i);
       if (child.getVisibility() == GONE) {
         continue;
       }
       child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
       mMaxChildWidth = Math.max(mMaxChildWidth, child.getMeasuredWidth());
       mMaxChildHeight = Math.max(mMaxChildHeight,
           child.getMeasuredHeight());
     }
     // Measure again for each child to be exactly the same size.
     childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxChildWidth,
         MeasureSpec.EXACTLY);
     childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxChildHeight,
         MeasureSpec.EXACTLY);
     for (int i = ; i < count; i++) {
       final View child = getChildAt(i);
       if (child.getVisibility() == GONE) {
         continue;
       }
       child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
     }
     setMeasuredDimension(resolveSize(mMaxChildWidth, widthMeasureSpec),
         resolveSize(mMaxChildHeight, heightMeasureSpec));
   }
   @Override
   protected void onLayout(boolean changed, int l, int t, int r, int b) {
     int layoutWidth = r - l;
     int layoutHeight = b - t;
     // Laying out the child views
     final int childCount = getChildCount();
     int left, top;
     radius = (layoutWidth <= layoutHeight) ? layoutWidth /
         : layoutHeight / ;
     childWidth = (int) (radius / .);
     childHeight = (int) (radius / .);
     float angleDelay = / getChildCount();
     for (int i = ; i < childCount; i++) {
       final CircleImageView child = (CircleImageView) getChildAt(i);
       if (child.getVisibility() == GONE) {
         continue;
       }
       if (angle > ) {
         angle -= ;
       } else {
         if (angle < ) {
           angle += ;
         }
       }
       child.setAngle(angle);
       child.setPosition(i);
       left = Math
           .round((float) (((layoutWidth / ) - childWidth / ) + radius
               * Math.cos(Math.toRadians(angle))));
       top = Math
           .round((float) (((layoutHeight / ) - childHeight / ) + radius
               * Math.sin(Math.toRadians(angle))));
       child.layout(left, top, left + childWidth, top + childHeight);
       angle += angleDelay;
     }
   }
   /**
   * Rotate the buttons.
   *
   * @param degrees The degrees, the menu items should get rotated.
   */
   private void rotateButtons(float degrees) {
     int left, top, childCount = getChildCount();
     float angleDelay = / childCount;
     angle += degrees;
     if (angle > ) {
       angle -= ;
     } else {
       if (angle < ) {
         angle += ;
       }
     }
     for (int i = ; i < childCount; i++) {
       if (angle > ) {
         angle -= ;
       } else {
         if (angle < ) {
           angle += ;
         }
       }
       final CircleImageView child = (CircleImageView) getChildAt(i);
       if (child.getVisibility() == GONE) {
         continue;
       }
       left = Math
           .round((float) (((circleWidth / ) - childWidth / ) + radius
               * Math.cos(Math.toRadians(angle))));
       top = Math
           .round((float) (((circleHeight / ) - childHeight / ) + radius
               * Math.sin(Math.toRadians(angle))));
       child.setAngle(angle);
       if (Math.abs(angle - firstChildPos) < (angleDelay / )
           && selected != child.getPosition()) {
         selected = child.getPosition();
         if (mOnItemSelectedListener != null && rotateToCenter) {
           mOnItemSelectedListener.onItemSelected(child, selected,
               child.getId(), child.getName());
         }
       }
       child.layout(left, top, left + childWidth, top + childHeight);
       angle += angleDelay;
     }
   }
   /**
   * @return The angle of the unit circle with the image view's center
   */
   private double getAngle(double xTouch, double yTouch) {
     double x = xTouch - (circleWidth / d);
     double y = circleHeight - yTouch - (circleHeight / d);
     switch (getQuadrant(x, y)) {
     case :
       return Math.asin(y / Math.hypot(x, y)) * / Math.PI;
     case :
     case :
       return - (Math.asin(y / Math.hypot(x, y)) * / Math.PI);
     case :
       return + Math.asin(y / Math.hypot(x, y)) * / Math.PI;
     default:
       // ignore, does not happen
       return ;
     }
   }
   /**
   * @return The selected quadrant.
   */
   private static int getQuadrant(double x, double y) {
     if (x >= ) {
       return y >= ? : ;
     } else {
       return y >= ? : ;
     }
   }
   private double startAngle;
   @Override
   public boolean onTouchEvent(MotionEvent event) {
     if (isEnabled()) {
       if (isRotating) {
         switch (event.getAction()) {
         case MotionEvent.ACTION_DOWN:
           // reset the touched quadrants
           for (int i = ; i < quadrantTouched.length; i++) {
             quadrantTouched[i] = false;
           }
           allowRotating = false;
           startAngle = getAngle(event.getX(), event.getY());
           break;
         case MotionEvent.ACTION_MOVE:
           double currentAngle = getAngle(event.getX(), event.getY());
           rotateButtons((float) (startAngle - currentAngle));
           startAngle = currentAngle;
           break;
         case MotionEvent.ACTION_UP:
           allowRotating = true;
           rotateViewToCenter((CircleImageView) getChildAt(selected),
               false);
           break;
         }
       }
       // set the touched quadrant to true
       quadrantTouched[getQuadrant(event.getX() - (circleWidth / ),
           circleHeight - event.getY() - (circleHeight / ))] = true;
       mGestureDetector.onTouchEvent(event);
       return true;
     }
     return false;
   }
   private class MyGestureListener extends SimpleOnGestureListener {
     @Override
     public boolean onFling(MotionEvent e, MotionEvent e, float velocityX,
         float velocityY) {
       if (!isRotating) {
         return false;
       }
       // get the quadrant of the start and the end of the fling
       int q = getQuadrant(e.getX() - (circleWidth / ), circleHeight
           - e.getY() - (circleHeight / ));
       int q = getQuadrant(e.getX() - (circleWidth / ), circleHeight
           - e.getY() - (circleHeight / ));
       // the inversed rotations
       if ((q == && q == && Math.abs(velocityX) < Math
           .abs(velocityY))
           || (q == && q == )
           || (q == && q == )
           || (q == && q == && Math.abs(velocityX) > Math
               .abs(velocityY))
           || ((q == && q == ) || (q == && q == ))
           || ((q == && q == ) || (q == && q == ))
           || (q == && q == && quadrantTouched[])
           || (q == && q == && quadrantTouched[])) {
         CircleLayout.this.post(new FlingRunnable(-
             * (velocityX + velocityY)));
       } else {
         // the normal rotation
         CircleLayout.this
             .post(new FlingRunnable(velocityX + velocityY));
       }
       return true;
     }
     @Override
     public boolean onSingleTapUp(MotionEvent e) {
       mTappedViewsPostition = pointToPosition(e.getX(), e.getY());
       if (mTappedViewsPostition >= ) {
         mTappedView = getChildAt(mTappedViewsPostition);
         mTappedView.setPressed(true);
       } else {
         float centerX = circleWidth / ;
         float centerY = circleHeight / ;
         if (e.getX() < centerX + (childWidth / )
             && e.getX() > centerX - childWidth /
             && e.getY() < centerY + (childHeight / )
             && e.getY() > centerY - (childHeight / )) {
           if (mOnCenterClickListener != null) {
             mOnCenterClickListener.onCenterClick();
             return true;
           }
         }
       }
       if (mTappedView != null) {
         CircleImageView view = (CircleImageView) (mTappedView);
         if (selected != mTappedViewsPostition) {
           rotateViewToCenter(view, false);
           if (!rotateToCenter) {
             if (mOnItemSelectedListener != null) {
               mOnItemSelectedListener.onItemSelected(mTappedView,
                   mTappedViewsPostition, mTappedView.getId(), view.getName());
             }
             if (mOnItemClickListener != null) {
               mOnItemClickListener.onItemClick(mTappedView,
                   mTappedViewsPostition, mTappedView.getId(), view.getName());
             }
           }
         } else {
           rotateViewToCenter(view, false);
           if (mOnItemClickListener != null) {
             mOnItemClickListener.onItemClick(mTappedView,
                 mTappedViewsPostition, mTappedView.getId(), view.getName());
           }
         }
         return true;
       }
       return super.onSingleTapUp(e);
     }
   }
   /**
   * Rotates the given view to the center of the menu.
   * @param view      the view to be rotated to the center
   * @param fromRunnable  if the method is called from the runnable which animates the rotation
   *             then it should be true, otherwise false
   */
   private void rotateViewToCenter(CircleImageView view, boolean fromRunnable) {
     if (rotateToCenter) {
       float velocityTemp = ;
       float destAngle = (float) (firstChildPos - view.getAngle());
       float startAngle = ;
       int reverser = ;
       if (destAngle < ) {
         destAngle += ;
       }
       if (destAngle > ) {
         reverser = -;
         destAngle = - destAngle;
       }
       while (startAngle < destAngle) {
         startAngle += velocityTemp / ;
         velocityTemp *= .F;
       }
       CircleLayout.this.post(new FlingRunnable(reverser * velocityTemp,
           !fromRunnable));
     }
   }
   /**
   * A {@link Runnable} for animating the menu rotation.
   */
   private class FlingRunnable implements Runnable {
     private float velocity;
     float angleDelay;
     boolean isFirstForwarding = true;
     public FlingRunnable(float velocity) {
       this(velocity, true);
     }
     public FlingRunnable(float velocity, boolean isFirst) {
       this.velocity = velocity;
       this.angleDelay = / getChildCount();
       this.isFirstForwarding = isFirst;
     }
     public void run() {
       if (Math.abs(velocity) > && allowRotating) {
         if (rotateToCenter) {
           if (!(Math.abs(velocity) < && (Math.abs(angle
               - firstChildPos)
               % angleDelay < ))) {
             rotateButtons(velocity / );
             velocity /= .F;
             CircleLayout.this.post(this);
           }
         } else {
           rotateButtons(velocity / );
           velocity /= .F;
           CircleLayout.this.post(this);
         }
       } else {
         if (isFirstForwarding) {
           isFirstForwarding = false;
           CircleLayout.this.rotateViewToCenter(
               (CircleImageView) getChildAt(selected), true);
         }
       }
     }
   }
   private int pointToPosition(float x, float y) {
     for (int i = ; i < getChildCount(); i++) {
       View item = (View) getChildAt(i);
       if (item.getLeft() < x && item.getRight() > x & item.getTop() < y
           && item.getBottom() > y) {
         return i;
       }
     }
     return -;
   }
   public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
     this.mOnItemClickListener = onItemClickListener;
   }
   public interface OnItemClickListener {
     void onItemClick(View view, int position, long id, String name);
   }
   public void setOnItemSelectedListener(
       OnItemSelectedListener onItemSelectedListener) {
     this.mOnItemSelectedListener = onItemSelectedListener;
   }
   public interface OnItemSelectedListener {
     void onItemSelected(View view, int position, long id, String name);
   }
   public interface OnCenterClickListener {
     void onCenterClick();
   }
   public void setOnCenterClickListener(
       OnCenterClickListener onCenterClickListener) {
     this.mOnCenterClickListener = onCenterClickListener;
   }
 }

xml文件:
 
  <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:circle="http://schemas.android.com/apk/res/com.szugyi.circlemenu"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      tools:context=".MainActivity" >
      <com.lixu.circlemenu.view.CircleLayout
          android:id="@+id/main_circle_layout"
         android:layout_width="fill_parent"
         android:layout_height="fill_parent"
         android:layout_above="@+id/main_selected_textView"
         android:layout_gravity="center_horizontal"
         circle:firstChildPosition="South"
         circle:rotateToCenter="true"
         circle:isRotating="true" >      
 <!--         circle:circleBackground="@drawable/green"  > -->
         <com.lixu.circlemenu.view.CircleImageView
             android:id="@+id/main_facebook_image"
             android:layout_width="dp"
             android:layout_height="dp"
             android:src="@drawable/icon_facebook"
             circle:name="@string/facebook" />
         <com.lixu.circlemenu.view.CircleImageView
             android:id="@+id/main_myspace_image"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:src="@drawable/icon_myspace"
             circle:name="@string/myspace" />
         <com.lixu.circlemenu.view.CircleImageView
             android:id="@+id/main_google_image"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:src="@drawable/icon_google"
             circle:name="@string/google" />
         <com.lixu.circlemenu.view.CircleImageView
             android:id="@+id/main_linkedin_image"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:src="@drawable/icon_linkedin"
             circle:name="@string/linkedin" />
         <com.lixu.circlemenu.view.CircleImageView
             android:id="@+id/main_twitter_image"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:src="@drawable/icon_twitter"
             circle:name="@string/twitter" />
         <com.lixu.circlemenu.view.CircleImageView
             android:id="@+id/main_wordpress_image"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:src="@drawable/icon_wordpress"
             circle:name="@string/wordpress" />
     </com.lixu.circlemenu.view.CircleLayout>
     <TextView
         android:id="@+id/main_selected_textView"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
         android:layout_centerHorizontal="true"
         android:layout_marginBottom="dp"
         android:textAppearance="?android:attr/textAppearanceLarge" />
 </RelativeLayout>

基于Android实现转盘按钮代码的全部内容就到此结束了,希望能够帮助到大家。

(0)

相关推荐

  • 21天学习android开发教程之SurfaceView与多线程的混搭

    上一篇简单介绍了SurfaceView的基本使用,这次就介绍SurfaceView与多线程的混搭.SurfaceView与多线程混搭,是为了防止动画闪烁而实现的一种多线程应用.android的多线程用法与JAVA的多线程用法完全一样,本文不做多线程方面的介绍了.直接讲解SurfaceView与多线程的混合使用,即开一条线程专门读取图片,另外一条线程专门绘图.         本文程序运行截图如下,左边是开单个线程读取并绘图,右边是开两个线程,一个专门读取图片,一个专门绘图: 对比一下,右边动画的

  • Android中SurfaceView和view画出触摸轨迹

    一.引言          想实现一个空白的画板,上面可以画出手滑动的轨迹,就这么一个小需求.一般就来讲就两种实现方式,view或者surfaceview.下面看看两种是如何实现的. 二.实现原理          先简单说一下实现原理:        (1)用一张白色的Bitmap作为画板        (2)用canvas在bitmap上画线        (3)为了画出平滑的曲线,要用canvas的drawPath(Path,Paint)方法.        (4)同时使用贝塞尔曲线来使曲

  • Android Fragment中使用SurfaceView切换时闪一下黑屏的解决办法

    重构了下之前自己的一个新闻客户端,全部使用了Fragment来进行页面切换,只有一个入口Activity作为程序的启动Activity,其中有一个界面需要调用摄像头识别二维码,于是就会用到SurfaceView进行预览,那么问题来了,当切换到对应的Fragment时,屏幕会黑一下,黑了1秒左右就显示出正常的界面,而且这种现象只有第一次进入该Fragment才会出现,之后进入都不会出现,解决方法是无意在github上看到了,试了一下,可以行的通,下面贴出解决方法. 方法一.在Activity的on

  • Android App中实现简单的刮刮卡抽奖效果的实例详解

    主要思想: 将一个view设计成多层:背景层,含中奖信息等: 遮盖层,用于刮奖,使用关联一个Bitmap的Canvas 在该Bitmap上,使用它的canvas.drawPath的api来处理 手势滑动(类似刮奖的动作) 使用paint.setXfermode 来进行消除手势滑动区域 public class GuaView extends View { private Bitmap mBitmap; //遮盖的图层 private Canvas mCanvas; //绘制遮盖图层 privat

  • 21天学习android开发教程之SurfaceView

    上一篇文章介绍了MediaPlayer相关内容,这次用两篇文章来介绍SurfaceView的用法.网上介绍SurfaceView的用法有很多,写法也层出不同,例如继承SurfaceView类,或者继承SurfaceHolder.Callback类等,这个可以根据功能实际需要自己选择,我这里就直接在普通的用户界面调用SurfaceHolder的lockCanvas和unlockCanvasAndPost. 先来看看程序运行的截图: 截图1主要演示了直接把正弦波绘画在SurfaceView上 对比上

  • 解决Android SurfaceView绘制触摸轨迹闪烁问题的方法

    本文分享了解决SurfaceView触摸轨迹闪烁问题的方法,供大家参考,具体内容如下 第一种解决SurfaceView触摸轨迹闪烁问题的方法: 由于SurfaceView使用双缓存机制,两张画布轮流显示到屏幕上.那么,要存储触摸轨迹并避免两张画布内容不一致造成的闪烁问题,完全可以利用保存绘制过程并不断重新绘制的方法解决闪烁,而且这样还顺带解决了多次试验中偶尔出现的因为moveTo()函数不能读取到参数执行默认设置(参数设为上次的触摸点)而出现的断线连接闪烁问题,详细代码如下: package c

  • Android中SurfaceView用法简单实例

    本文实例讲述了Android中SurfaceView用法.分享给大家供大家参考,具体如下: 这里贴上一个小程序代码,主要运用SurfaceView来实现在屏幕上画一个圆,你可以通过按方向键和触摸屏幕来改变圆的位置 代码: Activity: package com.view; import android.app.Activity; import android.os.Bundle; import android.view.Window; import android.view.WindowMa

  • js和html5实现手机端刮刮卡抽奖效果完美兼容android/IOS

    绝对值得看的来篇,哈哈.本人亲自完成,有错误请大家指出: 现在的手机完美支持html5,所以如果手机端想要做个抽奖模块的话,用刮刮卡抽奖效果,相信这个互动体验是非常棒的 ​ps:由于本人没有wp8系统的手机,所以没法兼容wp8系统的,目前完美兼容android,IOS 如果要在pc浏览的话,得改下js,目前支持谷歌,火狐,ie>=10,如果网友想要的话我就去写个 代码如下: 复制代码 代码如下: <!DOCTYPE html> <html lang="en"&g

  • Android编程之SurfaceView实例详解

    本文实例讲述了Android编程之SurfaceView用法.分享给大家供大家参考,具体如下: 关于surfaceView相关知识: View和SurfaceView主要区别: 1. View只能在UI线程中刷新,而SurfaceView可以在子线程中刷新 2. SurfaceView可以控制刷新频率 SurfaceView几个重要的方法: 1. 继承SurfaceView 后调用getHolder()方法可以获取到mSurfaceHolder对象这个对于可以控制SurfaceView的绘制 2

  • Android中利用SurfaceView制作抽奖转盘的全流程攻略

    一.概述 今天给大家带来SurfaceView的一个实战案例,话说自定义View也是各种写,一直没有写过SurfaceView,这个玩意是什么东西?什么时候用比较好呢? 可以看到SurfaceView也是继承了View,但是我们并不需要去实现它的draw方法来绘制自己,为什么呢? 因为它和View有一个很大的区别,View在UI线程去更新自己:而SurfaceView则在一个子线程中去更新自己:这也显示出了它的优势,当制作游戏等需要不断刷新View时,因为是在子线程,避免了对UI线程的阻塞. 知

  • Android编程之SurfaceView学习示例详解

    本文实例讲述了Android编程之SurfaceView学习示例.分享给大家供大家参考,具体如下: SurfaceView是View的子类,使用的方式与任何View所派生的类都是完全相同的,可以像其他View那样应用动画,并把它们放到布局中. SurfaceView封装的Surface支持使用本章前面所描述的所有标准Canvas方法进行绘图,同时也支持完全的OpenGL ES库. 使用OpenGL,你可以再Surface上绘制任何支持的2D或者3D对象,与在2D画布上模拟相同的效果相比,这种方法

  • Android提高之SurfaceView的基本用法实例分析

    前文介绍了Android中MediaPlayer用法的时候稍微介绍了SurfaceView,SurfaceView由于可以直接从内存或者DMA等硬件接口取得图像数据,因此是个非常重要的绘图容器,这次我就来较为详细的介绍SurfaceView的用法.网上介绍SurfaceView的用法有很多,写法也层出不同,例如继承SurfaceView类,或者继承SurfaceHolder.Callback类等,这个可以根据功能实际需要自己选择,本文所述方法就直接在普通的用户界面调用SurfaceHolder的

  • Android实现抽奖转盘实例代码

    本文详述了android抽奖程序的实现方法,程序为一个抽奖大转盘代码,里面定义了很多图形方法和动画. 实现主要功能的SlyderView.java源代码如下: import android.app.Activity; import android.content.Context; import android.graphics.BlurMaskFilter; import android.graphics.Canvas; import android.graphics.Color; import

  • android图像绘制(四)自定义一个SurfaceView控件

    自定义控件(类似按钮等)的使用,自定义一个SurfaceView. 如某一块的动态图(自定义相应),或者类似UC浏览器下面的工具栏. 如下图示例:  自定义类代码: 复制代码 代码如下: public class ImageSurfaceView extends SurfaceView implements Callback{ //用于控制SurfaceView private SurfaceHolder sfh; private Handler handler = new Handler();

  • Android提高之SurfaceView与多线程的混搭实例

    前文简单介绍了Android中SurfaceView的基本使用,本文就来介绍一下SurfaceView与多线程的混搭.SurfaceView与多线程混搭,是为了防止动画闪烁而实现的一种多线程应用.android的多线程用法与JAVA的多线程用法完全一样,本文不做多线程方面的介绍了.直接讲解SurfaceView与多线程的混合使用,即开一条线程专门读取图片,另外一条线程专门绘图. 本文程序运行截图如下,左边是开单个线程读取并绘图,右边是开两个线程,一个专门读取图片,一个专门绘图: 对比一下可以看出

  • Android简单实现圆盘抽奖界面

    闲来无事,做了一个简单的抽奖转盘的ui实现,供大家参考 package com.microchange.lucky; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet;

随机推荐