Skip to content

Commit

Permalink
Added clipping prompt to activity bounds
Browse files Browse the repository at this point in the history
Closes #2
  • Loading branch information
sjwall committed Jun 12, 2016
1 parent ffeaaea commit e28a328
Show file tree
Hide file tree
Showing 7 changed files with 222 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import android.support.annotation.ColorRes;
import android.support.annotation.DimenRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.IdRes;
import android.support.annotation.StringRes;
import android.text.Layout;
import android.text.StaticLayout;
Expand Down Expand Up @@ -77,6 +78,8 @@ public class MaterialTapTargetPrompt
private boolean mDismissing;
private ViewGroup mParentView;
private boolean mParentViewIsDecor;
private ViewGroup mClipToView;
private final float mStatusBarHeight;

MaterialTapTargetPrompt(final Activity activity)
{
Expand Down Expand Up @@ -107,6 +110,16 @@ public void onHidePromptComplete()
//Not used
}
};

int resourceId = mView.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
{
mStatusBarHeight = mView.getResources().getDimensionPixelSize(resourceId);
}
else
{
mStatusBarHeight = 0;
}
}

private ViewGroup getParentView()
Expand Down Expand Up @@ -148,6 +161,8 @@ public void show()
parent.addView(mView);
}

updateFocalCentrePosition();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
{
startRevealAnimation();
Expand Down Expand Up @@ -462,6 +477,12 @@ private void updateFocalCentrePosition()
{
mView.mCentreLeft += mTargetView.getTranslationX();
mView.mCentreTop += mTargetView.getTranslationY();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
&& ((ViewGroup) mActivity.findViewById(android.R.id.content)).getChildAt(0).getFitsSystemWindows())
{
mView.mCentreTop -= mStatusBarHeight;
}
}
}
else
Expand All @@ -470,12 +491,6 @@ private void updateFocalCentrePosition()
mView.mCentreTop = mBaseTop;
}

//If the view was not added to the decor view remove the status bar height
if (!mParentViewIsDecor)
{
mView.mCentreTop -= mView.mClipBoundsTop;
}

final ViewGroup parent = getParentView();
mTextPositionAbove = mView.mCentreTop > parent.getHeight() / 2;
mTextPositionRight = mView.mCentreLeft > parent.getWidth() / 2;
Expand Down Expand Up @@ -566,6 +581,38 @@ else if (mView.mTargetView != null)
mView.mIconDrawableLeft = mView.mCentreLeft - (mView.mTargetView.getWidth() / 2);
mView.mIconDrawableTop = mView.mCentreTop - (mView.mTargetView.getHeight() / 2);
}
updateClipBounds();
}

private void updateClipBounds()
{
if (mClipToView != null && mClipToView.getLayoutParams() instanceof ViewGroup.MarginLayoutParams)
{
final ViewGroup.MarginLayoutParams margins = (ViewGroup.MarginLayoutParams) mClipToView.getLayoutParams();
mView.mClipBounds = true;
mView.mClipBoundsLeft = mClipToView.getLeft() + margins.leftMargin;
mView.mClipBoundsBottom = mClipToView.getBottom() - margins.bottomMargin;
mView.mClipBoundsTop = mClipToView.getTop() + margins.topMargin;
mView.mClipBoundsRight = mClipToView.getRight() - margins.rightMargin;
if (mParentViewIsDecor)
{
mView.mClipBoundsTop += mStatusBarHeight;
mView.mClipBoundsBottom += mStatusBarHeight;
}
}
else if (mParentViewIsDecor)
{
mView.mClipBounds = true;
//Stop the canvas drawing over the status bar
mView.mClipBoundsTop = mStatusBarHeight;
mView.mClipBoundsLeft = 0f;
mView.mClipBoundsBottom = mActivity.getResources().getDisplayMetrics().heightPixels - mStatusBarHeight;
mView.mClipBoundsRight = mActivity.getResources().getDisplayMetrics().widthPixels;
}
else
{
mView.mClipBounds = false;
}
}

protected void onHidePrompt(final MotionEvent event, final boolean targetTapped)
Expand Down Expand Up @@ -601,32 +648,22 @@ static class PromptView extends View
private boolean mDrawRipple = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
private OnHidePromptListener mOnHidePromptListener;
private boolean mCaptureTouchEventOnFocal;
private float mClipBoundsTop;
private float mClipBoundsWidth;
private float mClipBoundsHeight;
private float mClipBoundsTop, mClipBoundsLeft, mClipBoundsBottom, mClipBoundsRight;
private View mTargetView;
private float mTextSeparation;
private boolean mClipBounds;

public PromptView(final Context context)
{
super(context);
//Stop the canvas drawing over the status bar
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
{
mClipBoundsTop = getResources().getDimensionPixelSize(resourceId);
}
mClipBoundsWidth = getResources().getDisplayMetrics().widthPixels;
mClipBoundsHeight = getResources().getDisplayMetrics().heightPixels;
}

