Enlarge a view using a zoom animation - java

If you please, I will quote the proposed solution in the developer page for Android The solution is how to enlarge the image when you click it But after applying it and when I click on the image the application closes and gives me an error occurred This is a picture of the error tracker Can anyone help me solve the problem
https://developer.android.com/training/animation/zoom
I have resubmitted the question after adding files xml and java
Sample of XML file containing 100 images for viewing
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/photo_1"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_margin="#dimen/fab_margin"
android:layout_weight="1"
android:src="#drawable/allah_jl_jlalh"
app:civ_border_color="#color/colorAccent"
app:civ_border_width="3dp"
tools:ignore="RtlHardcoded" />
<de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/photo_2"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_margin="#dimen/fab_margin"
android:layout_weight="1"
android:src="#drawable/alrahman"
app:civ_border_color="#color/colorAccent"
app:civ_border_width="3dp"
tools:ignore="RtlHardcoded" />
<de.hdodenhof.circleimageview.CircleImageView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/photo_3"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_margin="#dimen/fab_margin"
android:layout_weight="1"
android:src="#drawable/alrahem"
app:civ_border_color="#color/colorAccent"
app:civ_border_width="3dp"
tools:ignore="RtlHardcoded" />
</LinearLayout>
<ImageView
android:id="#+id/expanded_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
java file:
public class Athkar7 extends AppCompatActivity {
private Animator mCurrentAnimator;
private int mShortAnimationDuration;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
setContentView( R.layout.activity_athkar7 );
final CircleImageView thumb1View = (CircleImageView) findViewById( R.id.photo_1 );
thumb1View.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View view) {
zoomImageFromThumb( thumb1View,R.drawable.alrahman );
}
} );
// Retrieve and cache the system's default "short" animation time.
mShortAnimationDuration = getResources().getInteger(
android.R.integer.config_shortAnimTime );
}
public void zoomImageFromThumb(final View thumbView,int imageResId) {
// If there's an animation in progress, cancel it
// immediately and proceed with this one.
if (mCurrentAnimator != null) {
mCurrentAnimator.cancel();
}
// Load the high-resolution "zoomed-in" image.
final ImageView expandedImageView = (ImageView) findViewById(
R.id.expanded_image );
expandedImageView.setImageResource( imageResId );
// Calculate the starting and ending bounds for the zoomed-in image.
// This step involves lots of math. Yay, math.
final Rect startBounds = new Rect();
final Rect finalBounds = new Rect();
final Point globalOffset = new Point();
// The start bounds are the global visible rectangle of the thumbnail,
// and the final bounds are the global visible rectangle of the container
// view. Also set the container view's offset as the origin for the
// bounds, since that's the origin for the positioning animation
// properties (X, Y).
thumbView.getGlobalVisibleRect( startBounds );
findViewById( R.id.container )
.getGlobalVisibleRect( finalBounds,globalOffset );
startBounds.offset( -globalOffset.x,-globalOffset.y );
finalBounds.offset( -globalOffset.x,-globalOffset.y );
// Adjust the start bounds to be the same aspect ratio as the final
// bounds using the "center crop" technique. This prevents undesirable
// stretching during the animation. Also calculate the start scaling
// factor (the end scaling factor is always 1.0).
float startScale;
if ((float) finalBounds.width() / finalBounds.height()
> (float) startBounds.width() / startBounds.height()) {
// Extend start bounds horizontally
startScale = (float) startBounds.height() / finalBounds.height();
float startWidth = startScale * finalBounds.width();
float deltaWidth = (startWidth - startBounds.width()) / 2;
startBounds.left -= deltaWidth;
startBounds.right += deltaWidth;
} else {
// Extend start bounds vertically
startScale = (float) startBounds.width() / finalBounds.width();
float startHeight = startScale * finalBounds.height();
float deltaHeight = (startHeight - startBounds.height()) / 2;
startBounds.top -= deltaHeight;
startBounds.bottom += deltaHeight;
}
// Hide the thumbnail and show the zoomed-in view. When the animation
// begins, it will position the zoomed-in view in the place of the
// thumbnail.
thumbView.setAlpha( 0f );
expandedImageView.setVisibility( View.VISIBLE );
// Set the pivot point for SCALE_X and SCALE_Y transformations
// to the top-left corner of the zoomed-in view (the default
// is the center of the view).
expandedImageView.setPivotX( 0f );
expandedImageView.setPivotY( 0f );
// Construct and run the parallel animation of the four translation and
// scale properties (X, Y, SCALE_X, and SCALE_Y).
AnimatorSet set = new AnimatorSet();
set
.play( ObjectAnimator.ofFloat( expandedImageView,View.X,
startBounds.left,finalBounds.left ) )
.with( ObjectAnimator.ofFloat( expandedImageView,View.Y,
startBounds.top,finalBounds.top ) )
.with( ObjectAnimator.ofFloat( expandedImageView,View.SCALE_X,
startScale,1f ) )
.with( ObjectAnimator.ofFloat( expandedImageView,
View.SCALE_Y,startScale,1f ) );
set.setDuration( mShortAnimationDuration );
set.setInterpolator( new DecelerateInterpolator() );
set.addListener( new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
mCurrentAnimator = null;
}
#Override
public void onAnimationCancel(Animator animation) {
mCurrentAnimator = null;
}
} );
set.start();
mCurrentAnimator = set;
// Upon clicking the zoomed-in image, it should zoom back down
// to the original bounds and show the thumbnail instead of
// the expanded image.
final float startScaleFinal = startScale;
expandedImageView.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View view) {
if (mCurrentAnimator != null) {
mCurrentAnimator.cancel();
}
// Animate the four positioning/sizing properties in parallel,
// back to their original values.
AnimatorSet set = new AnimatorSet();
set.play( ObjectAnimator
.ofFloat( expandedImageView,View.X,startBounds.left ) )
.with( ObjectAnimator
.ofFloat( expandedImageView,
View.Y,startBounds.top ) )
.with( ObjectAnimator
.ofFloat( expandedImageView,
View.SCALE_X,startScaleFinal ) )
.with( ObjectAnimator
.ofFloat( expandedImageView,
View.SCALE_Y,startScaleFinal ) );
set.setDuration( mShortAnimationDuration );
set.setInterpolator( new DecelerateInterpolator() );
set.addListener( new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
thumbView.setAlpha( 1f );
expandedImageView.setVisibility( View.GONE );
mCurrentAnimator = null;
}
#Override
public void onAnimationCancel(Animator animation) {
thumbView.setAlpha( 1f );
expandedImageView.setVisibility( View.GONE );
mCurrentAnimator = null;
}
} );
set.start();
mCurrentAnimator = set;
}
} );
}
}
enter image description here
This code is to be applied to 100 images that you have set for viewing within a single activity
Here I have another problem that when I pass the application slider suddenly comes out of the activity and returns to the MainActivity how can I solve this problem ???

