When I change textSize attribute lower than 18sp the height changes. And when I add a drawable programmatically it also changes. What I want to do is keep the height fixed. How to do this?
See below, the problem is EditText 2. I want to keep the height fixed when I add the drawable in Java.
// layout.xml
<EditText
android:id="#+id/edittext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#C8E6C9"
android:paddingVertical="12dp" />
<EditText
android:id="#+id/edittext2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="#C8E6C9"
android:paddingVertical="12dp"
android:textSize="14sp" />
// EditText 1
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (count > 0) {
editText.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_close, 0);
} else {
editText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
}
// EditText 2
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if (count > 0) {
editText1.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_close, 0);
} else {
editText1.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
}
I wouldn't expect there to be a solution to this without changing your implementation slightly. The EditText wouldn't ever be able to measure it's height properly without having some information about the drawable in advance.
So a few solutions for you:
Minimum height
If you know the height of the drawable in advance, you could set a minimum height of the EditText to match it.
Just use a separate ImageView
Wrap the EditText in a horizontal LinearLayout with an ImageView containing your drawable.
You could also play around with changing the tint or alpha of the drawable instead of adding/removing it but I would recommend against it.
As a side note it seems like your intended use case is a button to clear the EditText? If so I would definitely go for the second approach but using an ImageButton so as to use the standard Android click handling instead of having to fiddle with touch listeners (which I think would be the only way to detect touch on a compound drawable).
Finally if you're using the Material Components library, the TextInputLayout component has the functionality for clearing a text field baked in, which you can read about here: Text fields.
Related
Here are the XML and Java snippets:
<EditText android:id="#+id/paper_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Select Paper"
android:maxLength="1"
android:inputType="phone"
android:onClick="getPaper"/>
public void getPaper(View view){
EditText paperText = findViewById(R.id.paper_text);
paper = paperText.getText().toString();
}
So if I press on the hint, the keyboard shows up and I type in a number such as "1". (I only need integer numbers so I thought I'd set the type to "number" or "phone", but the problem occurs with all types.) When I press return to close the keyboard, the number isn't stored in the variable "paper". (I used the debugger to check). However If I open the keyboard again, press backspace and type any number, it then stores the previous instance of the EditText, in this case 1.
To summarize, if I input the following numbers one after the other, this is what is stored:
input: 2, 3, 3, 1, 2
stores: blank, 2, 3, 3, 1
You can use addTextChangedListener instead of onClick()
Try this
EditText paperText = findViewById(R.id.paper_text);
paperText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
String paper = paperText.getText().toString().trim();
Toast.makeText(MainActivity.this, "" + paper, Toast.LENGTH_SHORT).show();
}
#Override
public void afterTextChanged(Editable editable) {
}
});
And Remove android:onClick="getPaper" from EditText
<EditText android:id="#+id/paper_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="Select Paper"
android:maxLength="1"
android:inputType="phone"
/>
By looking at the code snippet that you have provided, it seems like you have set the onclicklistner in edit text. So when you tap on the edittext as on first time it is blank, your first number is blank and then remaining numbers are stored.
FYI
The method that you mentioned in onclick attribute has View as an input argument parameter, this is the same view on which onclick or onclicklistner is set. In your case it is edittext, so no need to write findViewById() as this will reduce your app performance.
As various other people have pointed out, do not use android:onClick. Think about when this event is fired. It only gets fired when your user clicks/taps the EditText (typing on keyboard is NOT a clicking event).
When you subscribe to onClick listener, your method handler gets called ONLY when you click on it (in your case closing the keyboard with back button and then tapping the EditText again to start typing).
On the other hand, if you subscribe to TextChangeListener, you get callbacks for every time there is a change in text held by the EditText.
Hope that makes things easier to understand. Make sure that you always read the method javadocs or at least the Android documentation.
My guess is that you want the user to type, and then press a button to do something with the typed text. So, just add a Button in your layout along with EditText, and then subscribe to onClick of the button to perform your action based on the value of the EditText.
I have 4 imageview in one rows but i wanted to visible and gone need to do based on response. so how to remove unused space which i hardcoded layout.
<ImageView
android:id="#+id/imgFacebookUrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/facebook_login_guest"
app:layout_anchor="#id/appbar"
android:visibility="gone"
app:layout_anchorGravity="bottom|center" />
<ImageView
android:id="#+id/imgLinkdinUrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="200dp"
android:src="#drawable/icon_linkdin"
app:layout_anchor="#id/appbar"
android:visibility="gone"
app:layout_anchorGravity="bottom|center" />
public void setPadding (int left, int top, int right, int bottom)
Sets the padding. The view may add on the space required to display
the scrollbars, depending on the style and visibility of the
scrollbars. So the values returned from getPaddingLeft(),
getPaddingTop(), getPaddingRight() and getPaddingBottom() may be
different from the values set in this call.
Finally
ImageView ImageViewObj = (ImageView) findViewById(R.id.imgLinkdinUrl);
ImageViewObj.setPadding(0, 0, 0, 0);
This deletes all paddings (all sides) for your imgLinkdinUrl ImageView:
ImageView linkedInUrlImage = (ImageView) findViewById(R.id.imgLinkdinUrl);
linkedInUrlImage.setPadding(0, 0, 0, 0);
I am writing a simple text/eBook viewer for Android, so I have used a TextView to show the HTML formatted text to the users, so they can browse the text in pages by going back and forth. But my problem is that I can not paginate the text in Android.
I can not (or I don't know how to) get appropriate feedback from the line-breaking and page-breaking algorithms in which TextView uses to break text into lines and pages. Thus, I can not understand where the content ends in the actual display, so that I continue from the remaining in the next page. I want to find way to overcome this problem.
If I know what is the last character painted on the screen, I can easily put enough characters to fill a screen, and knowing where tha actual painting was finished, I can continue at the next page. Is this possible? How?
Similar questions have been asked several times on StackOverflow, but no satisfactory answer was provided. These are just a few of them:
How to paginate long text into pages in Android?
Ebook reader pagination issue in android
Paginate text based on rendered text size
There was a single answer, which seems to work, but it is slow. It adds characters and lines until the page is filled. I don't think this is a good way to do page breaking:
How to break styled text into pages in Android?
Rather than this question, it happens that PageTurner eBook reader does it mostly right, although it is somehow slow.
https://github.com/nightwhistler/pageturner
PS: I am not confined to TextView, and I know line breaking and page breaking algorithms can be quite complex (as in TeX), so I am not looking for an optimal answer, but rather a reasonably fast solution that can be usable by the users.
Update: This seems to be a good start for getting the right answer:
Is there a way of retrieving a TextView's visible line count or range?
Answer: After completing text layout, it is possible to find out the visible text:
ViewTreeObserver vto = txtViewEx.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
ViewTreeObserver obs = txtViewEx.getViewTreeObserver();
obs.removeOnGlobalLayoutListener(this);
height = txtViewEx.getHeight();
scrollY = txtViewEx.getScrollY();
Layout layout = txtViewEx.getLayout();
firstVisibleLineNumber = layout.getLineForVertical(scrollY);
lastVisibleLineNumber = layout.getLineForVertical(height+scrollY);
}
});
NEW ANSWER
PagedTextView library (in Kotlin) summarises the below lying algorithm by extending Android TextView. The sample app demonstrates the usage of the library.
Setup
dependencies {
implementation 'com.github.onikx:pagedtextview:0.1.3'
}
Usage
<com.onik.pagedtextview.PagedTextView
android:layout_width="match_parent"
android:layout_height="match_parent" />
OLD ANSWER
The algorithm below implements text pagination in separation of TextView itself lacking simultaneous dynamic change of both the TextView attributes and algorithm configuration parameters.
Background
What we know about text processing within TextView is that it properly breaks a text by lines according to the width of a view. Looking at the TextView's sources we can see that the text processing is done by the Layout class. So we can make use of the work the Layout class does for us and utilizing its methods do pagination.
Problem
The problem with TextView is that the visible part of text might be cut vertically somewhere at the middle of the last visible line. Regarding said, we should break a new page when the last line that fully fits into a view's height is met.
Algorithm
We iterate through the lines of text and check if the line's bottom exceeds the view's height;
If so, we break a new page and calculate a new value for the cumulative height to compare the following lines' bottom with (see the implementation). The new value is defined as top value (red line in the picture below) of the line that hasn't fit into the previous page + TextView's height.
Implementation
public class Pagination {
private final boolean mIncludePad;
private final int mWidth;
private final int mHeight;
private final float mSpacingMult;
private final float mSpacingAdd;
private final CharSequence mText;
private final TextPaint mPaint;
private final List<CharSequence> mPages;
public Pagination(CharSequence text, int pageW, int pageH, TextPaint paint, float spacingMult, float spacingAdd, boolean inclidePad) {
this.mText = text;
this.mWidth = pageW;
this.mHeight = pageH;
this.mPaint = paint;
this.mSpacingMult = spacingMult;
this.mSpacingAdd = spacingAdd;
this.mIncludePad = inclidePad;
this.mPages = new ArrayList<>();
layout();
}
private void layout() {
final StaticLayout layout = new StaticLayout(mText, mPaint, mWidth, Layout.Alignment.ALIGN_NORMAL, mSpacingMult, mSpacingAdd, mIncludePad);
final int lines = layout.getLineCount();
final CharSequence text = layout.getText();
int startOffset = 0;
int height = mHeight;
for (int i = 0; i < lines; i++) {
if (height < layout.getLineBottom(i)) {
// When the layout height has been exceeded
addPage(text.subSequence(startOffset, layout.getLineStart(i)));
startOffset = layout.getLineStart(i);
height = layout.getLineTop(i) + mHeight;
}
if (i == lines - 1) {
// Put the rest of the text into the last page
addPage(text.subSequence(startOffset, layout.getLineEnd(i)));
return;
}
}
}
private void addPage(CharSequence text) {
mPages.add(text);
}
public int size() {
return mPages.size();
}
public CharSequence get(int index) {
return (index >= 0 && index < mPages.size()) ? mPages.get(index) : null;
}
}
Note 1
The algorithm works not just for TextView (Pagination class uses TextView's parameters in the implementation above). You may pass any set of parameters StaticLayout accepts and later use the paginated layouts to draw text on Canvas/Bitmap/PdfDocument.
You can also use Spannable as yourText parameter for different fonts as well as Html-formatted strings (like in the sample below).
Note 2
When all text has the same font size, all lines have equal height. In that case you might want to consider further optimization of the algorithm by calculating an amount of lines that fits into a single page and jumping to the proper line at each loop iteration.
Sample
The sample below paginates a string containing both html and Spanned text.
public class PaginationActivity extends Activity {
private TextView mTextView;
private Pagination mPagination;
private CharSequence mText;
private int mCurrentIndex = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pagination);
mTextView = (TextView) findViewById(R.id.tv);
Spanned htmlString = Html.fromHtml(getString(R.string.html_string));
Spannable spanString = new SpannableString(getString(R.string.long_string));
spanString.setSpan(new ForegroundColorSpan(Color.BLUE), 0, 24, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spanString.setSpan(new RelativeSizeSpan(2f), 0, 24, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spanString.setSpan(new StyleSpan(Typeface.MONOSPACE.getStyle()), 0, 24, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spanString.setSpan(new ForegroundColorSpan(Color.BLUE), 700, spanString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spanString.setSpan(new RelativeSizeSpan(2f), 700, spanString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spanString.setSpan(new StyleSpan(Typeface.MONOSPACE.getStyle()), 700, spanString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
mText = TextUtils.concat(htmlString, spanString);
mTextView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Removing layout listener to avoid multiple calls
mTextView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
mPagination = new Pagination(mText,
mTextView.getWidth(),
mTextView.getHeight(),
mTextView.getPaint(),
mTextView.getLineSpacingMultiplier(),
mTextView.getLineSpacingExtra(),
mTextView.getIncludeFontPadding());
update();
}
});
findViewById(R.id.btn_back).setOnClickListener(v -> {
mCurrentIndex = (mCurrentIndex > 0) ? mCurrentIndex - 1 : 0;
update();
});
findViewById(R.id.btn_forward).setOnClickListener(v -> {
mCurrentIndex = (mCurrentIndex < mPagination.size() - 1) ? mCurrentIndex + 1 : mPagination.size() - 1;
update();
});
}
private void update() {
final CharSequence text = mPagination.get(mCurrentIndex);
if(text != null) mTextView.setText(text);
}
}
Activity's layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
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" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/btn_back"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#android:color/transparent"/>
<Button
android:id="#+id/btn_forward"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#android:color/transparent"/>
</LinearLayout>
<TextView
android:id="#+id/tv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
Screenshot:
Take a look at my demo project.
The "magic" is in this code:
mTextView.setText(mText);
int height = mTextView.getHeight();
int scrollY = mTextView.getScrollY();
Layout layout = mTextView.getLayout();
int firstVisibleLineNumber = layout.getLineForVertical(scrollY);
int lastVisibleLineNumber = layout.getLineForVertical(height + scrollY);
//check is latest line fully visible
if (mTextView.getHeight() < layout.getLineBottom(lastVisibleLineNumber)) {
lastVisibleLineNumber--;
}
int start = pageStartSymbol + mTextView.getLayout().getLineStart(firstVisibleLineNumber);
int end = pageStartSymbol + mTextView.getLayout().getLineEnd(lastVisibleLineNumber);
String displayedText = mText.substring(start, end);
//correct visible text
mTextView.setText(displayedText);
Surprisingly finding libraries for Pagination is difficult. I think it's better to use another Android UI element besides TextView. How about WebView?
An example # android-webview-example.
Code snippet:
webView = (WebView) findViewById(R.id.webView1);
String customHtml = "<html><body><h1>Hello, WebView</h1></body></html>";
webView.loadData(customHtml, "text/html", "UTF-8");
Note: This simply loads data onto a WebView, similar to a web browser. But let's not stop with just this idea. Add this UI to using pagination by WebViewClient onPageFinished . Please read on SO link # html-book-like-pagination.
Code snippet from one of the best answer by Dan:
mWebView.setWebViewClient(new WebViewClient() {
public void onPageFinished(WebView view, String url) {
...
mWebView.loadUrl("...");
}
});
Notes:
The code loads more data upon page scroll.
On the same webpage, there is a posted answer by Engin Kurutepe to set measurements for the WebView. This is necessary for specifing a page in pagination.
I have not implemented pagination but I think this is a good start and shows promise, should be fast. As you can see, there are developers that have implemented this feature.
I have a series of ImageViews that I programatically added into a LinearLayout, so they all end up horizontally lined up.
But when I try to use a TranslateAnimation to move all the images at once, a 1 pixel white gap flashes between every ImageView for about .02 seconds and then disappears. And this seems to consistently happen every 2 seconds or so.
TranslateAnimation moveLeft = new TranslateAnimation(0, -1250, 0, 0);
moveLeft.setDuration(10000);
moveLeft.setFillAfter(true);
I make my ImageViews all at the same time before I move them. (Also, the ImageViews have all default settings) I've also confirmed that there are no white gaps between the ImageViews before I move them.
The flickering only happens when I set all the ImageViews's animations to moveLeft.
Also, here is the class in question :
public class Terrain {
Bitmap tile;
InputStream is;
ImageView imageViewPlatform;
Drawable tileDrawable;
ArrayList<ImageView> terrainArray = new ArrayList<ImageView>();
ArrayList<TranslateAnimation> moveLeftArray = new ArrayList<TranslateAnimation>();
int count = 0;
int terrainBlockNumber = 0;
boolean initialized = false;
TranslateAnimation moveLeft;
public void initialize(Activity activity){
is = activity.getResources().openRawResource(+R.drawable.game_tile);
tile = BitmapFactory.decodeStream(is);
tileDrawable = new BitmapDrawable(activity.getResources(), tile);
moveLeft = new TranslateAnimation(0, -1250, 0, 0);
moveLeft.setDuration(10000);
moveLeft.setFillAfter(true);
initialized = true;
Log.d("Terrain", "Terrain images are initialized.");
}
public void draw(Activity activity, LinearLayout linearLayout,
LinearLayout.LayoutParams layoutParams) {
if (!initialized) {
throw new RuntimeException("initialize() method must " +
"be called before the draw() method.");
}else{
terrainArray.add(new ImageView(activity));
++count;
terrainArray.get(count-1).setImageDrawable(tileDrawable);
linearLayout.addView(terrainArray.get(count-1), layoutParams);
}
}
public void move(Activity activity) {
terrainBlockNumber++;
final int terrainAnimationBlock = terrainBlockNumber;
moveLeft.setAnimationListener(new Animation.AnimationListener() {
int currentCount = terrainAnimationBlock;
#Override
public void onAnimationStart(Animation animation) {
Log.d("Animation Started", "Block Number is " + currentCount);
}
#Override
public void onAnimationEnd(Animation animation) {
terrainArray.get(currentCount - 1).setVisibility(View.GONE);
Log.d("Terrain Deletion", "Block number " +
currentCount + " has been deleted.");
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
terrainArray.get(terrainBlockNumber - 1).startAnimation(moveLeft);
}
}
}
This is the XML file for the activity
<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"
tools:context="com.example.project.PlayActivity">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/linearLayout"
android:weightSum="1"
android:layout_alignParentTop="true"
android:layout_marginTop="200dp"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
</LinearLayout>
</RelativeLayout>
UPDATE :
Moving the entire LinearLayout does not seem to work either. Although, moving the entire LinearLayout isn't really helpful. It cuts off ImageViews that are off-screen.
But since you requested it, all I did was change the move method to :
public void move(LinearLayout linearLayout){
linearLayout.setAnimation(moveLeft);
}
All the images did actually move at the same speed, and there is still the flickering between the images.
UPDATE 2
I have confirmed that it has something to do with my images/how they're formatted/the size of the images or something along those lines.
If it is any help, the image I use is 95 X 84 pixels. (It's really tiny)
If you have several images you might want to:
Use a RecyclerView. This gives you more control over animations and decorations, and optimizes the memory usage at the same time. This answer will help you understand how to make your animations.
Make sure you are not constantly resizing your images. If the animation needs to handle images that are originally too big, it might impact on the quality of the animation (i.e. use thumbnails and fixed sizes in order to avoid costly computations)
For instance, if your original images are 600x800 but your image
view has a centerCrop/fit/etc ending up occupying a space of 200x200,
android will be doing a lot of resizing to match those settings. The
more computations it does, the more chances you get of missing
frames. In other words: what you experience is a low framerate,
which happens when android is unable to finish all drawing
computations in time for the next screen refresh.
There are different problems you can attack:
Reduce the computations by using the right image sizes
Smaller images also mean less memory usage, which reduces the need of memory reallocation or forced garbage collection.
Avoid computing/rendering things that are invisible. Either because they are out of screen or because something overlaps them. In your case, recycler view might help to load only the images on your visible screen, instead of wasting space and computations on images that are out of sight at the moment.
Reduce the layout rewrite. Android tries to render only the sections with updates, instead of re-render all the screen. But if your layout forces other layouts to recalculate their size, you can end up forcing a whole resize. In your case, do not use LinearLayout to list images. Instead, use some layout that is actually designed for that sort of things. As I said, RecyclerView with the default LinearLayoutManager works very well.
Check if you have hardware acceleration turned on.
Try to put the ImageViews in a LinearLayout or other ViewGroup and animate the entire ViewGroup and see if that helps.
I have a page that consists of an ImageView, and a RecyclerView. The RecyclerView contains a small number of items (currently three) and only takes up around a quarter of the screen on my test device. However, despite trying numerous layout options, I cannot get the RecyclerView to effectively wrap its content and take up just enough space required to contain these three rows, and leave the rest of the space for my ImageView.
To help illustrate what I mean, I have drawn two diagrams. The first shows what I would like to happen, and the second what is happening:
So far, I have tried several different combinations of RelativeLayout - for instance, I will set RecyclerView to layout:align_ParentBottom and the second RelativeLayout that contains the ImageView to layout:alignComponent so that its bottom matches the RecyclerView top (this would normally drag the ImageView layout so that it fills any reminaing space, which is what I would like to happen.)
The RecyclerView though just keeps occupying all the space it can, even though it only contains a few rows. The current "solution" I have is to place everything inside a LinearLayout and set less gravity to the RecyclerView, but it isn't ideal, because on different emulators it wont line up completely with the bottom of the screen, and in others there isn't enough room and the RecyclerView becomes scrollable.
Thanks in advance for any help and suggestions anyone can offer.
Many thanks to everyone who contributed, but I have found a programmatic solution outside of the layout files. In case anyone else is looking for a solution to this problem, I found one here.
It appears as if there is an issue with RecyclerView currently where it doesn't wrap content. The answer is to construct a custom class that extends LinearLayoutManager. I have posted the solution that worked for me below - most of it is copy and pasted from the answer given in the link I quoted. The only small issue is that it doesn't account for the extra space added by decorations, which is why I had to make a small tweak to the following line near the end of the code:
//I added the =2 at the end.
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin + 2;
Here is the code in its entirety:
public class HomeLinearLayoutManager extends LinearLayoutManager{
HomeLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
private int[] mMeasuredDimension = new int[2];
#Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
int width = 0;
int height = 0;
for (int i = 0; i < getItemCount(); i++) {
measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
if (getOrientation() == HORIZONTAL) {
width = width + mMeasuredDimension[0];
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
height = height + mMeasuredDimension[1];
if (i == 0) {
width = mMeasuredDimension[0];
}
}
}
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
width = widthSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
height = heightSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
setMeasuredDimension(width, height);
}
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
View view = recycler.getViewForPosition(position);
if (view != null) {
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
getPaddingLeft() + getPaddingRight(), p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
getPaddingTop() + getPaddingBottom(), p.height);
view.measure(childWidthSpec, childHeightSpec);
measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin + 2;
recycler.recycleView(view);
}
}
}
Thanks again.
Put the two in a RelativeLayout and make ImageView fill parent:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<RecyclerView
android:id="#+id/recyclerView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/>
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_above="#id/recyclerView"
/>
</RelativeLayout>
Edit: Wrote TextView by accident. Fixed.
The only solution I can think of is using layout weight. Specify 70% of the screen for the image and 30% for the Recyclerview as you said you have just 3 rows. Use adjustViewByBounds to ensure the images aspect ratio is maintained.
My code below:
<?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">
<ImageView
android:src="#drawable/ic_round_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:layout_weight=".9"/>
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight=".1"/>
</LinearLayout>