I want to make a game with a board composed of buttons without spacing between them and the board must be scrollable in 2 dimensions in the same time. When I was trying to make nested containers, then I could scroll, for example verticaly but horizontal is then locked.
How can I do scrollable board?
How to completely remove spacing between buttons?
To achieve both scrolling behaviors you can implement this XML below:
Now this is using a scroll view as the parent layout to have scrolling in both directions.
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:scrollbars="vertical">
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="320px" android:layout_height="fill_parent">
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linlay" android:layout_width="320px"
android:layout_height="fill_parent" android:stretchColumns="1"
android:background="#000000"/>
</HorizontalScrollView>
Then to enable the horizontal scrollbar use this:
android:scrollbarAlwaysDrawHorizontalTrack="true"
As for the no spacing on the buttons, you can easily achieve this by making sure they have no padding or margins to their neighbors what so ever.
Just size them how you like, to make sure they fit across the screen in the desired design.
To use a Gridview you can do something like this:
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<GridView
android:id="#+id/schemeGridView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:numColumns="1" >
</GridView>
</LinearLayout>
</HorizontalScrollView>
To solve the issue of diagonal scrolling. I believe you need to work on the actual touch event to initiate scroll.
Try this:
#Override
public boolean onTouchEvent(MotionEvent event) {
float curX, curY;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mx = event.getX();
my = event.getY();
break;
case MotionEvent.ACTION_MOVE:
curX = event.getX();
curY = event.getY();
vScroll.scrollBy((int) (mx - curX), (int) (my - curY));
hScroll.scrollBy((int) (mx - curX), (int) (my - curY));
mx = curX;
my = curY;
break;
case MotionEvent.ACTION_UP:
curX = event.getX();
curY = event.getY();
vScroll.scrollBy((int) (mx - curX), (int) (my - curY));
hScroll.scrollBy((int) (mx - curX), (int) (my - curY));
break;
}
return true;
}
Found here for reference: Diagonal scrolling
Let me know if this works.
Related
Inside CursorAdapter's bindView() I bind data to the following layout:
A TextView and two Buttons : "UP" and "DOWN".
The TextView is defined in XML like so:
<TextView
android:id="#+id/tv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="25dp"
android:paddingRight="25dp"
android:paddingTop="25dp"
android:scrollbars="vertical"
android:textAlignment="textStart"
android:textColor="#5c6284"
app:autoSizeMaxTextSize="40sp"
app:autoSizeMinTextSize="20sp"
app:autoSizeTextType="uniform" />
A vertical scrolling behavior is applied to the TextView, which is being controlled by the "UP and "DOWN" Buttons.
I would like to determine if the TextView requires scrolling ( is long enough to not fit its provided drawing area ) so that I can enable/disable the "UP" and "DOWN" buttons accordingly.
I'm currently reading BaseMovementMethod's scrollDown function, thinking of applying its measuring logic to my adapter, though I have the feeling that it should be much simpler. Maybe a built in behavior that I'm not aware of.
Is there a better way to achieve this, other than my suggested approach?
What I would do is put the textview inside a scrollview like so:
<ScrollView
android:id="#+id/scroller"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<TextView
android:id="#+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="test texts here"/>
</ScrollView>
In your activity, execute these lines:
boolean needScrolling = false;
if(scroller.getHeight() < tv_content.getHeight()) needScrolling = true;
You can use Static Layout class. If you set it up with your TextView's parameters you'll be able to calculate the height of the rendered text.
Layout.Alignment alignment = Layout.Alignment.ALIGN_NORMAL;
float spacingMultiplier = 1;
float spacingAddition = 0;
boolean includePadding = false;
StaticLayout myStaticLayout = new StaticLayout(text, myTextView.getPaint(), myTextView.getWidth(), alignment, spacingMultiplier, spacingAddition, includePadding);
float height = myStaticLayout.getHeight();
Then you can compare the height of your text and height of your TextView and figure out if it will require scrolling or not.
You can also try to manually create a Paint object with your min text size if myTextView.getPaint() approach does not work.
Calculate mTextView's height without data and with data and then compare it
mTextView.post(new Runnable() {
#Override
public void run() {
int lineHeight=mTextView.getCompoundPaddingBottom()+ mTextView.getCompoundPaddingTop()+mTextView.getLineHeight();
int height=mTextView.getHeight()-(mTextView.getCompoundPaddingTop()+mTextView.getLineHeight());
if (height>lineHeight){
}
}
});
I'm using ObjectAnimator to translate a view horizontally to the right edge of the outer view. Both views are children of the same layout, with the second view matching width and height of the parent and enclosing the first view. When my activity starts and ObjectAnimator is called to translate the view, it will only end up at the correct destination when the view starts out at 0.0, 0.0. When start coordinates are 100.00,100.00 , the view ends up 100.00 units past where it's supposed to be.
startX = view.getX();
endX = getRight(layout) - view.getWidth();
Log.i("debugger", "going from x="+startX+" to x="+endX);
translateRight = ObjectAnimator.ofFloat(view, "translationX", startX, endX);
And in the animatorListener
#Override
public void onAnimationEnd(Animator animator) {
Log.i("debugger", "end x = "+view.getX());
}
The method I use to get the X coordinate of the right edge of a view
public int getRight(View view){
return (int)(view.getX()+view.getWidth());
}
Snippet of xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="100"
android:orientation="horizontal"
android:gravity="center">
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="82"
android:layout_height="match_parent">
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/outerView"
/>
<View
android:layout_height="#dimen/view_width"
android:layout_width="#dimen/view_width"
android:background="#drawable/view"
android:id="#+id/view"
android:layout_toRightOf="#id/obstacle1"
android:layout_below="#id/obstacle1"
/>
<View
android:id="#+id/obstacle1"
android:layout_height="#dimen/view_width"
android:layout_width="#dimen/view_width"
android:background="#drawable/obstacle"
android:layout_alignParentTop="true"
/>
layout
When the view starts off in the upper left hand corner (where obstacle 1 is), the view ends up flush against the inside right wall of the outerView, where it should be. However, when the view has non-zero coordinates, as in the example where it sits below and to the right of obstacle1, it goes past the right edge and sits flush against the outside wall of the outerView. The funny thing is, if the view is placed in the xml at the upper left hand corner, it can move as supposed to no matter where it becomes positioned. When it doesn't start in the corner, everything's jacked from the get-go.
The logs look as follows for when view starts at 0,0:
going from x=0 to x=1080
end x = 1080
The logs look as follows for when view starts at 100, 100:
going from x=100 to x=1080
end x = 1180
Does anyone know why this is happening? Any help would be greatly appreciated.
You are translating the view on the X axe, with start value 100. If the translationX attribute of your view is 0, then the animation will start by instantly translating your view by 100.
You should do something like this :
translateRight = ObjectAnimator.ofFloat(view, "translationX", view.getTranslationX(), endX - startX);
I am implementing my own Calendar strangely the gridView is not coming up fully. I am the numbers are coming properly but the screen is not full. It is half. I would like to implement something similar to CalendarView.
Please check the snapshot you will understand:
can you see the lot of empty grey Space. How do make it such way it is full screen?
Here are two xml's that are related to Calendar
CalendarView.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/calendarMain"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background"
android:orientation="vertical" >
<RelativeLayout
android:id="#+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/calendar_top" >
</RelativeLayout>
<GridView
android:id="#+id/gridview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/header"
android:layout_gravity="center_horizontal"
android:listSelector="#android:color/transparent"
android:numColumns="7"
android:stretchMode="columnWidth" />
</RelativeLayout>
Next is CalendarItems.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/calendar_cell"
android:gravity="center"
android:orientation="vertical"
android:padding="2dip" >
<TextView
android:id="#+id/date"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#000000"
android:textSize="16dip" >
</TextView>
<TextView
android:id="#+id/textvaluedate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="#+id/date"
android:textColor="#F44336"
android:textSize="10dip"
android:visibility="gone" >
</TextView>
</LinearLayout>
Try to change everything match_parent still the same. I am not really sure where I am going wrong here?
Can somebody help me fix this?
Thanks!
UPDATE 2:
I have updated my code according to #Heshan Sandeepa. I got the full screen but the image box look really big. Please take a look at the screen shot. What could be wrong here?
Here is the CODE in my Baseadapter:
DisplayMetrics metrics = mContext.getResources().getDisplayMetrics();
int height = metrics.heightPixels;
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, month.get(Calendar.YEAR));
calendar.set(Calendar.MONTH, month.get(Calendar.MONTH));
int numDays = calendar.getActualMaximum(Calendar.DATE);
double rowCounts = Math.ceil(numDays/7);
int rowCount = (int) rowCounts;
if (convertView == null)
{
LayoutInflater vi = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.calendar_item, null);
}
v.setMinimumHeight(height / rowCount);
}
All I require is that I need bigger square box for each date. That is all.
Let me know!
Thanks!
For columns you can achieve above requirement through strechMode read here . For rows you can achieve this through following steps ,
Calculate the Device height.
getWindowManager().getDefaultDisplay().getMetrics(new DisplayMetrics());
int deviceHeight = new DisplayMetrics().heightPixels;
Reduce the action bar height / any paddings from that (if you have one)
You can determine how many rows you need, then you can define the height of each row(cell actually) . You can get the row number by deviding the number of days of relevant month by 7 and get the ceiling value.
ex - jan
int rowCount = Math.ceil(31/7);
= 5
ex - Feb (carefull, here no need to get the ceiling as you can get integer)
int rowCount = Math.ceil(28/7);
= 4
Same for all months.
Now you have screen height(step 2) and the number of row(step 3), so can define what is the exact height of each ro. I hope you are having an adapter and custom view for each cell.
When you are inflating the custom view at the getView() , define the calculated height as the minimum height.
your_view.setMinimumHeight(<device height / rowCount>)
I've created the following layout xml-file:
<RelativeLayout 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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="some.package.MainActivity" >
<TableLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TableRow
android:id="#+id/mainRow"
android:layout_weight="1" >
<FrameLayout
android:id="#+id/mainLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />
</TableRow>
<TableRow
android:id="#+id/footerRow"
android:layout_weight="1" >
<FrameLayout
android:id="#+id/footerLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1" />
</TableRow>
</TableLayout>
</RelativeLayout>
... and populate it with graphs from the GraphView api as follows:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int[] assetLayouts = new int[]{
R.id.mainLayout,
R.id.footerLayout,
};
int count = 0;
for (int assetLayout :assetLayouts ) {
GraphViewSeries exampleSeries = new GraphViewSeries(new GraphViewData[] {
new GraphViewData(1, 2.0d)
, new GraphViewData(2, 1.5d)
, new GraphViewData(3, 2.5d)
, new GraphViewData(4, 1.0d)
});
GraphView graphView = new LineGraphView(this, "" + ++count);
graphView.addSeries(exampleSeries);
FrameLayout layout = (FrameLayout) findViewById(assetLayout);
layout.addView(graphView);
}
}
This behaves as expected and divides the screen in two parts, with one graph taking up the first top half, and the second one taking up the other bottom half. Now, I want to give the top graph/row more weight, i.e., it should be proportionally larger than the lower graph/row. So, what i did was set the top row (mainRow) to android:layout_weight="2". I expect that the top row now should be twice as large as the bottom row, however, the opposite happens. The top one only get 33%, while the bottom one gets 66% of the screen real estate. This is opposite of the documentation I found:
For example, if there are three text fields and two of them declare a
weight of 1, while the other is given no weight, the third text field
without weight will not grow and will only occupy the area required by
its content. The other two will expand equally to fill the space
remaining after all three fields are measured. If the third field is
then given a weight of 2 (instead of 0), then it is now declared more
important than both the others, so it gets half the total remaining
space, while the first two share the rest equally.
http://developer.android.com/guide/topics/ui/layout/linear.html
What is going on here?
Sure I can work around it and just give the opposite weights of what I thought was right, but I'd rather do it right.
Also when setting weight, set width (if orientation is horizontal) or height (if vertical) to 0dp. That way the width/height is calculated properly.
I have a floor plan which is centred in an ImageView. The aspect ratio of the image is preserved so there is some space on either side of the image (indicated in red colour).
How can I determine the width of this red space in pixels or dp?
<RelativeLayout 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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context=".MyActivity"
android:background="#color/red"
android:orientation="vertical">
<ImageView
android:id="#+id/floor_plan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/floor_plan2"
android:adjustViewBounds="true"
android:layout_toStartOf="#+id/locateMe"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
/>
I note that the margins have been set to 0dp in the dimens.xml file.
That's only math :
int originalImgWidth = bitmap.getWidth();
int originalImgHeight = bitmap.getHeight();
float scale = screenHeight * 1f / originalImgHeight;
// since your img will fill the screen vertically
float marginSize = (screenWidth - (originalImgWidth * scale)) /2;
Note that the size might be negative if the image is bigger than the screen horizontally ^^
see how to get the bitmap here
see how to get screen size here