Use this library to solve your problem.

Related

Android Java Vertical scroll view size

I have a very simple activity with a vertical scroll view (mainscreen.xml below).
This vertical scroll view has a linear layout child view.
I dynamically add text views as children to this linear layout (populateLinlayWithTextViews() below).
Later, after these text view children have been added, I can scroll the vertical scroll view (onScrollChange() below).
And I can measure the visible part of the vertical scroll view (getHeight()).
My problem is that I need to know earlier than at scroll time what is the maximum height of the visible part of the vertical scroll view.
mainscreen.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="#+id/scrollview"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<LinearLayout
android:id="#+id/linlay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
</LinearLayout>
</ScrollView>
</LinearLayout>
MyActivity.java
protected void onCreate(#Nullable Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.mainscreen);
Resources resources = getResources();
int n_statusBarHeight = resources.getIdentifier( "status_bar_height", "dimen", "android"); // 36px
populateLinlayWithTextViews();
// HERE
ScrollView sv = sv = findViewById(R.id.scrollview);
int n_svVisiblePartHeight = sv.getHeight(); // 0px
View.OnScrollChangeListener onScrollChangedListener
= new View.OnScrollChangeListener()
{
#Override
public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
{
ScrollView sv = sv = findViewById(R.id.scrollview);
int n_svVisiblePartHeight = sv.getHeight(); // 680px
}
}
sv = findViewById(R.id.scrollview);
sv.setOnScrollChangeListener(onScrollChangedListener);
}
public void populateLinlayWithTextViews()
{
LinearLayout linlay = findViewById(R.id.linlay);
int n_viewHeight = 81; // px
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
n_viewHeight);
for(int n_i=0 ; n_i<20 ; n_i++)
{
TextView tvNew = new TextView(m_app);
tvNew.setText(n_i + " - test");
tvNew.setTextColor(Color.rgb(0, 0, 0)); // black
tvNew.setTextSize(TypedValue.COMPLEX_UNIT_SP, 40);
tvNew.setLayoutParams(params);
linlay.addView(tvNew, linlay.getChildCount());
}
}
When I scroll the vertical scroll view, I can see that n_svVisiblePartHeight's value is 680px.
But I need to know this value earlier // HERE.
But // HERE, the value I get is 0px.
Can you help me?
EDIT 1
I need to know this height because:
example 1: I would like to know initially the index of the text view that will be at the bottom of the (visible) screen after I have populated
the linear layout with text views ;
example 2: given this height X I'm looking for, let's say that I would like 10 text views to be visible initially, I would like to determine X/10 which will be the height of the text views, so that I can put it dynamically in n_viewHeight.
EDIT 2
I just need to know the height of the red arrow below, a soon as I can in the lifecycle of the activity and preferably before I add text views to the linear layout or right after (// HERE):
EDIT 3
I don't know if theoretically that's true:
n_scrollViewVisibleHeightInPx =
n_displayHeightInPx
- n_actionBarHeight
- n_navigationBarHeightInPx
+ n_statusBarHeightInPx;
... but practically n_scrollViewVisibleHeightInPx is the height of the space designated by the red arrow in the image above.
To get these various heights, below are the methods I used:
private int returnStatusBarHeightInPx()
{
int n_statusBarHeightInPx = -1;
Resources resources = null;
int n_idStatusBarHeight = -1;
resources = getResources();
n_idStatusBarHeight = resources.getIdentifier( "status_bar_height", "dimen", "android");
if(n_idStatusBarHeight > 0)
{
n_statusBarHeightInPx = getResources().getDimensionPixelSize(n_idStatusBarHeight);
}
else
{
n_statusBarHeightInPx = 0;
}
return n_statusBarHeightInPx;
}
private int returnNavigationBarHeightInPx()
{
int n_navigationBarHeightInPx = -1;
Resources resources = null;
int n_idNavigationBarHeight = -1;
resources = getResources();
n_idNavigationBarHeight = resources.getIdentifier("navigation_bar_height", "dimen", "android");
if(n_idNavigationBarHeight > 0)
{
n_navigationBarHeightInPx = getResources().getDimensionPixelSize(n_idNavigationBarHeight);
}
else
{
n_navigationBarHeightInPx = 0;
}
return n_navigationBarHeightInPx;
}
private int returnActionBarHeightInPx()
{
TypedValue typedValue = null;
int n_actionBarHeightInPx = -1;
typedValue = new TypedValue();
if(getTheme().resolveAttribute(android.R.attr.actionBarSize, typedValue, true))
{
n_actionBarHeightInPx =
TypedValue.complexToDimensionPixelSize(
typedValue.data,
getResources().getDisplayMetrics());
}
return n_actionBarHeightInPx;
}
private int returnDisplayHeightInPx()
{
DisplayMetrics displayMetrics = null;
int n_displayHeightInPx = -1;
displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
n_displayHeightInPx = displayMetrics.heightPixels;
return n_displayHeightInPx;
}
Why do you want to know it in "//here". You do not use that variable there. Your code does not explain, why it is not possible, to define the variable on scroll time.

Android swipebutton centerposition

I followed this tutorial: https://android.jlelse.eu/make-a-great-android-ux-how-to-make-a-swipe-button-eefbf060326d
It gave me a lot of information about swipebuttons, and I almost got it to work in my project. I need to swipe both left and right, and therefore I need the round slidingbutton to start in the middle instead of at the left side.
I can make it return to the middle with a function, but I can't seem to find a place where I set some initial positions of it.
EDIT:
XML in the layout:
<com.example.frederik.promille.SwipeButtonBeer
android:id="#+id/swipe_btn_beer"
android:layout_width="340dp"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="#+id/progressBar" />
Code to return the button to the middle:
public void moveButtonBack() {
final ValueAnimator positionAnimator =
ValueAnimator.ofFloat(slidingButton.getX(), (getWidth()-initialButtonWidth)/2);
positionAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
positionAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float x = (Float) positionAnimator.getAnimatedValue();
slidingButton.setX(x);
}
});
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(
centerText, "alpha", 1);
positionAnimator.setDuration(200);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(objectAnimator, positionAnimator);
animatorSet.start();
}

