I am new to android and currently working on an app which uses the camera API. I am having trouble with the implementation of Zoom function in the app. I am using Camera kit API to make the app and Camera-kit Api does not provide support for zoom controls. Please help me with the code required. I am unable to figure it out since a week. I need to implement Zoom to the camera Preview.
this is my Code.
public class MicroscopeAcitvity extends AppCompatActivity implements View.OnClickListener {
CameraView cameraView;
ImageButton cameraTakePic;
ImageButton buttonFlash;
Camera mCamera; //= Camera.open();
Camera.Parameters params;
TextView T1,T2;
int counter = 0;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_microscope_acitvity);
cameraView = (CameraView) findViewById(R.id.camera);
cameraTakePic = (ImageButton) findViewById(R.id.button_take_picture);
cameraTakePic.setOnClickListener(this);
buttonFlash = (ImageButton) findViewById(R.id.button_Flash);
buttonFlash.setOnClickListener(this);
T1 = (TextView) findViewById(R.id.flash_text1);
T1.setOnClickListener(this);
//T1.setVisibility(View.GONE);
T2 = (TextView) findViewById(R.id.flash_text2);
T2.setOnClickListener(this);
//T2.setVisibility(View.GONE);
cameraView.setCameraListener(new CameraListener() {
#Override
public void onPictureTaken(byte[] picture) {
super.onPictureTaken(picture);
// Create a bitmap
Bitmap result = BitmapFactory.decodeByteArray(picture, 0, picture.length);
}
});
cameraView.setFocus(CameraKit.Constants.FOCUS_TAP);
}
#Override
protected void onResume() {
super.onResume();
cameraView.start();
}
#Override
protected void onPause() {
cameraView.stop();
super.onPause();
}
#Override
public void onClick(View v) {
int id;
id = v.getId();
if(id == R.id.button_take_picture){
cameraView.captureImage();
}
if(id == R.id.button_Flash){
if(counter % 2 != 0){
T1.setVisibility(View.VISIBLE);
T2.setVisibility(View.VISIBLE);
counter = counter+1;
}
else{
T1.setVisibility(View.GONE);
T2.setVisibility(View.GONE);
counter = counter+1;
}
}
if(id == R.id.flash_text1){
T1.setTextColor(Color.RED);
T2.setTextColor(Color.DKGRAY);
cameraView.setFlash(CameraKit.Constants.FLASH_ON);
}
if (id == R.id.flash_text2){
T2.setTextColor(Color.RED);
T1.setTextColor(Color.DKGRAY);
cameraView.setFlash(CameraKit.Constants.FLASH_OFF);
}
}
}
If you want to zoom by pinch you have to implement a ScaleGestureDetector.SimpleOnScaleGestureListener
To set the zoom you simply have to change the camera parameters
Camera.Parameters parameters = camera.getParameters();
parameters.setZoom(zoomFactorValue);
camera.setParameters(parameters);
if you have some time you can code the rest yourself or look up how he did it
http://opencamera.sourceforge.net/
He uses pinch zoom on a surfaceview (but his code is not efficient and really ugly, very hard to understand on some points)
Related
I'm developing an application where I read some barcode. In a first step I had a big SurfaceView where I can see well the camera preview, but now I would set the dimensions of Surfaceview like the dimensions of barcode but I have bad camera visualization (it is too small). Can someone help me to stretch camera preview? Thanks
Here manage detector and surfaceview:
public class LettoreBarcode extends Fragment {
View view;
SurfaceView surfaceView;
Handler handler;
private BarcodeDetector detector;
private CameraSource cameraSource;
private TextView code;
SparseArray<Barcode> items;
private static Button btnBack;
String barcode = "" ;
SparseArray<Articoli> groups = new SparseArray<Articoli>();
Context _context = null;
ProductsAdapter.ViewHolder _ViewHolder = null;
public LettoreBarcode(){
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_barcode_scanner, container, false);
surfaceView = (SurfaceView) view.findViewById(R.id.surfaceView);
detector = new BarcodeDetector.Builder(getActivity()).setBarcodeFormats(Barcode.ALL_FORMATS).build();
final Dialog d = new Dialog(getActivity());
btnBack = (Button) view.findViewById(R.id.btnBack);
handler = new Handler();
if(!detector.isOperational()){
Toast.makeText(getActivity(), "Detector non attivabile", Toast.LENGTH_LONG).show();
}
cameraSource = new CameraSource.Builder(getActivity(), detector).setAutoFocusEnabled(true).build();
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
AttivaCamera();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
detector.setProcessor(new Detector.Processor<Barcode>() {
#Override
public void release() {
}
#Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
items = detections.getDetectedItems();
if (items.size() > 0){
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if (items.valueAt(0) != null){
//do something
handler.postDelayed(new Runnable() {
#Override
public void run() {
DisattivaCamera();
}
},10); //1000
}else
{
d.setContentView(R.layout.dialog_barcode_assente);
d.setTitle("Scanner");
d.setCancelable(true);
d.show();
DisattivaCamera();
}
}
});
}
}
});
btnBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getActivity().onBackPressed();
}
});
return view;
}
private void AttivaCamera()
{
try{
cameraSource.start(surfaceView.getHolder());
}catch(IOException e){
Toast.makeText(getActivity(), "Errore nell'avvio della fotocamera", Toast.LENGTH_LONG).show();
}
}
private void DisattivaCamera()
{
cameraSource.stop();
}
}
It is how I visualize camera with small surfaceview:
https://i.stack.imgur.com/TMunJ.png
I'm new in android development so I'm sorry if could be a lot of mistake in the code.
Sorry for my english also..
Thanks you guys!
In order to display only part of the camera input, i.e. to crop it on the screen, you need a surface view that has dimensions that fit the camera frame aspect ratio, and overlay it with some nontransparent views to leave only part of it visible. Don't put the SurfaeView inside scrolling layout:
So, instead of
<SurfaceView width: match_parent height: 400dp />
you need e.g. FrameLayout as explained here: Is it possible to crop camera preview?
This will not change the frame that arrives to the barcode detector. But this should not worry you; the detector will handle the uncropped image correctly.
I am creating a flashlight app. In my code, if camera(hardware) is there, it should show an alert, but it does not show the alert. My code is as below:
if (!isCameraFlash) {
showNoCameraAlert();
} else {
camera = Camera.open();
params = camera.getParameters();
}
but i get an error on
showNoCameraAlert();
Is this an invalid tag? or the tutorial i am using is old? I am using android studio. Here is my full Java code:
public class MainActivity extends ActionBarActivity {
private Camera camera;
ImageButton flashlightSwitchImg;
private boolean isFlashlightOn;
Parameters params;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
flashlightSwitchImg = (ImageButton) findViewById(R.id.flashlightSwitch);
boolean isCameraFlash = getApplicationContext().getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH);
if (!isCameraFlash) {
showNoCameraAlert();
} else {
camera = Camera.open();
params = camera.getParameters();
}
}
}
Any help will be appreciated. Thanks :)
You are calling the showNoCameraAlert() method. You need to add it to your MainActivity (that is the file where you put the code in.) So add it like this:
private void showNoCameraAlert(){
Toast.makeText(getApplicationContext(), "Camera flashlight not available in this Android device!", Toast.LENGTH_SHORT).show();
}
The full code for your MainActivity:
package com.example.administrator.flashlight;
import ...;
public class MainActivity extends ActionBarActivity {
private Camera camera;
ImageButton flashlightSwitchImg;
private boolean isFlashlightOn;
Parameters params;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
flashlightSwitchImg = (ImageButton) findViewById(R.id.flashlightSwitch);
//check if phone has a flashlight
boolean isCameraFlash = getApplicationContext().getPackageManager() .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH)
if (!isCameraFlash) {
//show error ( showNoCamereAlert() is below)
showNoCameraAlert();
} else {
//open the camera
camera = Camera.open();
params = camera.getParameters();
}
}
private void showNoCameraAlert(){
//Show Error toast
Toast.makeText(getApplicationContext(), "Camera flashlight not available in this Android device!", Toast.LENGTH_SHORT).show();
}
}
I'm starting to think that you didn't implement the showNoCameraAlert() method.
Try adding something like this to your MainActivity class:
private void showNoCameraAlert(){
Toast.makeText(getApplicationContext(), "There's no camera on the device or it doesn't have a flash", Toast.LENGTH_SHORT).show();
}
I am making an application where I have a camera inside of a viewPager. I am wondering what would best be suited to "pause" and "resume" the camera so it doesn't hog resources when it is pre-loaded. I have the feeling that stopPreview is better suited for this as it does not release the camera but keeps it however it doesn't display the camera which is the main reason it hogs resources.
Enter & exit application: startCamera() & releaseCamera()
Tab visible & not visible: startPreview() & stop Preview()
Would this be a good rule of thumb?
I had a similar situation. :
If I kept camera (in ViewPager) in on state, the swipe were clunky and OOM exceptions were frequent.
Two options came in my mind:
shift the entire instance in a different thread
OR
use stopPreview() and startPreview()
I went with the second one :
However, instead of doing this on Fragment lifecycle callbacks I gave a button on the fragment which toggled the preview. Reason being, if user is swiping very fast, you can still receive OOm exception since the preview calls will be queued, especially if there are very few fragments in the viewPager.
In essence Release camera onPause(), acquire camera in onResume() and give a groovy button in fragment which will toggle your Preview on the surface!
Hello Karl I had the same things need to implement in view pager. I have circular viewer in which one fragment has the camera fragment. I want to handle the camera preview in such a way so it should not consume the camera resource.
As you know android view pager default load two fragment in to the memory. We implemented the view pager change listener and call the fragment method to start and stop the preview. even also destroy the camera preview in on destroy method of fragment.
class ViewPagerChangeListener implements ViewPager.OnPageChangeListener {
int currentPosition = DEFAULT_FRAGMENT;
#Override
public void onPageScrollStateChanged(int state) {
TimberLogger.d(TAG, "onPageScrollStateChanged");
}
#Override
public void onPageScrolled(int index, float arg1, int arg2) {
TimberLogger.d(TAG, "onPageScrolled" + index);
}
#Override
public void onPageSelected(int position) {
mWatchPosition = position;
TimberLogger.d(TAG, "onPageSelected" + mWatchPosition);
int newPosition = 0;
if (position > 4) {
newPosition = position;
}
TimberLogger.d(TAG, "newPosition" + newPosition);
/**
* Listener knows the new position and can call the interface method
* on new Fragment with the help of PagerAdapter. We can here call
* onResumeFragment() for new fragment and onPauseFragment() on the
* current one.
*/
// new fragment onResume
loadedFragment(newPosition).onResumeFragment();
// current fragment onPuase called
loadedFragment(currentPosition).onPauseFragment();
currentPosition = newPosition;
TimberLogger.d(TAG, "currentPosition" + currentPosition);
}
}
See the two method onResumeFragment and onPuaseFragment this two are the custom function each view pager fragment implements. In view pager change event we call the pause of current fragment and onResume of the new fragment.
// new fragment onResume
loadedFragment(newPosition).onResumeFragment();
// current fragment onPuase called
loadedFragment(currentPosition).onPauseFragment();
You can write your camera start preview inside custom method onResumeFragment and stop preview in onPauseFragment and also make sure you should override the onDestory() method of your camera fragment for release the camera resources.
The best solution will be to startCamera() in onResume(), and release it in onPause(), so you can handle, that camera is not free in onResume().
In ViewPager you can startPreview(), when fragment with it is selected, and stopPreview() otherwise. Also u can startPreview() in onCreateView() and stopPreview() in onDestroyView() in fragment.
This takes care of most of the operations CameraPreview.java:
package com.example.fela;
import android.app.Activity;
import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.ErrorCallback;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.Size;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.WindowManager;
import java.util.List;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
private Camera camera;
private int cameraId;
private Activity activity;
private CameraPreviewActivityInterface activityInterface;
public CameraPreview(Activity activity, int cameraId) {
super(activity);
try {
activityInterface = (CameraPreviewActivityInterface) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement ExampleFragmentCallbackInterface ");
}
this.activity = activity;
this.cameraId = cameraId;
holder = getHolder();
holder.addCallback(this);
// deprecated setting, but required on Android versions prior to 3.0
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder) {}
/**
* custom camera tweaks and startPreview()
*/
public void refreshCamera() {
if (holder.getSurface() == null || camera == null) {
// preview surface does not exist, camera not opened created yet
return;
}
Log.i(null, "CameraPreview refreshCamera()");
// stop preview before making changes
try {
camera.stopPreview();
} catch (Exception e) {
// ignore: tried to stop a non-existent preview
}
int rotation = ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
int degrees = 0;
// specifically for back facing camera
switch (rotation) {
case Surface.ROTATION_0:
degrees = 90;
break;
case Surface.ROTATION_90:
degrees = 0;
break;
case Surface.ROTATION_180:
degrees = 270;
break;
case Surface.ROTATION_270:
degrees = 180;
break;
}
camera.setDisplayOrientation(degrees);
setCamera(camera);
try {
camera.setPreviewDisplay(holder);
camera.startPreview();
} catch (Exception e) {
// this error is fixed in the camera Error Callback (Error 100)
Log.d(VIEW_LOG_TAG, "Error starting camera preview: " + e.getMessage());
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Log.i(null, "CameraPreview surfaceChanged()");
// if your preview can change or rotate, take care of those events here.
// make sure to stop the preview before resizing or reformatting it.
// do not start the camera if the tab isn't visible
if(activityInterface.getCurrentPage() == 1)
startCamera();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {}
public Camera getCameraInstance() {
Camera camera = Camera.open();
// parameters for camera
Parameters params = camera.getParameters();
params.set("jpeg-quality", 100);
params.set("iso", "auto");
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
params.setPictureFormat(PixelFormat.JPEG);
// set the image dimensions
List<Size> sizes = params.getSupportedPictureSizes();
int max = 0, width = 0, height = 0;
for(Size size : sizes) {
if(max < (size.width*size.height)) {
max = (size.width*size.height);
width = size.width;
height = size.height;
}
}
params.setPictureSize(width, height);
camera.setParameters(params);
// primarily used to fix Error 100
camera.setErrorCallback(new ErrorCallback() {
#Override
public void onError(int error, Camera camera) {
if(error == Camera.CAMERA_ERROR_SERVER_DIED) {
releaseCamera();
startCamera();
}
}
});
return camera;
}
/**
* intitialize a new camera
*/
protected void startCamera() {
if(getCamera() == null)
setCamera(getCameraInstance());
refreshCamera();
}
/**
* release camera so other applications can utilize the camera
*/
protected void releaseCamera() {
// if already null then the camera has already been released before
if (getCamera() != null) {
getCamera().release();
setCamera(null);
}
}
public Camera getCamera() {
return camera;
}
public void setCamera(Camera camera) {
this.camera = camera;
}
public void setCameraId(int cameraId) {
this.cameraId = cameraId;
}
/**
* get the current viewPager page
*/
public interface CameraPreviewActivityInterface {
public int getCurrentPage();
}
}
In my FragmentCamera.java file:
private CameraPreview cameraPreview;
// code...
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// code...
cameraPreview = new CameraPreview(getActivity(), cameraId);
previewLayout.addView(cameraPreview);
// code...
}
// code...
#Override
public void onPause() {
super.onPause();
cameraPreview.releaseCamera();
}
#Override
public void onResume() {
super.onResume();
cameraPreview.startCamera();
}
protected void fragmentVisible() {
onResume();
}
protected void fragmentNotVisible() {
onPause();
}
And the MainActivity.java file (implements CameraPreviewActivityInterface):
viewPager.setOnPageChangeListener(new OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
currentPage = position;
if (currentPage == 1) {
fragmentCamera.fragmentVisible();
} else {
fragmentCamera.fragmentNotVisible();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
#Override
public int getCurrentPage() {
return currentPage;
}
I'm currently facing 2 major problems,
I'm using a youtube player and when it gets on full screen, It plays for 1-2 seconds and stop.
When I click the "Play" button in the middle, it's buffering all over again. even if the gray bar filled to it's center.
those problems aren't occurring in portrait mode.
here is my class, like the youtube api demo with a bit defference
public class Video extends YouTubeFailureRecoveryActivity implements YouTubePlayer.OnFullscreenListener, Utils.OnGetUrlListener, View.OnClickListener {
static int AUTO_PLAY_DELAY = 1000;
static final int PORTRAIT_ORIENTATION = Build.VERSION.SDK_INT < 9
? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
: ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT;
private LinearLayout mRootLayout;
/**
* * Youtube ***
*/
YouTubePlayerView mPlayerView;
YouTubePlayer mPlayer;
boolean mIsFullscreen;
String urlID;
/**
* * My ***
*/
RelativeLayout mContainer;
ImageView mBtPlay;
boolean mIsNeedSetFlags;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Utils.getInstance().setActivity(this);
setContentView(R.layout.video_main);
mIsNeedSetFlags = true;
mRootLayout = (LinearLayout) findViewById(R.id.video_root_layout);
mContainer = (RelativeLayout) findViewById(R.id.container);
mBtPlay = (ImageView) findViewById(R.id.video_play);
mBtPlay.setVisibility(View.INVISIBLE);
mPlayerView = (YouTubePlayerView) findViewById(R.id.player);
Intent intent = getIntent();
doLayout();
}
#Override
public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer player, boolean wasRestored) {
mPlayer = player;
player.addFullscreenControlFlag(YouTubePlayer.FULLSCREEN_FLAG_CUSTOM_LAYOUT);
player.setOnFullscreenListener(this);
if (mIsNeedSetFlags) {
mIsNeedSetFlags = false;
int controlFlags = player.getFullscreenControlFlags();
setRequestedOrientation(PORTRAIT_ORIENTATION);
controlFlags |= YouTubePlayer.FULLSCREEN_FLAG_ALWAYS_FULLSCREEN_IN_LANDSCAPE;
player.setFullscreenControlFlags(controlFlags);
}
if (!wasRestored) {
player.cueVideo(urlID);
}
}
#Override
protected YouTubePlayer.Provider getYouTubePlayerProvider() {
return mPlayerView;
}
private void doLayout() {
LinearLayout.LayoutParams playerParams = (LinearLayout.LayoutParams) mPlayerView.getLayoutParams();
if (mIsFullscreen) {
playerParams.width = LinearLayout.LayoutParams.MATCH_PARENT;
playerParams.height = LinearLayout.LayoutParams.MATCH_PARENT;
mParallaxScrollView.setVisibility(View.GONE);
} else {
mParallaxScrollView.setVisibility(View.VISIBLE);
if (getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
ViewGroup.LayoutParams otherViewsParams = mParallaxScrollView.getLayoutParams();
playerParams.width = otherViewsParams.width = MATCH_PARENT;
playerParams.height = WRAP_CONTENT;
mRootLayout.setOrientation(LinearLayout.VERTICAL);
}
}
mPlayerView.setLayoutParams(playerParams);
}
#Override
public void onFullscreen(boolean isFullscreen) {
mIsFullscreen = isFullscreen;
showPlayerAndPlay();
doLayout();
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
doLayout();
}
#Override
public void onGetUrlFinished(String videoUrl) {
urlID = videoUrl;
mBtPlay.setVisibility(View.VISIBLE);
mBtPlay.setOnClickListener(this);
mPlayerView.initialize(Utils.YOU_TUBE_DEV_KEY, this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.video_play:
showPlayerAndPlay();
break;
}
}
private void showPlayerAndPlay() {
mPlayerView.setVisibility(View.VISIBLE);
mBtPlay.setVisibility(View.INVISIBLE);
if (!mPlayer.isPlaying())
new android.os.Handler().postDelayed(new Runnable() {
#Override
public void run() {
mPlayer.play();
}
}, AUTO_PLAY_DELAY);
}
}
YouTube does not allow other views to be overlayed on top of its player view.
If you check the logs, you will also see a warning message that specifies this very limitation, plus more information on which view (its ID) and the overlapping region.
A good alternative is to used Exoplayer, to overlay your video with view. It is not part of the android sdk, but it's recommended by google and included in android developer documentation :
http://google.github.io/ExoPlayer/ https://developer.android.com/guide/topics/media/exoplayer.html
Exoplayer allow you to stream any kind of video, not only Youtubes videos.
It's also good to mention that Exoplayer is used in Youtube application.
As the answer marked as correct explained: the problem is overlaying a view over the Youtube player view. If you need to keep those views will the Youtube is initializing then this will do the trick.
I was doing a loading animation with crossfade for the involved views. Setting alpha to 0 won't fix the issue because the view is still there. But setting visibility to GONE or INVISIBLE does work. For what I understand a View is not computed if is not VISIBLE, well at least it will not be taken into consideration after the visibility changed. Finally, I did something like this:
myView.animate().alpha(0).setDuration(800).setListener(
new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationEnd(Animator animator) {
myView.setVisibility(View.GONE);
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
}).start();
i am drawing a piechart by extending surfaceview to PieChart Class. now i am creating 2 objects for Piechart and adding to a VieWFlipper to swipe between those charts. now my problem is 2nd Piechart is not visible to the user if user swipes to 2nd view. but all the 2nd pies functionality is working. i am thinking like its refresh problem of the surfaceview.
any help on this will be appreciable. the following is my PieChart class.
class MyPieChart extends SurfaceView implements SurfaceHolder.Callback {
#Override
public void onDraw(Canvas canvas) {
if (hasData) {
resetColor();
try {
canvas.drawColor(getResources().getColor(R.color.graphbg_color));
graphDraw(canvas);
} catch (ValicException ex) {
}
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
Log.i("PieChart", "surfaceChanged");
}
public int callCount = 0;
#Override
public void surfaceCreated(SurfaceHolder holder) {
if ((callCount++) % 2 == 0) {
callCount = 1;
try {
Log.i("PieChart", "surfaceCreated");
mChartThread = new ChartThread(getHolder(), this);
mChartThread.setRunning(true);
if (!mChartThread.isAlive()) {
mChartThread.start();
}
mFrame = holder.getSurfaceFrame();
mOvalF = new RectF(0, 0, mFrame.right, mFrame.right);
} catch (Exception e) {
// No error message required
}
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i("PieChart", "surfaceDestroyed");
boolean retry = true;
callCount = 0;
mChartThread.setRunning(false);
while (retry) {
try {
mChartThread.join();
retry = false;
} catch (InterruptedException e) {
// No error message required
}
}
}
}
class ChartThread extends Thread {
private SurfaceHolder mSurfaceHolder;
private PieChart mPieChart;
private boolean mRefresh = false;
public ChartThread(SurfaceHolder surfaceHolder, PieChart pieChart) {
// Log.i("ChartThread", "ChartThread");
mSurfaceHolder = surfaceHolder;
mPieChart = pieChart;
}
public void setRunning(boolean Refresh) {
// Log.i("ChartThread", "setRunning : " + Refresh);
mRefresh = Refresh;
}
#Override
public void run() {
Canvas c;
// Log.i("ChartThread", "run : " + mRefresh);
while (mRefresh) {
c = null;
try {
c = mSurfaceHolder.lockCanvas(mPieChart.mFrame);
// c.drawColor(0xFFebf3f5);
synchronized (mSurfaceHolder) {
mPieChart.onDraw(c);
}
} catch (Exception ex) {
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
here is my flipper.xml
<ViewFlipper
android:id="#+id/flipper"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout android:id="#+id/pie1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<LinearLayout android:id="#+id/pie2"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
and i here is my activity
public class ViewFlipperActivity extends Activity {
Button b1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b1 = (Button)findViewById(R.id.submit1);
b1.setOnClickListener(new View.OnClickListener() {
ViewFlipper vflipper=(ViewFlipper)findViewById(R.id.flipper);
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
vflipper.showNext();
}
});
}
and i am dding the piecharts to Pie1 and Pie2 LinearLayouts in the Flipper.
both the pie's are created and pasted on to the Pie Layouts. now if i move to the 2nd view in the flipper Pie1 is showing instead of pie2 and all other data and functionality which i am getting is related to Pie2. my doubt is Pie2 is rendering and hidden under Pie1. can any one help me on this with some solution.
i got a break through for this issue. which caused another issue with the following changes.
in flipper.xml replaced LinearLayout i place of view flipper.
<LinearLayout
android:id="#+id/flipper"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout android:id="#+id/pie1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout >
and in ViewFlipperActivity
public class ViewFlipperActivity extends Activity {
Button b1;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b1 = (Button)findViewById(R.id.submit1);
b1.setOnClickListener(new View.OnClickListener() {
LinearLayout vflipper=(LinearLayout)findViewById(R.id.flipper);
LinearLayout pie1=(LinearLayout)findViewById(R.id.pie1);
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
vflipper.setAnimation(AnimationUtils.loadAnimation(this, R.anim.push_left_in));
pie1.removeAllViews();
pie1.addView(PieChart/SurfaceView);
}
});
}
with the animation and is working fine and piechart is getting changed on the view. but block rect is getting visible from the surfaceview for a sec when swiping between piecharts. can some one help me on this issue.
SurfaceView is not going to work properly inside a ViewFlipper as it cannot be animated correctly. This is why Android 4.0 introduces a new widget called TextureView that solves this problem.
here main problem is SurfaceView cannot be animated. that's why neither ViewFlipper nor Layout Animation cannot be applied for SurfaceView.