I have been banging my head for days to find some help but maybe I am not looking at the right place.
I am following this article to replicate Twitter like button animation (I don't want to use rebuilt libraries) - http://frogermcs.github.io/twitters-like-animation-in-android-alternative/
I have a Custom View called LikeButtonView
public class LikeButtonView : FrameLayout, View.IOnClickListener
{
private static DecelerateInterpolator DECCELERATE_INTERPOLATOR = new DecelerateInterpolator();
private static AccelerateDecelerateInterpolator ACCELERATE_DECELERATE_INTERPOLATOR = new AccelerateDecelerateInterpolator();
private static OvershootInterpolator OVERSHOOT_INTERPOLATOR = new OvershootInterpolator(4);
private ImageView ivStar;
private DotsView vDotsView;
private AnimatorSet animatorSet;
public LikeButtonView(Context context, IAttributeSet attrs) :
base(context, attrs)
{
Initialize();
}
public LikeButtonView(Context context, IAttributeSet attrs, int defStyle) :
base(context, attrs, defStyle)
{
Initialize();
}
public void OnClick(View v)
{
vDotsView.setCurrentProgress(0);
animatorSet = new AnimatorSet();
ObjectAnimator starScaleYAnimator = ObjectAnimator.OfFloat(ivStar, ImageView.ScaleYs, 0.2f, 1f);
starScaleYAnimator.SetDuration(350);
starScaleYAnimator.StartDelay = (250);
starScaleYAnimator.SetInterpolator(OVERSHOOT_INTERPOLATOR);
ObjectAnimator starScaleXAnimator = ObjectAnimator.OfFloat(ivStar, ImageView.ScaleXs, 0.2f, 1f);
starScaleXAnimator.SetDuration(350);
starScaleXAnimator.StartDelay = (250);
starScaleXAnimator.SetInterpolator(OVERSHOOT_INTERPOLATOR);
ObjectAnimator dotsAnimator = ObjectAnimator.OfFloat(vDotsView, DotsView.DOTS_PROGRESS, 0.2f, 1f);
dotsAnimator.SetDuration(900);
dotsAnimator.StartDelay = (50);
dotsAnimator.SetInterpolator(ACCELERATE_DECELERATE_INTERPOLATOR);
animatorSet.PlayTogether(
starScaleYAnimator,
starScaleXAnimator,
dotsAnimator
);
animatorSet.Start();
}
private void Initialize()
{
var INF = LayoutInflater.From(Context).Inflate(Resource.Layout.view_like_button, this, true);
ivStar = INF.FindViewById<ImageView>(Resource.Id.ivStar);
vDotsView = INF.FindViewById<DotsView>(Resource.Id.vDotsView);
SetOnClickListener(this);
}
}
I am also using private DotsView vDotsView which is another custom view, which is a C# Replica of this view https://github.com/frogermcs/LikeAnimation/blob/master/app/src/main/java/frogermcs/io/likeanimation/DotsView.java
In the above link, right at the end, I see the following
public static final Property<DotsView, Float> DOTS_PROGRESS = new Property<DotsView, Float>(Float.class, "dotsProgress") {
#Override
public Float get(DotsView object) {
return object.getCurrentProgress();
}
#Override
public void set(DotsView object, Float value) {
object.setCurrentProgress(value);
}
};
It is Android.Util.Property getting used to get and set the progress
ObjectAnimator dotsAnimator = ObjectAnimator.OfFloat(vDotsView, DotsView.DOTS_PROGRESS, 0.2f, 1f);
I am lost right here, I do not know how to implement this in C#? I have been trying different things but no luck with implementing public static final Property<DotsView, Float> DOTS_PROGRESS with exact parameters.
If anyone can help would be highly appreciated.
If this helps anyone, we can do something like the following
[Register("DOTS_PROGRESS")]
public static Property DotsProgress {
get {
JniObjectReference objectValue = _members.get_StaticFields().GetObjectValue("DOTS_PROGRESS.Landroid/util/Property;");
return Object.GetObject<Property>(objectValue.get_Handle(), 1);
}
}
Found this package which was converted from java to C#
https://www.fuget.org/packages/Karamunting.Android.HanksZyh.SmallBang/1.2.2/lib/monoandroid81/SmallBang.dll/Hanks.Library.Bang/DotsView?code=true
Related
I have generated simple black with square corners for QR code using com.google.zxing:core:3.3.3.
I want to customize QR code appearance like Instagram.
This library is used at many places https://github.com/scola/Qart
How to make square edges rounded? like below image :
You can create custom class like
private static class CustomViewFinderView extends ViewFinderView {
public final Paint PAINT = new Paint();
public CustomViewFinderView(Context context) {
super(context);
init();
}
public CustomViewFinderView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
// paint initialization
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// Here you can draw your view using canvas with edges
}
}
After that while you initialize your ZXingScannerView add your custom view in createViewFinderView method.
ZXingScannerView mScannerView = new ZXingScannerView(this) {
#Override
protected IViewFinder createViewFinderView(Context context) {
return new CustomViewFinderView(context);
}
};
How can i change letter spacing in a textview?
Will it help if I have HTML text in it (I cannot use webview in my code).
P.S. I'm using my own typeface in the textview with HTML text.
Since API 21 there is an option set letter spacing. You can call method setLetterSpacing or set it in XML with attribute letterSpacing.
More space:
android:letterSpacing="0.1"
Less space:
android:letterSpacing="-0.07"
check out android:textScaleX
Depending on how much spacing you need, this might help. That's the only thing remotely related to letter-spacing in the TextView.
Edit: please see #JerabekJakub's response below for an updated, better method to do this starting with api 21 (Lollipop)
This answer is based on Pedro's answer but adjusted so it also works if text attribute is already set:
package nl.raakict.android.spc.widget;
import android.content.Context;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ScaleXSpan;
import android.util.AttributeSet;
import android.widget.TextView;
public class LetterSpacingTextView extends TextView {
private float letterSpacing = LetterSpacing.BIGGEST;
private CharSequence originalText = "";
public LetterSpacingTextView(Context context) {
super(context);
}
public LetterSpacingTextView(Context context, AttributeSet attrs){
super(context, attrs);
originalText = super.getText();
applyLetterSpacing();
this.invalidate();
}
public LetterSpacingTextView(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
}
public float getLetterSpacing() {
return letterSpacing;
}
public void setLetterSpacing(float letterSpacing) {
this.letterSpacing = letterSpacing;
applyLetterSpacing();
}
#Override
public void setText(CharSequence text, BufferType type) {
originalText = text;
applyLetterSpacing();
}
#Override
public CharSequence getText() {
return originalText;
}
private void applyLetterSpacing() {
if (this == null || this.originalText == null) return;
StringBuilder builder = new StringBuilder();
for(int i = 0; i < originalText.length(); i++) {
String c = ""+ originalText.charAt(i);
builder.append(c.toLowerCase());
if(i+1 < originalText.length()) {
builder.append("\u00A0");
}
}
SpannableString finalText = new SpannableString(builder.toString());
if(builder.toString().length() > 1) {
for(int i = 1; i < builder.toString().length(); i+=2) {
finalText.setSpan(new ScaleXSpan((letterSpacing+1)/10), i, i+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
super.setText(finalText, BufferType.SPANNABLE);
}
public class LetterSpacing {
public final static float NORMAL = 0;
public final static float NORMALBIG = (float)0.025;
public final static float BIG = (float)0.05;
public final static float BIGGEST = (float)0.2;
}
}
If you want to use it programatically:
LetterSpacingTextView textView = new LetterSpacingTextView(context);
textView.setSpacing(10); //Or any float. To reset to normal, use 0 or LetterSpacingTextView.Spacing.NORMAL
textView.setText("My text");
//Add the textView in a layout, for instance:
((LinearLayout) findViewById(R.id.myLinearLayout)).addView(textView);
after API >=21 there is inbuild method provided by TextView called setLetterSpacing
check this for more
I built a custom class that extends TextView and solves this problem... Check out my answer here =)
As android doesn't support such a thing, you can do it manually with FontCreator. It has good options for font modifying.
I used this tool to build a custom font, even if it takes some times but you can always use it in your projects.
For embedding HTML text in your textview you can use Html.fromHTML() syntax.
More information you will get from http://developer.android.com/reference/android/text/Html.html#fromHtml%28java.lang.String%29
There is such issue, I have horizontal RecyclerView where each cell less than width of screen.
So I found a solution here
RecyclerVIew auto scroll to display all the elements as in News Feed etc.,
All work excellent if one cell take whole width of the screen otherwise(if each cell take 95% of screen width) every auto swipe place the cell at the beginner of screen (right side) and it is logical. So at the end of one visible cell it is start of another cell
it is doesn't looks good. I need this cell to be at the middle of the screen like this.
I need to see previous cell - current - next one
Now I would like to explain some magic how I make current smooth scroll (as I mentioned at link above)
this method in my CustomLinnearLayoutManager
#Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position)
{
LinearSmoothScroller linearSmoothScroller = new LinearSmoothScroller(recyclerView.getContext())
{
#Override
public PointF computeScrollVectorForPosition(int targetPosition)
{
return SmoothLayoutManager.this.computeScrollVectorForPosition(targetPosition);
}
#Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics)
{
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
};
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
But this method works without offset
I found out one more method that can provide desired offset
scrollToPositionWithOffset(final int position, final int offset)
And it is looks like exactly what I need , but this method works without smooth animation.
So, eventually my question is : how to apply animation logic from first method to second (that with offset)
Feel free to ask
To auto snapping and showing one item at center of RecyclerView, simply you need to use LinearSnapHelper like following:
LinearSnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(recyclerView);
If you want to scroll to a specific item programmatically, LinearSnapHelper handles snapping functionality too.
SmoothScroller smoothScroller = new LinearSmoothScroller(recyclerView.getContext()) {
#Override
protected int getVerticalSnapPreference() {
return LinearSmoothScroller.SNAP_TO_ANY;
}
#Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return 120f / displayMetrics.densityDpi;
}
};
...
smoothScroller.setTargetPosition(position);
recyclerView.getLayoutManager().startSmoothScroll(smoothScroller);
Here is the visual result:
.
..................Manually Scrolling...........................Programmatically Scrolling..........
Eventually, I found the way thanks a lot to #aminography for his answer and also one more answer help me a lot
https://stackoverflow.com/a/39654328
Actually now I have such implementation
My custom LinnearLayoutManager implementation
public class SmoothLayoutManager extends LinearLayoutManager
{
public static final int X_25 = 25;
public static final int X_200 = 200;
public static final float DEFAULT = X_25;
/**
* !! IMPORTANT !!
* If you need to add new value, don't forget add it here also
*/
#Retention(RetentionPolicy.SOURCE)
#IntDef({X_25, X_200})
private #interface Speed
{
}
private static float MILLISECONDS_PER_INCH = DEFAULT;
public SmoothLayoutManager(Context context)
{
super(context);
}
public SmoothLayoutManager(Context context, int orientation, boolean reverseLayout)
{
super(context, orientation, reverseLayout);
}
public SmoothLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)
{
super(context, attrs, defStyleAttr, defStyleRes);
}
public SmoothLayoutManager setSpeedOfSmooth(#Speed int iSpeed)
{
MILLISECONDS_PER_INCH = iSpeed;
return this;
}
#Override
public void scrollToPositionWithOffset(final int position, final int offset)
{
super.scrollToPositionWithOffset(position, offset);
}
#Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position)
{
RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(recyclerView.getContext())
{
#Override
public PointF computeScrollVectorForPosition(int targetPosition)
{
return SmoothLayoutManager.this.computeScrollVectorForPosition(targetPosition);
}
#Override
protected int getVerticalSnapPreference()
{
return LinearSmoothScroller.SNAP_TO_ANY;
}
#Override
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics)
{
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
}
#Override
public int calculateDtToFit(final int viewStart, final int viewEnd, final int boxStart, final int boxEnd, final int snapPreference)
{
return (boxStart + (boxEnd - boxStart) / 2) - (viewStart + (viewEnd - viewStart) / 2);
}
};
smoothScroller.setTargetPosition(position);
startSmoothScroll(smoothScroller);
}
}
And this is how I make set
private void setRv(Context iC)
{
RecyclerView.Adapter adapter = new UpSaleInnerAdapter(mPicasso, mInflater, iLink -> mListener.onButtonClick(iLink));
mRv.setLayoutManager(new SmoothLayoutManager(iC, LinearLayoutManager.HORIZONTAL, false).setSpeedOfSmooth(SmoothLayoutManager.X_200));
mRv.setAdapter(adapter);
SnapHelper snapHelper = new LinearSnapHelper();
snapHelper.attachToRecyclerView(mRv);
}
Note :
I noticed that sometimes if you make fast swipe, so SnapHelper a little bit confused and pass more cells that need... like a turbo mode :)
If someone will find how to fix it, let me know.
Thanks!
I have created a custom View that will display a circle (the idea is that the user will be able to interact with this "ball" in various ways)
From my main activity class, I want to adjust some of the "ball's" properties, in this case change its color.
My problem is that nothing happens (no errors either, the app runs but doesn't do what I want) when I try to call the various methods from my MainActivity class, but if I do it from CircleView class, it works (for example changing the color upon touch)
Here is my custom View class (CircleView.java):
public class CircleView extends View {
private int circleColor = Color.GREEN;
private Paint paint;
public CircleView(Context context) {
super(context);
init(context, null);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_SCROLL:
this.circleColor = setRandomColor();
invalidate();
break;
case MotionEvent.ACTION_DOWN:
this.circleColor = setRandomColor();
invalidate();
break;
}
return super.onTouchEvent(event);
}
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
paint = new Paint();
paint.setAntiAlias(true);
}
public void setCircleColor(int circleColor) {
this.circleColor = circleColor;
invalidate();
}
public int setRandomColor() {
Random random = new Random();
int randomColor = Color.argb(255, random.nextInt(), random.nextInt(), random.nextInt());
return randomColor;
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//...
//someXvalue, someYvalue, someRadius are being set here
//...
paint.setColor(circleColor);
canvas.drawCircle(someXvalue, someYvalue, someRadius, paint);
}
}
And here is my MainActivity.java class:
public class MainActivity extends Activity implements
GestureDetector.OnGestureListener {
private GestureDetectorCompat mDetector;
CircleView circle;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDetector = new GestureDetectorCompat(this, this);
circle = new CircleView(this);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
this.mDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
#Override
public boolean onDown(MotionEvent event) {
return true;
}
#Override
public boolean onSingleTapConfirmed(MotionEvent event) {
circle.setCircleColor(circle.setRandomColor(0));
circle.invalidate();
return true;
}
}
I am new to Android development, and Java as well. I realize it could be something with the Context, which is something I have not fully understood yet. Could also be something with the TouchEvents. I am sure that someone out there can see my mistake. Any help is appreciated.
your circle view is not a part of activity's layout , it's just a object in memory which has no link to your activity screen so solutions
1.) Either set circle as Activity's view
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDetector = new GestureDetectorCompat(this, this);
circle = new CircleView(this);
setContentView(circle);
}
2.) you can create your <yourpackagename.CircleView ...attributes .../> tag in your activity_main.xml and then use findViewById to initialize it in your activity.
1)If all you want to do with gestures is on tap, just implement an onClickListener on your View instead.
2)You aren't actually using the GestureDetector anywhere. The way it works is you set an onTouchListener for the view you want to get gestures on, and send the events to the gesture detector. You aren't ever sending data for any view to the detector, so it will never do anything.
3)Not a bug just an oddness- why circle.setColor(circle.setRandomColor())? I would expect a function named setXXX to actually set XXX, rather than having to do it yourself later. Not following that convention will work, but make debugging and maintenance hard.
Edit: Also what #Pavneet_Singh said- your circle isn't in your layout anywhere, so it won't be on screen.
i am using following code for creating marker(bitmap),how to add click event for marker. i use graphhopper android for OSM map
startMarker = createMarker(startPoint, R.drawable.marker_departure); layers.add(startMarker);
add use createMarker method
public Marker createMarker(LatLong p, int resource) {
Drawable drawable = activity.getResources().getDrawable(resource);
Bitmap bitmap = AndroidGraphicFactory.convertToBitmap(drawable);
return new Marker(p, bitmap, 0, -bitmap.getHeight() / 2);
}
and how to add text near to marker
thanks in advance
Try with this, may be this will help full.
layers.setOnMarkerClickListener(new OnMarkerClickListener()
{
#Override
public boolean onMarkerClick(Marker arg0) {
//Your stuff
});
i use following code its works for me
MyMarker frommarker = newMyMarker(activity,newLatLong(fl.latitude,fl.longitude), AndroidGraphicFactory.convertToBitmap(activity.getResources().getDrawable(R.drawable.marker_departure)), 0, 0);
mapView.getLayerManager().getLayers().add(frommarker);
and mymarker class
public class MyMarker extends Marker {
private Context ctx;
public MyMarker(Context ctx, LatLong latLong, Bitmap bitmap, int horizontalOffset,
int verticalOffset) {
super(latLong, bitmap, horizontalOffset, verticalOffset);
this.ctx = ctx;
}
#Override
public boolean onTap(LatLong tapLatLong, Point layerXY, Point tapXY) {
if (this.contains(layerXY, tapXY)) {
}
}