Custom Collapsing Toolbar smooth title resizing

I'm using a custom Collapsing Toolbar Layout, which has a Title and a Subtitle.
I got the title to collapse and animate on a curved path, but the part of the title becoming smaller as collapsing isn't smooth. It resizes in a jagged sort of way.
This is my behavior that is responsible for moving and resizing the title:
public class ViewBehavior : CoordinatorLayout.Behavior
{
private Context mContext;
private int mStartMarginRight;
private int mEndMargintRight;
private int mMarginLeft;
private int mStartMarginBottom;
private bool isHide;
private static float SCALE_MINIMUM = 0.5f;
public ViewBehavior(Context context, IAttributeSet attrs)
{
mContext = context;
}
public override bool LayoutDependsOn(CoordinatorLayout parent, Java.Lang.Object child, View dependency)
{
return dependency is AppBarLayout;
}
public override bool OnDependentViewChanged(CoordinatorLayout parent, Java.Lang.Object child, View dependency)
{
ShouldInitProperties((child as HeaderView), dependency);
int maxScroll = ((AppBarLayout)dependency).TotalScrollRange;
float percentage = System.Math.Abs(dependency.GetY()) / (float)maxScroll;
float childPosition = dependency.Height
+ dependency.GetY()
- (child as View).Height
- (getToolbarHeight() - (child as View).Height) * percentage / 2;
childPosition = childPosition - mStartMarginBottom * (1f - percentage);
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams)(child as View).LayoutParameters;
lp.RightMargin = (int)(100 * System.Math.Sin(percentage * System.Math.PI)) + mStartMarginRight / 2 + mEndMargintRight / 2;
lp.LeftMargin = mMarginLeft;
(child as View).LayoutParameters = lp;
(child as View).SetY(childPosition);
float x = (child as HeaderView).Title.TextSize;
//Here is the algorithm for setting the text size
(child as HeaderView).Title.SetTextSize(ComplexUnitType.Sp, 36 * (1 - percentage / 2));
(child as HeaderView).SubTitle.SetTextSize(ComplexUnitType.Sp, 26 * (1 - percentage / 2));
var toolbarTitleSize = (int)TypedValue.ApplyDimension(ComplexUnitType.Sp, 18, Application.Context.Resources.DisplayMetrics);
var toolbarSubTitleSize = (int)TypedValue.ApplyDimension(ComplexUnitType.Sp, 16, Application.Context.Resources.DisplayMetrics);
if ((child as HeaderView).Title.TextSize < toolbarTitleSize)
(child as HeaderView).Title.SetTextSize(ComplexUnitType.Sp, 18);
if ((child as HeaderView).SubTitle.TextSize < toolbarSubTitleSize)
(child as HeaderView).SubTitle.SetTextSize(ComplexUnitType.Sp, 14);
if (Build.VERSION.SdkInt < BuildVersionCodes.Lollipop)
{
if (isHide && percentage < 1)
{
(child as View).Visibility = ViewStates.Visible;
isHide = false;
}
else if (!isHide && percentage == 1)
{
(child as View).Visibility = ViewStates.Gone;
isHide = true;
}
}
return true;
}
public void ShouldInitProperties(HeaderView child, View dependency)
{
if (mStartMarginRight == 0)
mStartMarginRight = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_start_margin_right);
if (mEndMargintRight == 0)
mEndMargintRight = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_end_margin_right);
if (mStartMarginBottom == 0)
mStartMarginBottom = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_start_margin_bottom);
if (mMarginLeft == 0)
mMarginLeft = mContext.Resources.GetDimensionPixelOffset(Resource.Dimension.header_view_end_margin_left);
}
public int getToolbarHeight()
{
int result = 0;
TypedValue tv = new TypedValue();
if (mContext.Theme.ResolveAttribute(Android.Resource.Attribute.ActionBarSize, tv, true))
{
result = TypedValue.ComplexToDimensionPixelSize(tv.Data, mContext.Resources.DisplayMetrics);
}
return result;
}
}
How can I change the algorithm so it should resize in a smoother fashion?
Edit - Video:
https://youtu.be/j6LseSW6h1s
As mentioned by others scaling via textSize doesn't work well on Android within animations since it isn't accurate enough (it rounds up the decimal values to integers).
If it fulfills your need you should perform your animation with the scaleX/scaleY attributes, e.g.:
float scale = 1 - percentage * SCALE_MINIMUM;
(child as HeaderView).Title.SetScaleX(scale);
(child as HeaderView).Title.SetScaleY(scale);
(child as HeaderView).SubTitle.SetScaleX(scale);
(child as HeaderView).SubTitle.SetScaleY(scale);
The problem you have is that the even if you calculate scales as demical values, they become integer values in the TextView. You should enable both LINEAR_TEXT_FLAG and SUBPIXEL_TEXT_FLAG flags in your TextView's Paint class to achieve smooth scaling and positioning.
Something like this:
yourTextView.Paint.SubpixelText = true;
yourTextView.Paint.LinearText = true;
I have use this layout format for collapsing toolbar and it works smoothly.
<android.support.design.widget.AppBarLayout
android:id="#+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="#dimen/height_300dp"
android:background="?colorPrimary">
<android.support.design.widget.CollapsingToolbarLayout
android:id="#+id/collapsible_Toolbar_Layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:collapsedTitleTextAppearance="#style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
app:contentScrim="#color/colorDarkBlue"
app:expandedTitleMarginEnd="#dimen/margin_64dp"
app:expandedTitleMarginStart="#dimen/margin_20dp"
app:expandedTitleTextAppearance="#style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:fitsSystemWindows="true"
android:focusableInTouchMode="true"
android:scaleType="centerCrop"
app:layout_collapseMode="parallax" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorTransparent" />
<ImageButton
android:id="#+id/ib"
android:layout_width="#dimen/margin_35dp"
android:layout_height="#dimen/margin_35dp"
android:layout_gravity="right"
android:layout_marginRight="#dimen/margin_10dp"
android:layout_marginTop="#dimen/height_245dp"
android:background="#null"
android:src="#drawable/ic_launcher" />
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="#android:color/transparent"
android:popupTheme="#style/ThemeOverlay.AppCompat.Light"
app:contentInsetStart="#dimen/margin_50dp"
app:layout_collapseMode="pin">
<ImageButton
android:id="#+id/ib2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_marginRight="#dimen/margin_10dp"
android:background="#null"
android:popupTheme="#style/ThemeOverlay.AppCompat.Light"
android:src="#drawable/ic_launcher"
android:visibility="invisible" />
</android.support.v7.widget.Toolbar>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
After that in Fragment in IntializeComponents I am intialize this layout only and set Text
appBarLayout = (AppBarLayout)view.findViewById(R.id.app_bar_layout);
CollapsingToolbarLayout toolbarLayout = (CollapsingToolbarLayout) view.findViewById(R.id.collapsible_Toolbar_Layout);
toolbarLayout.setTitle(yourTitle);
toolbarLayout.setCollapsedTitleTextColor(Color.WHITE);
toolbarLayout.setExpandedTitleColor(Color.WHITE);
appBarLayout.addOnOffsetChangedListener(this);
Add this method for Handle the toolbar
#Override
public void onOffsetChanged(AppBarLayout appBarLayout, int offset) {
int maxScroll = appBarLayout.getTotalScrollRange();
float percentage = (float) Math.abs(offset) / (float) maxScroll;
handleToolbarTitleVisibility(percentage);
}
private void handleToolbarTitleVisibility(float percentage) {
if (percentage >= PERCENTAGE_TO_SHOW_TITLE_AT_TOOLBAR) {
if(!mIsTheTitleVisible) {
imageButton.setVisibility(View.VISIBLE);
ib.setVisibility(View.INVISIBLE);
mIsTheTitleVisible = true;
}
} else {
if (mIsTheTitleVisible) {
imageButton.setVisibility(View.INVISIBLE);
ibMap.setVisibility(View.VISIBLE);
mIsTheTitleVisible = false;
}
}
}
I hope it will helps you :)
No if you are using customTextview then also it will work because I am also using customTextView only.
Will you post the customtextview code here? So all can see the problem in your customTextview.

