I have a GridView (with 2 columns and 2 rows) and want to stretch the rows to fill the whole screen. It should look the same on all devices.
That means I don't want some empty space under the last row. So I searched a little bit and found a solution to set the minimum height of the GridView dynamically with following code:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels;
int height = metrics.heightPixels;
In addition I added these lines of code in my Adapter:
gridView = inflater.inflate(R.layout.act_main_menu_sub, null);
gridView.setMinimumHeight(ActMainMenu.height/2);
But now it looks like this:
The View is scrollable now and the items have the same size. But it doesn't fit on the screen.
Here is the code of my layout including the GridView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/layout_main_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#b2b2b2"
android:orientation="vertical">
<!-- android:layout_height="wrap_content" -->
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
android:padding="2dp"
app:titleMarginStart="20dp"
app:titleTextAppearance="#style/MyMaterialTheme.Base.TitleTextStyle"
app:titleTextColor="#color/textColorPrimary">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="MASTERFITNESS TRAINERSCHULUNG"
android:textColor="#android:color/white"
android:textStyle="bold|italic"/>
</android.support.v7.widget.Toolbar>
<!--android:columnWidth="160dp"-->
<GridView
android:id="#+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:gravity="center"
android:horizontalSpacing="20dp"
android:numColumns="2"
android:stretchMode="columnWidth"
android:verticalSpacing="20dp"></GridView>
</LinearLayout>
What is the problem here?
The problem with your 2nd screen shots in the height calculation. metrics.heightPixels gives you the full height of the screen, including the toolbar and any margins you have. These should 1st be subtracted out, then divide the screen in half.
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
// your layout has 10dp margin (top & bottom) + 20 dp between grid items, 10+10+20=40
int marginSizeDp = 40;
float scale = metrics.density;
int marginSizePx = Math.round (marginSizeDp * scale);
int appBarHeight = getAppBarHeight();
int height = metrics.heightPixels;
int minHt = Math.round((height - marginSizePx - appBarHeight)/2);
gridView.setMinimumHeight(minHt);
Get the toolbar height thanks to AZ13 at https://stackoverflow.com/a/7167086/7292819
// returns height of app bar in pixels
private int getAppBarHeight() {
final TypedArray styledAttributes = getTheme().obtainStyledAttributes(
new int[] { android.R.attr.actionBarSize });
int appBarHeight = (int) styledAttributes.getDimension(0, 0);
styledAttributes.recycle();
return appBarHeight;
}
Truthfully, if this layout is static (there's only 4 items, no scrolling, little or no changing of the content of each item), I probably wouldn't bother with a GridView & adapter. A RelativeLayout or GridLayout might be better.
Related
I have a png image something like below and I need to fill its background color according to its capacity.
For example if tank has oil %100 percent of its capacity, background should be yellow , if has %25 , background should be %25 percent yellow and %75 transparent.
Assume that this is a healthbar in a game.
this is what i have in my layout, just a simple imageview in a linearlayout.
Is there any way to achieve this using animation, clip or something ?
<ImageView
android:id="#+id/ivOilTank"
android:layout_width="0dp"
android:src="#mipmap/oilTank"
android:layout_height="match_parent"
android:layout_weight="1">
Change your layout xml to contain-
<FrameLayout
android:layout_width="150dp"
android:layout_height="wrap_content"
android:background="#android:color/black"
>
<View
android:id="#+id/percent_highlight"
android:layout_width="0dp"
android:layout_height="match_parent"
/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#mipmap/oilTank"
/>
</FrameLayout>
Now wherever you want to highlight the certain percentage of the image -
View highlight = findViewById(R.id.percent_highlight);
highlight.setBackgroundResource(<Color_id>);//Any color you want to set
ViewGroup.LayoutParams layoutParams = highlight.getLayoutParams();
layoutParams.width = (int) (dpToPixel(150) * 25 / 100.0f);//If you want to set 25%
highlight.setLayoutParams(layoutParams);
where dpToPixel() converts dp to pixels -
public int dpToPixel(float dp) {
final float scale = getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
Here is my solution,
Since I am not interested in using dp for width property, i looked for another solution. If you want to use dp directly check Shadab Ansari's answer which gave me a clue.
frameLayout
<FrameLayout
android:id="#+id/flOil"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
>
<View
android:id="#+id/progress_view"
android:background="#fc12d108"
android:layout_width="55dp"
android:layout_height="match_parent"
android:layout_margin="1dp"/>
<ImageView
android:id="#+id/ivOil"
android:layout_width="match_parent"
android:src="#mipmap/oilTank"
android:layout_height="match_parent"
>
</ImageView>
</FrameLayout>
Code
ViewTreeObserver vto = ivRate.getViewTreeObserver();
vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
public boolean onPreDraw() {
ivRate.getViewTreeObserver().removeOnPreDrawListener(this);
widthTank = ivRate.getMeasuredWidth();//get the width of the imageView which has oilTank image as dp.
ViewGroup.LayoutParams layoutParams = prgrs.getLayoutParams();
layoutParams.width = (int) (widthTank / (new Random().nextInt(4) + 2));//calculate a width for view which is going to fill background color, random was user for testwill be using desired value.
prgrs.setLayoutParams(layoutParams);
return true;
}
});
Before using widthTank variable , onPreDraw method has to be called so be sure that it is called otherwise it will not be assigned.
Please checkout this example
https://github.com/fanrunqi/WaveProgressView or https://github.com/rathodchintan/Percentage-wise-Image-Filling
this is the best way to fill image
i am implementing recyclerview inside scrollview
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="#+id/rv1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"
android:listSelector="#android:color/transparent" />
</LinearLayout>
set recyclerview to fixed height like this
mRecyclerView_other.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager_other = new LinearLayoutManager(context);
mRecyclerView_other.setLayoutManager(layoutManager_other);
int adapterItemSize = 64;
int viewHeight = adapterItemSize * list.size();
mRecyclerView_other.getLayoutParams().height = viewHeight;
mRecyclerView_other.setAdapter(adapter_other);
as holder height will be fixed to 64dp i have put adapterItemSize = 64, but the issue i am facing is only two rows from the list are visible.
I think you have not setLayoutParams. When you change the layout params of a view, you need to set it, eg, this is how you set it for your recyclerview:
LinearLayout.LayoutParams layoutParams = mRecyclerView_other.getLayoutParams();
layoutParams.width = 64;
layoutParams.height = 64;
mRecyclerView_other.setLayoutParams(layoutParams);
You are also setting your width and height using integer values instead of pulling them from the dimens.xml - try this:
In your dimens.xml file:
<dimen name="test">64dp</dimen>
Then extract the int value like this:
int valueInPixels = (int) getResources().getDimension(R.dimen.test)
I am using GridLayout(support) for displaying ImageViews in my application. There are 3 columns and 5 rows. The problem is that the cells in the GridLayout automatically get some space between them. I am not setting any padding or margin for the cells. Please refer to the image below. All cells are added dynamically and here is how I add these cells.
Getting Screen Width and Height:
Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
screenWidth = size.x;
screenHeight = size.y;
rowHeight = (int) (screenHeight * 0.2);
Adding View to GridLayout:
GridLayout.LayoutParams params = new GridLayout.LayoutParams(
getSpec(rowColumn[0]), getSpec(rowColumn[1]));
params.height = rowHeight;
if (rowColumn[1].equalsIgnoreCase("col_full")) {
params.width = (int) (screenWidth);
} else if (rowColumn[1].equalsIgnoreCase("col_two_part")) {
params.width = (int) (screenWidth * 0.6);
} else {
params.width = (int) (screenWidth * 0.3);
}
ImageButton image = (ImageButton) imageHashMap
.get(reOrderedButtonsListCopy.get(i));
image.setLayoutParams(params);
gridLayout.addView(image, params);
XML Layout:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.xx.xxx"
android:id="#+id/scrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<android.support.v7.widget.GridLayout
xmlns:app="http://schemas.android.com/apk/res/com.xx.xxx"
android:id="#+id/gridlayout_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp"
app:columnCount="3"
app:rowCount="5" >
</android.support.v7.widget.GridLayout>
</LinearLayout>
</ScrollView>
Current result:
The red lines show the spaces in between the cells. Also, there is some space on the left side of GridLayout. I have only given 2dp as layout_margin. Any reasons why this padding occurs?
[EDIT]
Making the following changes removed the spacings.
gridLayout = (GridLayout) findViewById(R.id.gridlayout_main);
gridLayout.setUseDefaultMargins(false);
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setRowOrderPreserved(false);
Refer to the image below.
Found the solution.
Making the following changes removed the spacings.
gridLayout = (GridLayout) findViewById(R.id.gridlayout_main);
gridLayout.setUseDefaultMargins(false);
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setRowOrderPreserved(false);
Refer to the image below.
The only solution that worked for me was to add extra columns in the GridLayout like android:columnCount="7" and then the column that needs more width set to 3 or more. The more space you want to give to that column. It then automatically reserves more space for those columns. The whole GridLayout works as a stretching thing. The columnWeight says how much a column can stretch.
I have a gridview and make a custom adapter for fill it, user can set by spinner rows and columns of my grid. In each cell of grid I set a videoview.
So I need to set dinamically the size for each videoview in my custom Adapter in order to fill the remaining part of the screen. Following this I can do the task, I take display size and set layout for my view dividing by the number of rows and columns.
The problem is that principal layout has action-bar and a textview . So, windows size is not correct. I need to subtract action-bar and textview size.
I find a solution for know action-bar size, but when get height of my textview it is always 0.
As suggest here I should take textview size after rendering, but for render my gridview I need to know this size !!
There are other ways to do it ? It's necessary to manually calculate view size ??
this is my layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context="it.nexera.visiamobile.ViewLiveMultiActivity"
>
<TextView
android:id="#+id/txt_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textColor="#454545"
android:gravity="left"
android:text="#string/sel_grid" />
<Spinner
android:id="#+id/grid_spinner"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/gridview"
android:layout_toRightOf="#+id/txt_grid" />
<GridView
android:id="#+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:stretchMode="columnWidth"
android:layout_below="#+id/txt_grid"
android:gravity="center"
/>
</RelativeLayout>
and this is my getView method for custom adapter :
// create a new VideoView for each item referenced by the Adapter
#SuppressLint("NewApi")
public View getView(int position, View convertView, ViewGroup parent) {
VideoView videoView;
if (convertView == null) { // if it's not recycled, initialize some attributes
videoView = new VideoView(mContext);
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
int width=0;
int height=0;
if (android.os.Build.VERSION.SDK_INT >= 13){
Point size = new Point();
display.getSize(size);
width = size.x;
height = size.y;
}
else{
width = display.getWidth();
height = display.getHeight();
}
// Calculate ActionBar height
TypedValue tv = new TypedValue();
int actionBarHeight=0;
if (mContext.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true))
{
actionBarHeight = TypedValue.complexToDimensionPixelSize(tv.data,mContext.getResources().getDisplayMetrics());
}
TextView textview = (TextView) ((Activity) mContext).findViewById (it.nexera.visiamobile.R.id.txt_grid);
int textview_height=textview.getHeight();
height=height-actionBarHeight-textview_height;
AbsListView.LayoutParams param = new AbsListView.LayoutParams(
(width/COL_NUMBER),
(height/ROW_NUMBER));
videoView.setLayoutParams(param);
Uri video = Uri.parse(mvideoSrc[position]);
videoView.setVideoURI(video);
videoView.start();
} else {
videoView = (VideoView) convertView;
}
return videoView;
}
Your problem is that you retrieve at the beginning the size of the whole screen of your device.
So ActionBar must be substracted, but any other views if your layout doesn't take all the remaining space. So your method contradicts android modularity, for example, if your view is used in different ways depending on the size of the device.
I think what you need instead is using ViewTreeObserver, like this :
final View myView = ... // The RelativeLayout that's declared as root of your layout file
myView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// You can here use View.getMeasuredWidth() or View.getMeasuredHeight() which correspond to the available space for the view containing your GridView and your TextView and then set your TextView's size
}
}
Edit : To make the gridview fill all remaining space you can instead use a LinearLayout, using its weight attribute :
<?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:orientation="vertical"
android:weightSum="1"
tools:context="it.nexera.visiamobile.ViewLiveMultiActivity"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/txt_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textColor="#454545"
android:gravity="left"
android:text="#string/sel_grid" />
<Spinner
android:id="#+id/grid_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<GridView
android:id="#+id/gridview"
android:layout_width="0dp"
android:layout_height="0dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:layout_weight="1"
/>
</LinearLayout>
Have you tried by adding a RelativeLayout under the Grid, and adding two hidden views on it, one in the topleft corner, and another one in the bottoright corner (1dip height/width, for example). Then, from code you can findViewById them, and call getLocationOnScreen. It's just the first dirty idea that came to my mind. That way you can get the exact size in pixels (or dpi) of the Grid.
How do you make a progressbar with rounded corner at the right side (the end), not only in the left side (the start). What I currently have is nearly the layout what I want but the progressbar loader is just a straight vertical line, I'd like to get this line rounded.
Basically you should make a custom Widget, so you can cutomize it to your taste.
Here is a tutorial on exactly what you're looking for. link!
So what I ended up doing this in xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#color/white"
android:id="#+id/splash_linear">
<FrameLayout
android:layout_width="144dp"
android:layout_height="13dp"
android:layout_gravity="center"
android:layout_marginTop="20dp">
<View android:id="#+id/progress_horizontal"
android:background="#drawable/progress_background"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<View android:id="#+id/progress_horizontal_bar"
android:background="#drawable/progress_bar"
android:layout_width="0dp"
android:layout_height="match_parent"/>
</FrameLayout>
</LinearLayout>
Then in code:
public void updateProgress(int percent) {
int progressBarSizeDp = 144; // the size of the progressbar
float scale = (float) (progressBarSizeDp/100.0);
int progressSize = (int) (percent * scale);
if(progressSize > progressBarSizeDp) {
progressSize = progressBarSizeDp;
} else if(progressSize < 20) {
progressSize = 20;
}
View progressBar = (View) findViewById(R.id.progress_horizontal_bar);
int py = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, progressSize, getResources().getDisplayMetrics());
LayoutParams params = new FrameLayout.LayoutParams(py, LayoutParams.MATCH_PARENT);
progressBar.setLayoutParams(params);
View splashMain = (View) findViewById(R.id.splash_linear);
splashMain.invalidate();
}
Found a nice link:
Custom progress bar with rounded corners
Basically it uses a custom RelativeLayout and a 9-patch approach to draw the rounded progress bar.