@Override
public void onDraw(final Canvas canvas)
{
if (mClipBounds)
{
canvas.clipRect(0, mClipBoundsTop, mClipBoundsWidth, mClipBoundsHeight);
canvas.clipRect(mClipBoundsLeft, mClipBoundsTop, mClipBoundsRight, mClipBoundsBottom);
}

//Draw the backgrounds
Expand Down Expand Up @@ -795,6 +832,18 @@ public Builder setTarget(final View target)
return this;
}

/**
* Set the view for the prompt to focus on using the given resource id.
*
* @return This Builder object to allow for chaining of calls to set methods
*/
public Builder setTarget(@IdRes final int target)
{
mTargetView = mActivity.findViewById(target);
mTargetSet = mTargetView != null;
return this;
}

/**
* Set the centre point as a screen position
* @param left Centre point from screen left
Expand All @@ -810,6 +859,16 @@ public Builder setTarget(final float left, final float top)
return this;
}

/**
* Has the target been set successfully?
*
* @return True if set successfully.
*/
public boolean isTargetSet()
{
return mTargetSet;
}

/**
* Set the primary text using the given resource id.
*
Expand Down Expand Up @@ -1193,14 +1252,8 @@ public MaterialTapTargetPrompt create()
{
mPrompt.mBaseLeft = mCentreLeft;
mPrompt.mBaseTop = mCentreTop;

//As the view is added to the decor view group the status bar height needs to be taken into account
int resourceId = mActivity.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0)
{
mPrompt.mBaseTop += mActivity.getResources().getDimensionPixelSize(resourceId);
}
}
mPrompt.mClipToView = (ViewGroup) ((ViewGroup) mActivity.findViewById(android.R.id.content)).getChildAt(0);

mPrompt.mPrimaryText = mPrimaryText;
mPrompt.mPrimaryTextColourAlpha = Color.alpha(mPrimaryTextColour);
Expand Down Expand Up @@ -1253,8 +1306,6 @@ public MaterialTapTargetPrompt create()
mPrompt.mPaintSecondaryText.setAntiAlias(true);
mPrompt.mPaintSecondaryText.setTextSize(mSecondaryTextSize);

mPrompt.updateFocalCentrePosition();

return mPrompt;
}

Expand Down
20 changes: 13 additions & 7 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@
~ 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.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="uk.co.samuelwall.materialtaptargetprompt.sample">
-->
<manifest package="uk.co.samuelwall.materialtaptargetprompt.sample"
xmlns:android="http://schemas.android.com/apk/res/android">

<application
android:allowBackup="true"
Expand All @@ -25,15 +24,22 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name="uk.co.samuelwall.materialtaptargetprompt.sample.MainActivity"
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.MAIN"/>

<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".DialogStyleActivity"
android:theme="@style/AppTheme.Dialog"
android:parentActivityName=".MainActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2016 Samuel Wall
*
* Licensed under the Apache License, Version 2.0 (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-2.0
*
* 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.
*/

package uk.co.samuelwall.materialtaptargetprompt.sample;

import android.os.Bundle;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;

import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt;

public class DialogStyleActivity extends AppCompatActivity
{

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialog_style);

final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

public void showPrompt(View view)
{
new MaterialTapTargetPrompt.Builder(this)
.setTarget(R.id.fab)
.setAnimationInterpolator(new FastOutSlowInInterpolator())
.setPrimaryText("Clipped to activity bounds")
.setSecondaryText("The prompt does not draw outside the activity")
.show();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package uk.co.samuelwall.materialtaptargetprompt.sample;

import android.content.Intent;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
Expand Down Expand Up @@ -130,6 +131,11 @@ public void showStylePrompt(View view)
new MaterialTapTargetPrompt.Builder(this, R.style.MaterialTapTargetPromptTheme_FabTarget).show();
}

public void showDialog(View view)
{
startActivity(new Intent(this, DialogStyleActivity.class));
}

@Override
protected void onCreate(Bundle savedInstanceState)
{
Expand Down
52 changes: 52 additions & 0 deletions sample/src/main/res/layout/activity_dialog_style.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (C) 2016 Samuel Wall
~
~ Licensed under the Apache License, Version 2.0 (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-2.0
~
~ 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.
-->

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="200dp"
android:minHeight="400dp"
android:layout_gravity="center"
android:background="@android:color/white"
tools:context="uk.co.samuelwall.materialtaptargetprompt.sample.DialogStyleActivity">

<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.AppBarOverlay">

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />

</android.support.design.widget.AppBarLayout>

<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"

android:onClick="showPrompt" android:src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>
10 changes: 10 additions & 0 deletions sample/src/main/res/layout/content_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,14 @@
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:onClick="showStylePrompt"/>

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dialog"
android:id="@+id/button_dialog"
android:layout_below="@+id/button_overflow"
android:layout_toRightOf="@+id/button_nav"
android:layout_toEndOf="@+id/button_nav"
android:onClick="showDialog"/>
</RelativeLayout>
Loading

0 comments on commit e28a328

Please sign in to comment.