How to implement PdfRenderer Zoom and Scroll support?

I am trying to use PdfRenderer, and the requirement is to have Zoom and scroll available with it, but in Android PdfRenderer do not provide any support for Zoom and scroll, there is only page navigation support available.
But i guess zoom and scroll support can be implemented as PdfRenderer uses bitmap to show the content using imageview.
How to implement Zoom and Scroll support with Google PdfRenderer
sample?
PS: I am using this PdfRenderer sample provided by Google, https://github.com/googlesamples/android-PdfRendererBasic
I used the idea of #yan-yankelevich and wrote the code in Java. Much problem was with finding proper zoom and corresponding Bitmap size values. Don't forget that PdfRenderer works only on API 21+.
Fragment with PDF Bitmap fragment_pdf_renderer.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
android:orientation="vertical"
tools:context=".PdfRendererFragment">
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:contentDescription="#null" />
</HorizontalScrollView>
</ScrollView>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/from_divider_gray"
android:gravity="center_vertical"
android:orientation="horizontal">
<Button
android:id="#+id/previous"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/previous_page"
android:textSize="13sp" />
<Button
android:id="#+id/next"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="#string/next_page"
android:textSize="13sp" />
<ImageButton
android:id="#+id/zoomout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:padding="8dp"
android:src="#drawable/ic_zoom_out_black_36dp" />
<ImageButton
android:id="#+id/zoomin"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="0dp"
android:padding="8dp"
android:src="#drawable/ic_zoom_in_black_36dp" />
</LinearLayout>
</LinearLayout>
The PdfRendererFragment:
/**
* This fragment has a big {#ImageView} that shows PDF pages, and 2
* {#link android.widget.Button}s to move between pages. We use a
* {#link android.graphics.pdf.PdfRenderer} to render PDF pages as
* {#link android.graphics.Bitmap}s.
*/
#RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class PdfRendererFragment extends Fragment implements View.OnClickListener {
/**
* Key string for saving the state of current page index.
*/
private static final String STATE_CURRENT_PAGE_INDEX = "current_page_index";
/**
* The filename of the PDF.
*/
public String FILENAME;
public String PURCHASE_ID;
public int TICKETS_NUMBER;
/**
* File descriptor of the PDF.
*/
private ParcelFileDescriptor mFileDescriptor;
/**
* {#link android.graphics.pdf.PdfRenderer} to render the PDF.
*/
private PdfRenderer mPdfRenderer;
/**
* Page that is currently shown on the screen.
*/
private PdfRenderer.Page mCurrentPage;
/**
* {#link android.widget.ImageView} that shows a PDF page as a {#link android.graphics.Bitmap}
*/
private ImageView mImageView;
/**
* {#link android.widget.Button} to move to the previous page.
*/
private Button mButtonPrevious;
private ImageView mButtonZoomin;
private ImageView mButtonZoomout;
private Button mButtonNext;
private float currentZoomLevel = 12;
/**
* PDF page index
*/
private int mPageIndex;
public PdfRendererFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_pdf_renderer, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Retain view references.
mImageView = (ImageView) view.findViewById(R.id.image);
mButtonPrevious = (Button) view.findViewById(R.id.previous);
mButtonNext = (Button) view.findViewById(R.id.next);
mButtonZoomin = view.findViewById(R.id.zoomin);
mButtonZoomout = view.findViewById(R.id.zoomout);
// Bind events.
mButtonPrevious.setOnClickListener(this);
mButtonNext.setOnClickListener(this);
mButtonZoomin.setOnClickListener(this);
mButtonZoomout.setOnClickListener(this);
mPageIndex = 0;
// If there is a savedInstanceState (screen orientations, etc.), we restore the page index.
if (null != savedInstanceState) {
mPageIndex = savedInstanceState.getInt(STATE_CURRENT_PAGE_INDEX, 0);
}
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
FILENAME = getActivity().getIntent().getExtras().getString("pdfFilename");
TICKETS_NUMBER = getActivity().getIntent().getExtras().getInt("tickets_number");
PURCHASE_ID = getActivity().getIntent().getExtras().getString("purchaseGuid");
}
#Override
public void onStart() {
super.onStart();
try {
openRenderer(getActivity());
showPage(mPageIndex);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getActivity(), getString(R.string.ticket_file_not_found, FILENAME), Toast.LENGTH_SHORT).show();
App app = (App) getActivity().getApplicationContext();
TicketUtil.downloadTicket(app, PURCHASE_ID);
getActivity().finish();
}
}
#Override
public void onStop() {
try {
closeRenderer();
} catch (IOException e) {
e.printStackTrace();
}
super.onStop();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (null != mCurrentPage) {
outState.putInt(STATE_CURRENT_PAGE_INDEX, mCurrentPage.getIndex());
}
}
/**
* Sets up a {#link android.graphics.pdf.PdfRenderer} and related resources.
*/
private void openRenderer(Context context) throws IOException {
// In this sample, we read a PDF from the assets directory.
File file = TicketUtil.getTicketFile(context, PURCHASE_ID);
if (!file.exists()) {
// Since PdfRenderer cannot handle the compressed asset file directly, we copy it into
// the cache directory.
InputStream asset = context.getAssets().open(FILENAME);
FileOutputStream output = new FileOutputStream(file);
final byte[] buffer = new byte[1024];
int size;
while ((size = asset.read(buffer)) != -1) {
output.write(buffer, 0, size);
}
asset.close();
output.close();
}
mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
// This is the PdfRenderer we use to render the PDF.
if (mFileDescriptor != null) {
mPdfRenderer = new PdfRenderer(mFileDescriptor);
}
}
/**
* Closes the {#link android.graphics.pdf.PdfRenderer} and related resources.
*
* #throws java.io.IOException When the PDF file cannot be closed.
*/
private void closeRenderer() throws IOException {
if (null != mCurrentPage) {
mCurrentPage.close();
mCurrentPage = null;
}
if (null != mPdfRenderer) {
mPdfRenderer.close();
}
if (null != mFileDescriptor) {
mFileDescriptor.close();
}
}
/**
* Zoom level for zoom matrix depends on screen density (dpiAdjustedZoomLevel), but width and height of bitmap depends only on pixel size and don't depend on DPI
* Shows the specified page of PDF to the screen.
*
* #param index The page index.
*/
private void showPage(int index) {
if (mPdfRenderer.getPageCount() <= index) {
return;
}
// Make sure to close the current page before opening another one.
if (null != mCurrentPage) {
mCurrentPage.close();
}
// Use `openPage` to open a specific page in PDF.
mCurrentPage = mPdfRenderer.openPage(index);
// Important: the destination bitmap must be ARGB (not RGB).
int newWidth = (int) (getResources().getDisplayMetrics().widthPixels * mCurrentPage.getWidth() / 72 * currentZoomLevel / 40);
int newHeight = (int) (getResources().getDisplayMetrics().heightPixels * mCurrentPage.getHeight() / 72 * currentZoomLevel / 64);
Bitmap bitmap = Bitmap.createBitmap(
newWidth,
newHeight,
Bitmap.Config.ARGB_8888);
Matrix matrix = new Matrix();
float dpiAdjustedZoomLevel = currentZoomLevel * DisplayMetrics.DENSITY_MEDIUM / getResources().getDisplayMetrics().densityDpi;
matrix.setScale(dpiAdjustedZoomLevel, dpiAdjustedZoomLevel);
// Toast.makeText(getActivity(), "width " + String.valueOf(newWidth) + " widthPixels " + getResources().getDisplayMetrics().widthPixels, Toast.LENGTH_LONG).show();
// matrix.postTranslate(-rect.left/mCurrentPage.getWidth(), -rect.top/mCurrentPage.getHeight());
// Here, we render the page onto the Bitmap.
// To render a portion of the page, use the second and third parameter. Pass nulls to get
// the default result.
// Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
mCurrentPage.render(bitmap, null, matrix, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
// We are ready to show the Bitmap to user.
mImageView.setImageBitmap(bitmap);
updateUi();
}
/**
* Updates the state of 2 control buttons in response to the current page index.
*/
private void updateUi() {
int index = mCurrentPage.getIndex();
int pageCount = mPdfRenderer.getPageCount();
if (pageCount == 1) {
mButtonPrevious.setVisibility(View.GONE);
mButtonNext.setVisibility(View.GONE);
} else {
mButtonPrevious.setEnabled(0 != index);
mButtonNext.setEnabled(index + 1 < pageCount);
}
if (currentZoomLevel == 2) {
mButtonZoomout.setActivated(false);
} else {
mButtonZoomout.setActivated(true);
}
}
/**
* Gets the number of pages in the PDF. This method is marked as public for testing.
*
* #return The number of pages.
*/
public int getPageCount() {
return mPdfRenderer.getPageCount();
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.previous: {
// Move to the previous page
currentZoomLevel = 12;
showPage(mCurrentPage.getIndex() - 1);
break;
}
case R.id.next: {
// Move to the next page
currentZoomLevel = 12;
showPage(mCurrentPage.getIndex() + 1);
break;
}
case R.id.zoomout: {
// Move to the next page
--currentZoomLevel;
showPage(mCurrentPage.getIndex());
break;
}
case R.id.zoomin: {
// Move to the next page
++currentZoomLevel;
showPage(mCurrentPage.getIndex());
break;
}
}
}
}
Bring your attention to the fact that zoom level depends on your screen density, but width and height of Bitmap (it is in pixels) depend only on your zoom level. Also, you need to tweak your sizes so that at default zoom (for me it was pdf rendered full screen and value was 12) you PDF bitmap takes no more and no less than needed in your View.
int newWidth = (int) (getResources().getDisplayMetrics().widthPixels * mCurrentPage.getWidth() / 72 * currentZoomLevel / 40);
int newHeight = (int) (getResources().getDisplayMetrics().heightPixels * mCurrentPage.getHeight() / 72 * currentZoomLevel / 64);
Bitmap bitmap = Bitmap.createBitmap(
newWidth,
newHeight,
Bitmap.Config.ARGB_8888);
I found out that zoom 12 fits my screen and 40 and 64 are coefficents that make Bitmap proper size.
mCurrentPage.getWidth() returns width in Postscript points, where each pt is 1/72 inch.
72 (DPI) is the default PDF resolution.
PS. If you need simultaneous vertical and horizontal scroll Scrollview vertical and horizontal in android
The solution i used when confronted to this situation was :
Load the pdfRenderer page in a ImageView
Put my ImageView in a ScrollView (tadam scroll managed), and this ScrollView in a FrameLayout
Add two buttons (outside the scroll view) to manage zoom in and out (each button triggering a scale animation on my ImageView). You could also manage it with a gesture detector but i had hard time with the scrolling behaviour when doing so
Add two buttons to manage page changes (still outside the ScrollView)
For a nice effect i added FadeIn/FadeOut animations on my buttons, FadeIn triggering on OnTouchEvents (if no animation is playing), and FadeOut triggering when FadeIn animation is over
Hope i helped, aks me if you need more detailed informations, but you should know where to start now
Here is a code sample (wich do not inclue page navigation etc, but only zoom behaviour and scrolling, as the rest being in the google code sample you linked)
Code :
C# (but very easy to convert into Java)
private Button _zoomInButton;
private Button _zoomOutButton;
private ImageView _pdfViewContainer;
private float _currentZoomLevel;
private float _zoomFactor;
private float _maxZoomLevel;
private float _minZoomLevel;
private void Init(View view) // the content of this method must go in your OnViewCreated method, here the view being the frameLayout you will find in xml
{
_zoomInButton = view.FindViewById<Button>(Resource.Id.PdfZoomInButton);
_zoomOutButton = view.FindViewById<Button>(Resource.Id.PdfZoomOutButton);
_pdfViewContainer = view.FindViewById<ImageView>(Resource.Id.PdfViewContainer);
_zoomInButton.Click += delegate { ZoomIn(); }; //for you (in Java) this must looks like setOnClickListener(this); and in the onClick metghod you just have to add a case for R.id.PdfZoomInButton containing a call to ZoomIn();
_zoomOutButton.Click += delegate { ZoomOut(); };
_minZoomLevel = 0.9f;
_maxZoomLevel = 1.2f;
_zoomFactor = 0.1f;
}
private void ZoomIn()
{
if (_currentZoomLevel + _zoomFactor < _maxZoomLevel)
{
ScaleAnimation scale = new ScaleAnimation(_currentZoomLevel, _currentZoomLevel + _zoomFactor, _currentZoomLevel, _currentZoomLevel + _zoomFactor, Dimension.RelativeToSelf, 0.5f, Dimension.RelativeToSelf, 0.5f);
scale.Duration = 50;
scale.FillAfter = true;
_pdfViewContainer.StartAnimation(scale);
_currentZoomLevel += _zoomFactor;
}
}
private void ZoomOut()
{
if (_currentZoomLevel - _zoomFactor > _minZoomLevel)
{
ScaleAnimation scale = new ScaleAnimation(_currentZoomLevel, _currentZoomLevel - _zoomFactor, _currentZoomLevel, _currentZoomLevel - _zoomFactor, Dimension.RelativeToSelf, 0.5f, Dimension.RelativeToSelf, 0.5f);
scale.Duration = 50;
scale.FillAfter = true;
_pdfViewContainer.StartAnimation(scale);
_currentZoomLevel -= _zoomFactor;
}
}
XMl
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/PdfContainer">
<ScrollView xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:id="#+id/PdfScrollView">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitCenter"
android:adjustViewBounds="true"
android:scrollbars="vertical"
android:src="#drawable/mediaIconPDF"
android:id="#+id/PdfViewContainer" />
</ScrollView>
<LinearLayout
android:id="#+id/PdfRightLayout"
android:layout_gravity="right"
android:orientation="vertical"
android:gravity="center"
android:layout_width="50dp"
android:layout_height="match_parent"
android:weightSum="1">
<Button
android:id="#+id/PdfZoomInButton"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="+" />
<space
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.2" />
<Button
android:id="#+id/PdfZoomOutButton"
android:layout_width="match_parent"
android:layout_height="50dp"
android:text="-" />
</LinearLayout>
<LinearLayout
android:id="#+id/PdfBottomLayout"
android:layout_gravity="bottom"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#color/vogofTransparentGrey"
android:weightSum="1">
<Button
android:id="#+id/PdfPreviousPage"
android:layout_width="0dp"
android:layout_weight="0.15"
android:layout_height="match_parent"
android:text="Prev" />
<TextView
android:id="#+id/PdfCurrentPageLabel"
android:layout_width="0dp"
android:layout_weight="0.7"
android:gravity="center"
android:layout_height="match_parent"
/>
<Button
android:id="#+id/PdfNextPage"
android:layout_width="0dp"
android:layout_weight="0.15"
android:layout_height="match_parent"
android:text="Next" />
</LinearLayout>
</FrameLayout>
With this, some time to understand it and little efforts you should be able to get the desired result. Have a nice day
I found a nicer answer here: PdfRendering zoom on page linked by CommonsWare: https://github.com/commonsguy/cw-omnibus/tree/v8.8/PDF/PdfRenderer . So based on soshial's answer, you have pinch zoom and can get rid of the zoom buttons and the constants:
import com.davemorrissey.labs.subscaleview.ImageSource;
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
....
private void showPage(int index) {
if (mPdfRenderer.getPageCount() <= index) {
return;
}
// Make sure to close the current page before opening another one.
if (null != mCurrentPage) {
mCurrentPage.close();
}
// Use `openPage` to open a specific page in PDF.
mCurrentPage = mPdfRenderer.openPage(index);
if(mBitmap==null) {
// Important: the destination bitmap must be ARGB (not RGB).
int newWidth = (int) (getResources().getDisplayMetrics().densityDpi * mCurrentPage.getWidth() / 72);
int newHeight = (int) (getResources().getDisplayMetrics().densityDpi * mCurrentPage.getHeight() / 72);
mBitmap = Bitmap.createBitmap(
newWidth,
newHeight,
Bitmap.Config.ARGB_8888);
}
mBitmap.eraseColor(0xFFFFFFFF);
mCurrentPage.render(mBitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
// We are ready to show the Bitmap to user.
mSubsamplingImageView.resetScaleAndCenter();
mSubsamplingImageView.setImage(ImageSource.cachedBitmap(mBitmap));
updateUi();
}
I also added bitmap recycle:
/**
* Closes the {#link android.graphics.pdf.PdfRenderer} and related resources.
*
* #throws java.io.IOException When the PDF file cannot be closed.
*/
private void closeRenderer() throws IOException {
if (null != mCurrentPage) {
mCurrentPage.close();
mCurrentPage = null;
}
if (null != mPdfRenderer) {
mPdfRenderer.close();
}
if (null != mFileDescriptor) {
mFileDescriptor.close();
}
if(mBitmap!=null)
{
mBitmap.recycle();
mBitmap = null;
}
}
And in the xml, instead of ImageView:
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
android:id="#+id/report_viewer_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Starting with this solution : https://stackoverflow.com/a/46002017/5049286 I found a good way to avoid the initial zoom coefficient and the others fixed coefficients, only changed this method :
private void showPage(int index) {
if (mPdfRenderer.getPageCount() <= index) {
return;
}
if (null != mCurrentPage) {
mCurrentPage.close();
}
mCurrentPage = mPdfRenderer.openPage(index);
int newWidth = (int) (mVerticalScrollView.getWidth() *
currentZoomLevel);
int newHeight = (int) (newWidth *
((float)mCurrentPage.getHeight()/(float)mCurrentPage.getWidth()));
Bitmap bitmap = Bitmap.createBitmap(
newWidth,
newHeight,
Bitmap.Config.ARGB_8888);
mCurrentPage.render(bitmap, null, null,
PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
mImageView.setImageBitmap(bitmap);
updateUi();
}
With this solution currentZoomLevel starts from 1.0f to xxx ( you decide a limit ) and the rendered image at zoom 1.0f fit into the scrollview and the proportions are maintained...

Android: how to get default camera settings of builtin camera application

I have seen lots of tutorial and information but i could not find any single place how to use the default settings of the existing camera application into any other customized camera application. I have seen the sharpness of the image and its focus is very fine in the built-in camera application. Now i am creating my own application with my customized features but i am still unable to make it sharp and non-blurry... I dont want to use Intent technique of the camera because i have to do some image processing afterward.
I have used zooming but strangely zoom is not properly working ...like it works in built-in camera application
here is my surface change code
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
{
Log.e(TAG, "surfaceChanged");
// XXX stopPreview() will crash if preview is not running
if (mPreviewRunning) {
mCamera.stopPreview();
}
Camera.Parameters params = mCamera.getParameters();
List<Camera.Size> sizes = params.getSupportedPreviewSizes();
mFrameWidth = w;
mFrameHeight = h;
// selecting optimal camera preview size
{
double minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes)
{
if (Math.abs(size.height - h) < minDiff)
{
mFrameWidth = size.width;
mFrameHeight = size.height;
minDiff = Math.abs(size.height - h);
}
}
}
try
{
//params.set("rotation", 180);
//params.set("orientation", "landscape");
//params.set("auto", "WHITE_BALANCE_AUTO");//WHITE_BALANCE_AUTO
Display display = ((WindowManager)getSystemService(WINDOW_SERVICE)).getDefaultDisplay();
if(display.getRotation() == Surface.ROTATION_0)
{
params.setPreviewSize(mFrameHeight, mFrameWidth);
mCamera.setDisplayOrientation(90);
}
if(display.getRotation() == Surface.ROTATION_90)
{
params.setPreviewSize(mFrameWidth, mFrameHeight);
}
if(display.getRotation() == Surface.ROTATION_180)
{
params.setPreviewSize(mFrameHeight, mFrameWidth);
}
if(display.getRotation() == Surface.ROTATION_270)
{
params.setPreviewSize(mFrameWidth, mFrameHeight);
mCamera.setDisplayOrientation(180);
}
if(params.isZoomSupported())
{
Log.e(TAG, params.getZoom()+"surfaceChanged camer zoom"+params.getMinExposureCompensation());
params.setZoom(params.getMaxZoom());
params.setExposureCompensation(1);
// params.setColorEffect("none");
params.setWhiteBalance(params.WHITE_BALANCE_AUTO);
params.setFocusMode(params.FOCUS_MODE_AUTO);
params.setSceneMode(params.SCENE_MODE_ACTION);
}
params.set("auto", "FOCUS_MODE_AUTO");
params.setPreviewSize(mFrameWidth,mFrameHeight);
mCamera.setParameters(params);
mCamera.setPreviewDisplay(holder);
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
Kindly let me know how to make the camera preview exactly same as the built in application one.
You mean a fullscreen camera preview?
I use this code:
this.requestWindowFeature(Window.FEATURE_NO_TITLE); //no title
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //no status bar, etc
and this:
setContentView(R.layout.main);
addContentView(overlay, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
((FrameLayout) findViewById(R.id.preview)).addView(preview);
the first snippet sets the app to fullscreen and hide title and status bar.
the second snipppet adds my overlay (extended View) to the main layout.
Here my xml and java code:
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/preview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher" />
</LinearLayout>
Overlay.java:
class Overlay extends View {
String text = "";
String textBearing = "Bearing: ";
public Overlay(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
paint.setTextSize(16);
canvas.drawText(text, 20, 20, paint);
canvas.drawText(textBearing, 20, 50, paint);
super.onDraw(canvas);
}
}
And my activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE); //no title
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //fullscreen
overlay = new Overlay(this);
setContentView(R.layout.main);
addContentView(overlay, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
camera = getCameraInstance(); //camera.open();
preview = new Preview(this, camera);
((FrameLayout) findViewById(R.id.preview)).addView(preview);
}
Hope it helps
I encountered the same problem with you. After reading the source code of the builtin camera app, and comparing the focus processing of builtin camera and my own camera, I realized the problem is on autofocus.
So try this:
mCamera.autoFocus(new Camera.AutoFocusCallback() {
#Override
public void onAutoFocus(boolean success, Camera camera) {
mCamera.takePicture(null, null, mPicture);
}
});
which makes the result image as sharp as builtin camera.
The documents is here.

Categories