I have horizontal RecyclerView with images.
When i scroll it left, i have image order like this.
When i scroll it right, i have order like this.
I need to set central image on top, above left and right ones. How to do it?
I overrided getChildDrawingOrder method:
#Override
protected int getChildDrawingOrder(int childCount, int i) {
int centerChild;
//find center row
if ((childCount % 2) == 0) { //even childCount number
centerChild = childCount / 2; // if childCount 8 (actualy 0 - 7), then 4 and 4-1 = 3 is in centre.
int otherCenterChild = centerChild - 1;
//Which more in center?
View child = this.getChildAt(centerChild);
final int left = child.getLeft();
final int right = child.getRight();
//if this row goes through center then this
final int absParentCenterX = getLeft() + getWidth() / 2;
//Log.i("even", i + " from " + (childCount - 1) + ", while centerChild = " + centerChild);
if ((left < absParentCenterX) && (right > absParentCenterX)) {
//this child is in center line, so it is last
//centerChild is in center, no need to change
} else {
centerChild = otherCenterChild;
}
} else {//not even - done
centerChild = childCount / 2;
//Log.i("not even", i + " from " + (childCount - 1) + ", while centerChild = " + centerChild);
}
int rez;
//find drawIndex by centerChild
if (i > centerChild) {
//below center
rez = (childCount - 1) - i + centerChild;
} else if (i == centerChild) {
//center row
//draw it last
rez = childCount - 1;
} else {
//above center - draw as always
// i < centerChild
rez = i;
}
//Log.i("return", "" + rez);
return rez;
}
Also i set
setChildrenDrawingOrderEnabled(true);
Full code is here.
Fixed with adding ViewCompat.setTranslationZ(view, translationZ);
protected final void updateViews() {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
//setMarginsForChild(child);
if (mAppearAnimationIsWorking)
child.setAlpha(0);
else
child.setAlpha(1);
if (mScaleUnfocusedViews && !mAppearAnimationIsWorking) {
float scale = computeScale(child);
child.setTranslationY(-getMeasuredHeight() * (1 - scaleFactor) / 2);
ViewCompat.setTranslationZ(child, -getPercentageFromCenter(child));
child.setScaleX(scale * scaleFactor * innerScale);
child.setScaleY(scale * scaleFactor * innerScale);
}
}
}
getChildDrawingOrder and setChildrenDrawingOrderEnabled can be removed.
Related
I have in my app a fragment that has 2 Recyclerview - one horizontal and one vertical.
I am trying to implement an "animation" that changes the horizontal RV's views height and width according to my vertical RV's scroll position.
Here is my implementation of NestedScrollView.OnScrollChangeListener() -
featuredProductsNestedScrollView.setOnScrollChangeListener((NestedScrollView.OnScrollChangeListener)
(nestedScrollView, scrollX, scrollY, oldScrollX, oldScrollY) -> {
Log.d("scrollYValue", "scrollY - " + scrollY);
Log.d("scrollYValue", "oldScrollY - " + oldScrollY);
// Log.d("scrollYValue", "-----------------");
int calculatedValueFrom = scrollY;
if (scrollY == 0)
calculatedValueFrom = oldScrollY;
else if (oldScrollY == 0)
return;
// if (scrollY > oldScrollY) {
// calculatedValueFrom = scrollY;
// } else {
// calculatedValueFrom = oldScrollY;
// }
// Log.d("scrollYValue", "calculatedValueFrom - " + calculatedValueFrom);
int vendorsRowItemHeight = Math.max(160 - calculatedValueFrom, 80);
// Log.d("scrollYValue", "vendorsRowItemHeight - " + vendorsRowItemHeight);
// Log.d("scrollYValue", "scrollY - " + scrollY);
int newWidth = (int) (303 * (vendorsRowItemHeight / 160f));
int newHeight = vendorsRowItemHeight - 10;
// Log.d("scrollYValue", "newWidth - " + newWidth);
// Log.d("scrollYValue", "newHeight - " + newHeight);
// Log.d("scrollYValue", "-----------------");
int newHeight1 = newHeight * 5;
int newWidth1 = newWidth * 5;
// Log.d("scrollYValue", "newHeight1 - " + newHeight1);
// Log.d("scrollYValue", "-----------------");
// Log.d("scrollYValue", "newWidth1 - " + newWidth1);
// Log.d("scrollYValue", "-----------------");
resizeView(vendorsList, ViewGroup.LayoutParams.MATCH_PARENT, newHeight1);
resizeView(featuredVendorsNestedScrollView, ViewGroup.LayoutParams.MATCH_PARENT, newHeight1);
for (int i = 0; i < currentVendorsList.size(); i++) {
VendorsHolder holder = (VendorsHolder) vendorsList.findViewHolderForAdapterPosition(i);
if (holder != null) {
resizeView(holder.vendorHolderCardview, newWidth1, newHeight1);
vendorsAdapter.notifyDataSetChanged();
}
}
});
private void resizeView(View view, int newWidth, int newHeight) {
try {
Constructor<? extends ViewGroup.LayoutParams> ctor = view.getLayoutParams().getClass().getDeclaredConstructor(int.class, int.class);
view.setLayoutParams(ctor.newInstance(newWidth, newHeight));
} catch (Exception e) {
e.printStackTrace();
}
}
I have some weird behaviour going on in my app when this function works - it does resize the top horizontal RV's views, but for every scroll being made the scrollY value gets rested to 0 so the animation has the feeling of a flickering animation (which is actually not true, it actually does what I wanted but for some reason goes back to the minimal value possible)
here is an image of my log prints of scrollY so you can better understand what I mean -
So basically, for some reason, the scrollY value represents something other than just the value going down...otherwise how can I explain why it resets itself for every time the function is being called?
My Requirement : I need to animate a 7*16 LED Display by passing frames through the Android App over BluetoothLE. I have created the design of the display on the app and added empty views with gradient drawable background to them. The colour of these views need to change when my touch moves into them. Adding a touch listener to each view isn't going to help in my case.
What I have achieved : I have a large number of views (100+) added programmatically with a tag set to each of them. I have set an OnTouch Event Handler for the parent view in which these views have been added.
By tracking the absolute coordinates of the touch event (x and y) and comparing with the absolute bounds of a few individual views that I am looping in the touch event handler, I am able to detect hover like touch move (out of bounds to in bounds) over 3-4 views properly.
I have referred the solution from https://stackoverflow.com/a/21903640
Where I am stuck : However, when I try to increase the loop size to cover all the added views, the app response slows down and hover detection fails on most of the views. I know this is happening because of heavy computation in the OnTouch Event Handler which I am not supposed to do.
What I need : I need an improvement on this solution in terms of performance or an alternative way to go about reaching my goal.
Code Snippet
void DrawScreen()
{
for (int column = 0; column < 8; column++)
{
for (int row = 0; row < 17; row++)
{
relativeLayout.AddView(DrawRect(row, column));
}
}
}
View DrawRect(int row, int column)
{
View customView = new View(Context);
GradientDrawable shape = new GradientDrawable();
shape.SetShape(ShapeType.Rectangle);
shape.SetCornerRadii(new float[] { 10, 10, 10, 10, 10, 10, 10, 10 });
shape.SetColor(Color.ParseColor("#3F0000"));
RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
param.LeftMargin = ((column-1) * (width + h_spacing)) + h_spacing;
param.Width = width;
param.Height = height;
param.TopMargin = ((row-1) * (height + v_spacing)) + v_spacing;
customView.Background = shape;
customView.LayoutParameters = param;
customView.Tag = (8 - column).ToString() + "," + (17 - row).ToString();
return customView;
}
private void RelativeLayout_Touch(object sender, View.TouchEventArgs e)
{
if(e.Event.Action == MotionEventActions.Up)
{
out_of_bounds = true;
view_in_bound = null;
}
else
{
for (int row = 1; row < 8; row++)
{
for (int column = 1; column < 17; column++)
{
View view = relativeLayout.FindViewWithTag(row.ToString() + "," + column.ToString());
if (CheckInterSection(view, e.Event.RawX, e.Event.RawY))
{
if (out_of_bounds == true)
{
view_in_bound = view;
out_of_bounds = false;
Log.Debug("Touch", "Inside");
//ToggleViewState(view);
}
else
{
Log.Debug("Touch", "Still Inside");
}
}
else
{
if (view == view_in_bound)
{
out_of_bounds = true;
view_in_bound = null;
Log.Debug("Touch", "Outside");
}
}
}
}
}
}
bool CheckInterSection(View view, float rawX, float rawY)
{
int[] location = new int[2];
view.GetLocationOnScreen(location);
int x = location[0] - h_spacing/2;
int y = location[1] - v_spacing/2;
int width = (view.Width + h_spacing/2);
int height = (view.Height + v_spacing/2);
return (!(rawX < x || rawX > (x + width) || rawY < y || rawY > (y + height)));
}
I tried to use trajectory angles to further reduce the loop size but the performance was never up to my expectations and touch events over views were getting missed regularly.
Then I realized that I was going in the wrong direction and found a much simpler solution. Since my views were being added programmatically and were of same size, I knew the coordinates and bounds of each view in the layout. So I divided the layout into a grid and depending upon the touch coordinates, I was able to identify over which section the touch was on. Below is my solution which has been working perfectly. However, I will wait a while till I mark this as a solution since someone could have a better implementation of my technique or an alternative solution.
void DrawScreen()
{
for (int column = 1; column < 17; column++)
{
for (int row = 1; row < 8; row++)
{
relativeLayout.AddView(DrawRect(row, column));
}
}
}
View DrawRect(int row, int column)
{
View customView = new View(Context);
if (!CheckBit(row - 1, column - 1))
{
customView.SetBackgroundResource(Resource.Drawable.off_rounded_btn);
}
else
{
customView.SetBackgroundResource(Resource.Drawable.rounded_btn);
}
RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
param.LeftMargin = ((column-1) * (width + h_spacing)) + h_spacing;
param.Width = width;
param.Height = height;
param.TopMargin = ((row-1) * (height + v_spacing)) + v_spacing;
customView.LayoutParameters = param;
customView.Tag = row.ToString() + "," + column.ToString();
return customView;
}
void RelativeLayout_Touch(object sender, View.TouchEventArgs e)
{
if (e.Event.Action == MotionEventActions.Up)
{
view_in_bound = null;
}
else
{
int row = CheckTouchArea(e.Event.RawX, e.Event.RawY)[0];
if (row != 0)
{
int column = CheckTouchArea(e.Event.RawX, e.Event.RawY)[1];
check_view = GetView(row, column);
if (check_view != view_in_bound)
{
ChangeViewState(check_view, Touch_CheckBit(row - 1, column - 1), row - 1, column - 1);
view_in_bound = check_view;
}
}
}
}
int[] CheckTouchArea(float rawX, float rawY)
{
int[] tag = new int[2];
int[] location = new int[2];
relativeLayout.GetLocationOnScreen(location);
float x = location[0] + h_padding / 2;
int y = location[1] + v_padding / 2;
float width = relativeLayout.Width - h_padding;
int height = relativeLayout.Height - v_padding;
if ((!(rawX < x || rawX > (x + width) || rawY < y || rawY > (y + height))))
{
int column = (int)Math.Ceiling((rawX - x) * 16 / width);
int row = (int)(Math.Ceiling((rawY - y) * 7 / height));
tag[0] = row;
tag[1] = column;
}
return tag;
}
I'm trying to build a custom ViewGroup base on DavidPizarro/AutoLabelUI
https://github.com/DavidPizarro/AutoLabelUI
My goal is to create a page that looks like this:
but this is the closest that I got:
This is the important part of my code:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int sizeWidth = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
int modeHeight = MeasureSpec.getMode(heightMeasureSpec);
totalWidth = sizeWidth;
int width = 0;
int height = getPaddingTop() + getPaddingBottom();
int lineWidth = 0;
int lineHeight = 0;
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
// child.setMinimumWidth(1080);
boolean lastChild = i == childCount - 1;
if (child.getVisibility() == View.GONE) {
if (lastChild) {
width = Math.max(width, lineWidth);
height += lineHeight;
}
continue;
}
Logger.Log("");
//child.setMinimumWidth(300);
measureChildWithMargins(child, widthMeasureSpec, lineWidth, heightMeasureSpec, height);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
int childWidthMode = MeasureSpec.AT_MOST;
int childWidthSize = sizeWidth;
int childHeightMode = MeasureSpec.AT_MOST;
int childHeightSize = sizeHeight;
if (lp.width == LayoutParams.MATCH_PARENT) {
childWidthMode = MeasureSpec.EXACTLY;
childWidthSize -= lp.leftMargin + lp.rightMargin;
} else if (lp.width >= 0) {
childWidthMode = MeasureSpec.EXACTLY;
childWidthSize = lp.width;
}
if (lp.height >= 0) {
childHeightMode = MeasureSpec.EXACTLY;
childHeightSize = lp.height;
} else if (modeHeight == MeasureSpec.UNSPECIFIED) {
childHeightMode = MeasureSpec.UNSPECIFIED;
childHeightSize = 0;
}
Logger.Log("");
child.measure(
MeasureSpec.makeMeasureSpec(childWidthSize, childWidthMode),
MeasureSpec.makeMeasureSpec(childHeightSize, childHeightMode)
);
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
if (lineWidth + childWidth > sizeWidth) {
// NEW LINE!!! this code means that the width of the child is bןgger then the space left!
width = Math.max(width, lineWidth);
lineWidth = childWidth;
height += lineHeight;
lineHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
} else {
lineWidth += childWidth;
lineHeight = Math.max(lineHeight, child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
}
if (lastChild) {
width = Math.max(width, lineWidth);
height += lineHeight;
}
}
// end of loop.
width += getPaddingLeft() + getPaddingRight();
setMeasuredDimension(
(modeWidth == MeasureSpec.EXACTLY) ? sizeWidth : width,
(modeHeight == MeasureSpec.EXACTLY) ? sizeHeight : height);
}
/**
* This method will place each label next to another. If there is not enough
* space for the next label, it will be added in a new new line.
* <p>
*/
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
mLines.clear();
mLineHeights.clear();
mLineMargins.clear();
int width = getWidth();
int lineWidth = 0;
int lineHeight = 0;
lineViews.clear();
float horizontalGravityFactor = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child.getVisibility() == View.GONE) {
continue;
}
LayoutParams lp = (LayoutParams) child.getLayoutParams();
int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
int childHeight = child.getMeasuredHeight() + lp.bottomMargin + lp.topMargin;
if (lineWidth + childWidth > width) {
mLineHeights.add(lineHeight);
mLines.add(lineViews);
mLineMargins.add((int) ((width - lineWidth) * horizontalGravityFactor) + getPaddingLeft());
lineHeight = 0;
lineWidth = 0;
lineViews = new ArrayList<>();
}
lineWidth += childWidth;
lineHeight = Math.max(lineHeight, childHeight);
lineViews.add(child);
}
// END OF LOOP.
mLineHeights.add(lineHeight);
mLines.add(lineViews);
mLineMargins.add((int) ((width - lineWidth) * horizontalGravityFactor) + getPaddingLeft());
int verticalGravityMargin = 0;
int numLines = mLines.size();
int left;
int top = getPaddingTop();
// now we are looping threw the number of row in total - mLines.size(), and we want to measure each tag!
for (int i = 0; i < numLines; i++) {
lineHeight = mLineHeights.get(i);
// lineViews = number of lines for child!
lineViews = mLines.get(i);
left = mLineMargins.get(i);
int children = lineViews.size();
for (int j = 0; j < children; j++) {
View child = lineViews.get(j);
if (child.getVisibility() == View.GONE) {
continue;
}
LayoutParams lp = (LayoutParams) child.getLayoutParams();
// if height is match_parent we need to remeasure child to line height
if (lp.height == LayoutParams.MATCH_PARENT) {
int childWidthMode = MeasureSpec.AT_MOST;
int childWidthSize = lineWidth;
if (lp.width == LayoutParams.MATCH_PARENT) {
childWidthMode = MeasureSpec.EXACTLY;
} else if (lp.width >= 0) {
childWidthMode = MeasureSpec.EXACTLY;
childWidthSize = lp.width;
}
child.measure(
MeasureSpec.makeMeasureSpec(childWidthSize, childWidthMode),
MeasureSpec.makeMeasureSpec(lineHeight - lp.topMargin - lp.bottomMargin,
MeasureSpec.EXACTLY)
);
}
int childWidth = child.getMeasuredWidth();
int childHeight = child.getMeasuredHeight();
int gravityMargin = 0;
if (Gravity.isVertical(lp.gravity)) {
switch (lp.gravity) {
case Gravity.TOP:
default:
break;
case Gravity.CENTER_VERTICAL:
case Gravity.CENTER:
gravityMargin = (lineHeight - childHeight - lp.topMargin - lp.bottomMargin) / 2;
break;
case Gravity.BOTTOM:
gravityMargin = lineHeight - childHeight - lp.topMargin - lp.bottomMargin;
break;
}
}
child.layout(left + lp.leftMargin,
top + lp.topMargin + gravityMargin + verticalGravityMargin,
left + childWidth + lp.leftMargin,
top + childHeight + lp.topMargin + gravityMargin + verticalGravityMargin);
left += childWidth + lp.leftMargin + lp.rightMargin;
}
// end of loop
top += lineHeight;
}
// end of loop
}
I would appreciate if you can show me what I have to do to change the size of the child to make it stretched all the way to fill the empty space.
I honestly don't know what all that code you posted above was doing, too long, too little sense made, don't even know how it worked.
Out of curiosity, I'm gonna try solve this problem directly here, I hope it works.
First the onMeasure() method:
// maximum available width for children
int maxW = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
// you want all children to be as wide as they want, but not wider than the view group
int widthMS = MeasureSpec.makeMeasureSpec(w, MeasureSpec.AT_MOST);
// you probably want them all to have the same height.
// maybe define it in xml attrs?
int heightMS = MeasureSpec.makeMeasureSpec(rowHeight, MeasureSpec.EXACTLY);
// remaining width of current row, initially equals to w
int remW = w;
// index of first child in the current row
int rowFirstChild = 0;
// row count, used to calculate the view group's height
int rows = 0;
int i = 0;
while (i < getChildCount()) {
Child ch = getChildAt(i);
if (ch.getVisibility() != View.GONE) {
// ask how big does it want to be
child.measure(widthMS, heightMS);
int chWidth = ch.getMeasuredWidth();
// if it fits
if (remW - chWidth >= 0) {
// update remW, then go to next child
remW -= chWidth;
i++;
}
// if it does not fit
else {
// if it's not the first child in the row
if (i > rowFirstChild) {
stretchViews(rowFirstChild, i - 1, maxW, remW, heightMS);
// this will be the first child in the next row and take the space from
// that row's remW
rowFirstChild = i;
remW = maxW - chWidth;
}
// if it's the first and only child on this row
else {
// it should just take the full width and give first spot in the next
// row to the next child, and reset remW
rowFirstChild = i + 1;
remW = maxW;
}
// both of these scenarios result in the addition of a new row
rows++;
}
}
}
// finally, we want to take as much width as we can, and as minimum height as we can
int finalW = MeasureSpec.getSize(widthMeasureSpec);
int finalH = Math.min(
rows * rowHeight + getPaddingTop() + getPaddingBottom(),
MeasureSpec.getSize(heightMeasureSpec)
);
setMeasuredDimensions(finalW, finalH);
// note that this measurement ignores height measure spec and automatically takes the
// minimum height, and ignores the height measure spec of its children as well and
// just gives them height from its rowHeight attr.
// you are free to change this setting.
Now, onLayout() method. Here, since we already assigned measurements to our children, they are all set, we simply have to lay them out, not much work to do:
// maximum usable width in any row
int maxW = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
// left starting point
int left = getPaddingLeft();
// top starting point
int top = getPaddingTop();
int i = 0;
while (i < getChildCount()) {
Child ch = getChildAt(i);
if (ch.getVisibility() != GONE) {
int chWidth = ch.getMeasuredWidth();
ch.layout(
left,
top,
left + chWidth,
top + rowHeight
);
// if this child is the last in row (-1 for error tolerance when rounding ints)
if (left + chWidth >= maxW - 1) {
// reset'left' back to its starting point
left = getPaddingLeft();
// move 'top' down by 'rowHeight'
top += rowHeight;
}
// if it wasn't the last child in the row
else {
// then simply advance the 'left' position
left += chWidth;
}
}
}
// Note that this method only supports LTR layout.
// You can make minor changes to add support for RTL.
// Also, margins between children are ignored, spend some time on that if you want
Let me know if this works
Update:
Never mind, I'll just do the stretching method anyway:
/**
* Stretches children of this view group horizontally, and proportionally to their widths
* to span the entire row width
*
* #param firstIndex index of first child to stretch (inclusive)
* #param lastIndex index of last child to stretch (inclusive)
* #param fullWidth the width to cover (max available width for row children)
* #param remWidth remaining width to cover
* #param heightMS the hight measure spec to reuse on these views
*/
private void stretchViews(int firstIndex, int lastIndex, int fullWdith, int
remWidth, int heightMS) {
for (int i = firstIndex; i <= lastIndex; i++) {
Child ch = getChildAt(i);
if (ch.getVisibility() != GONE) {
int measuredW = ch.getMeasuredWidth();
int widthMS = MeasureSpec.makeMeasureSpec(
measuredW + remWidth * measuredW / fullWidth, MeasureSpec.EXACTLY);
ch.measure(widthMS, heightMS);
}
}
}
I want to detect motion with Android sensors. For example I hold only bottom of phone and move top of phone to up. I think I need sampling algorithms. I can write a simple application to record data of sensors . For comparing real time data and recorded data ,Is there any libary ? I have suspicious about performace problems if I would make it. Is there a different path for detetion movements ?
These links will help you to start..
http://developer.android.com/guide/topics/sensors/sensors_motion.html
http://code.google.com/p/android-motion-detection/
http://www.helloandroid.com/tutorials/android-image-processing-detecting-motions
http://code.google.com/p/android-motion-detection/ is a good example.
I modified the isDifferent method in RgbMotionDetection class to detect the motion in the center part (25%) of the camera view.
protected static boolean isDifferent(int[] first, int width, int height) {
if (first==null) throw new NullPointerException();
if (mPrevious==null) return false;
if (first.length != mPrevious.length) return true;
if (mPreviousWidth != width || mPreviousHeight != height) return true;
int totDifferentPixels = 0;
int size = height * width;
int startHeight = height / 4;
int endHeight = 3 * (height / 4);
int startWidth = width / 4;
int endWidth = 3 * (width / 4);
int offSet = width / 4;
Log.d("params", "start height " + startHeight + "end height " + endHeight + "start width " + startWidth + "end width " + endWidth);
Boolean offSetApplied;
for (int i = startHeight, ij=0; i < endHeight; i++) {
{
offSetApplied = false;
for (int j = startWidth; j < endWidth; j++, ij++) {
if (!offSetApplied){
offSetApplied = true;
ij = startHeight * width + offSet;
}
int pix = (0xff & ((int)first[ij]));
int otherPix = (0xff & ((int)mPrevious[ij]));
//Catch any pixels that are out of range
if (pix < 0) pix = 0;
if (pix > 255) pix = 255;
if (otherPix < 0) otherPix = 0;
if (otherPix > 255) otherPix = 255;
if (Math.abs(pix - otherPix) >= mPixelThreshold) {
totDifferentPixels++;
//Paint different pixel red
//first[ij] = Color.RED;
}
}
}
}
if (totDifferentPixels <= 0) totDifferentPixels = 1;
//boolean different = totDifferentPixels > mThreshold;
int percent = 100/(size/totDifferentPixels);
//float percent = (float) totDifferentPixels / (float) size;
boolean different = percent > SENSITIVITY;
String output = "Number of different pixels: " + totDifferentPixels + "> " + percent + "%";
if (different) {
Log.e(TAG, output);
} else {
Log.d(TAG, output);
}
return different;
}
Do you know any examples, screencasts that document how to develop with ToolBar on "mono for android" ?
I would like to develop a tiny toolbar and I'm searching for the proper way to code it?
Here is Dashboard, and if you or somebody else will need ActionBar here is a link!
public class DashboardLayout : ViewGroup
{
private const int UNEVEN_GRID_PENALTY_MULTIPLIER = 10;
private int _mMaxChildWidth;
private int _mMaxChildHeight;
public DashboardLayout(IntPtr doNotUse, JniHandleOwnership transfer) : base(doNotUse, transfer)
{
}
public DashboardLayout(Context context)
: base(context)
{
}
public DashboardLayout(Context context, IAttributeSet attrs)
: base(context, attrs)
{
}
public DashboardLayout(Context context, IAttributeSet attrs, int defStyle)
: base(context, attrs, defStyle)
{
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
_mMaxChildWidth = 0;
_mMaxChildHeight = 0;
// Measure once to find the maximum child size.
var childWidthMeasureSpec = MeasureSpec.MakeMeasureSpec(
MeasureSpec.GetSize(widthMeasureSpec), MeasureSpecMode.AtMost);
var childHeightMeasureSpec = MeasureSpec.MakeMeasureSpec(
MeasureSpec.GetSize(widthMeasureSpec), MeasureSpecMode.AtMost);
var count = ChildCount;
for (var i = 0; i < count; i++)
{
var child = GetChildAt(i);
if (child.Visibility == ViewStates.Gone)
{
continue;
}
child.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
_mMaxChildWidth = Math.Max(_mMaxChildWidth, child.MeasuredWidth);
_mMaxChildHeight = Math.Max(_mMaxChildHeight, child.MeasuredHeight);
}
// Measure again for each child to be exactly the same size.
childWidthMeasureSpec = MeasureSpec.MakeMeasureSpec(
_mMaxChildWidth, MeasureSpecMode.Exactly);
childHeightMeasureSpec = MeasureSpec.MakeMeasureSpec(
_mMaxChildHeight, MeasureSpecMode.Exactly);
for (int i = 0; i < count; i++)
{
var child = GetChildAt(i);
if (child.Visibility == ViewStates.Gone)
{
continue;
}
child.Measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
SetMeasuredDimension(
ResolveSize(_mMaxChildWidth, widthMeasureSpec),
ResolveSize(_mMaxChildHeight, heightMeasureSpec));
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
var width = r - l;
var height = b - t;
var count = ChildCount;
// Calculate the number of visible children.
var visibleCount = 0;
for (var i = 0; i < count; i++)
{
var child = GetChildAt(i);
if (child.Visibility == ViewStates.Gone)
{
continue;
}
++visibleCount;
}
if (visibleCount == 0)
{
return;
}
// Calculate what number of rows and columns will optimize for even horizontal and
// vertical whitespace between items. Start with a 1 x N grid, then try 2 x N, and so on.
var bestSpaceDifference = int.MaxValue;
// Horizontal and vertical space between items
int hSpace;
int vSpace;
var cols = 1;
int rows;
while (true)
{
rows = (visibleCount - 1) / cols + 1;
hSpace = ((width - _mMaxChildWidth * cols) / (cols + 1));
vSpace = ((height - _mMaxChildHeight * rows) / (rows + 1));
var spaceDifference = Math.Abs(vSpace - hSpace);
if (rows * cols != visibleCount)
{
spaceDifference *= UNEVEN_GRID_PENALTY_MULTIPLIER;
}
if (spaceDifference < bestSpaceDifference)
{
// Found a better whitespace squareness/ratio
bestSpaceDifference = spaceDifference;
// If we found a better whitespace squareness and there's only 1 row, this is
// the best we can do.
if (rows == 1)
{
break;
}
}
else
{
// This is a worse whitespace ratio, use the previous value of cols and exit.
--cols;
rows = (visibleCount - 1) / cols + 1;
hSpace = ((width - _mMaxChildWidth * cols) / (cols + 1));
vSpace = ((height - _mMaxChildHeight * rows) / (rows + 1));
break;
}
++cols;
}
// Lay out children based on calculated best-fit number of rows and cols.
// If we chose a layout that has negative horizontal or vertical space, force it to zero.
hSpace = Math.Max(0, hSpace);
vSpace = Math.Max(0, vSpace);
// Re-use width/height variables to be child width/height.
width = (width - hSpace * (cols + 1)) / cols;
height = (height - vSpace * (rows + 1)) / rows;
var visibleIndex = 0;
for (var i = 0; i < count; i++)
{
var child = GetChildAt(i);
if (child.Visibility == ViewStates.Gone)
{
continue;
}
var row = visibleIndex / cols;
var col = visibleIndex % cols;
var left = hSpace * (col + 1) + width * col;
var top = vSpace * (row + 1) + height * row;
child.Layout(left, top,
(hSpace == 0 && col == cols - 1) ? r : (left + width),
(vSpace == 0 && row == rows - 1) ? b : (top + height));
++visibleIndex;
}
}
}