Google maps v2 fragment view flickers when changing it's width - java

My app contains Google maps v2 API fragment view. On button click I want to change it's width from left to right side like this: Google map taking half screen --> Google map taking full screen.
It works, But I see strange black area on the right side of the screen during width transition.
I have read that it's Google bug and that they released fix for this but it only works since Android 4.1 version. I am using Android 4.0
Also I checked some workarounds mentioned by another people but all of them focuses on tasks such like scrolling, etc. Nobody is mentioning google maps view width change.
Anybody can help me?
My xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/mainLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="510dp"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp" />
<ImageView
android:id="#+id/mapExpandButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="25dp"
android:layout_marginRight="510dp"
android:background="#drawable/map_expand" />
<ImageView
android:id="#+id/mapCloseButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="25dp"
android:layout_marginLeft="15dp"
android:background="#drawable/map_close" />
Google maps init:
mapFragment = (SupportMapFragment)getActivity().getSupportFragmentManager().findFragmentById(R.id.map);
map = mapFragment.getMap ();
map.getUiSettings().setRotateGesturesEnabled(false); // disable rotation
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(54.6873439, 25.2770559) , 16.0f)); // set initial position
map.getUiSettings().setZoomControlsEnabled(false);
On "expand" button click, I am expanding google map like this:
ResizeWidthAnimation anim = new ResizeWidthAnimation(mapFragment.getView (), width);
anim.setDuration(400);
mapFragment.getView ().startAnimation(anim);
Animation class:
public class ResizeWidthAnimation extends Animation
{
private int mWidth;
private int mStartWidth;
private View mView;
public ResizeWidthAnimation(View view, int width)
{
mView = view;
mWidth = width;
mStartWidth = view.getWidth();
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t)
{
int newWidth = mStartWidth + (int) ((mWidth - mStartWidth) * interpolatedTime);
mView.getLayoutParams().width = newWidth;
mView.requestLayout();
}
#Override
public void initialize(int width, int height, int parentWidth, int parentHeight)
{
super.initialize(width, height, parentWidth, parentHeight);
}
#Override
public boolean willChangeBounds()
{
return true;
}
}

We solved this issue by adding a view on top of the map and animating this view width change. Nothing else worked.
Tips to avoid Google map flickering bug:
Don't do "add" or "replace" operations with the fragment which contains Google map fragment inside. Instead, use show/hide operations with fragment view. This will not recreate already created fragment when you use these operations. For example:
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft1 = manager.beginTransaction();
ft1.show (someFragment);
ft1.hide (someFragment2);
ft1.commit();
During app execution, don't try to change google map fragment dimension parameters (width, height, margin, etc.) at all. Search workarounds by using another (additional) views if you need some google map animations, width changes, etc.

Relayouting on each frame of your animation is very expensive (even more for a map) and you should not do that. If you really want to animate the bounds of your map, try to apply a scale animation, then at the end of it, relayout your View to its final new dimensions and disable scaling.
To improve animation performance using a map or any other SurfaceView, you can call requestTransparentRegion() on the MapFragment container, passing itself as argument.

Related

Why does progress drawable changes its size after setting it programmatically?

I have to set progressDrawable for AppCompatSeekBar programmatically but it leads to changing the SeekBar's progressDrawable height after I set it for the second time and further. You can see what I mean below:
What should I do to change this behavior? I already set minHeight and maxHeight to 12dp as it was suggested in another answer.
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatSeekBar
android:id="#+id/seek_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:maxHeight="12dp"
android:minHeight="12dp"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:progress="50"
android:splitTrack="false"
android:thumb="#drawable/my_thumb" />
<Button
android:id="#+id/change_seek_bar_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center"
android:text="Change seek bar" />
</FrameLayout>
my_thumb.xml:
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="23dp"
android:height="23dp"
android:viewportWidth="23"
android:viewportHeight="23">
<path
android:fillColor="#B7BDC2"
android:pathData="M11.5,20L11.5,20A9.5,9.5 0,0 1,2 10.5L2,10.5A9.5,9.5 0,0 1,11.5 1L11.5,1A9.5,9.5 0,0 1,21 10.5L21,10.5A9.5,9.5 0,0 1,11.5 20z" />
</vector>
MainActivity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.change_seek_bar_button);
SeekBar seekBar = findViewById(R.id.seek_bar);
// sets it the right way
setProgressDrawable(seekBar);
// on button click it sets progressDrawable with wrong height
button.setOnClickListener((view) -> setProgressDrawable(seekBar));
}
private void setProgressDrawable(SeekBar seekBar) {
GradientDrawable progressDrawable = new GradientDrawable(
GradientDrawable.Orientation.LEFT_RIGHT,
new int[]{0xFF000000, generateRandomColor()}
);
seekBar.setProgressDrawable(progressDrawable);
}
private int generateRandomColor() {
Random random = new Random();
return Color.argb(255, random.nextInt(256), random.nextInt(256), random.nextInt(256));
}
}
Most probably the problem is in ProgressBar.updateDrawableBounds(int w, int h). When it calls mProgressDrawable.setBounds(0, 0, right, bottom), it doesn't really take into account that progressDrawable might not be equal to the height of the whole View. But initially this function is called when width and height are 0's and I guess that's why it works for the first time.
The problem is kind of clear, so the most obvious solution is to change bounds after setting new progressDrawable:
button.setOnClickListener((view) -> {
setProgressDrawable(seekBar);
// converting 12 dp to pixels
int desiredHeight = (int) (12 * Resources.getSystem().getDisplayMetrics().density);
Rect bounds = seekBar.getProgressDrawable().copyBounds();
int actualTop = (int) Math.round((bounds.bottom - bounds.top) / 2.0 - desiredHeight / 2.0);
seekBar.getProgressDrawable().setBounds(bounds.left, actualTop, bounds.right, actualTop + desiredHeight);
});
And it actually solves the problem.

Center crop dont work in gridlayoutmaneger Android

I have grid view which is using GridLayoutManager and the RecyclerView
grid has 3 rows which are working fine as you see,[![enter image description here][1]][1]
but for some reason, image views scale type won't work on any of the items and those items you see work fine because the resolution already is square mean 512*512 but if you see the last item that has low resolution it have white space in left and right.
that's my code from a setup list
int getori = getResources().getConfiguration().orientation;
if (getori == Configuration.ORIENTATION_PORTRAIT) {
gl = new GridLayoutManager(getBaseContext(), 3);
} else if (getori == Configuration.ORIENTATION_LANDSCAPE){
gl = new GridLayoutManager(getBaseContext(), 6);
}
gg.setHasFixedSize(true);
gg.setFitsSystemWindows(true);
gg.setLayoutManager(gl);
gg.setAdapter(startpostsystem);
that's my grid adapter code
#Override
public void onBindViewHolder(Grid_view holder, final int position) {
holder.im.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String getfiledop = fall[position].getAbsolutePath();
Intent is = new Intent(cm,Open_post_item.class);
is.putExtra("req",12);
cm.startActivity(is);
and this is my grid view items layout code.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="140dp">
<ImageView
android:id="#+id/imageView18"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
app:srcCompat="#drawable/sunbow100" />
I tried to use :
android:scaleType="centerCrop"
android:adjustViewBounds="true"
or fitxy it make it worse
view bounds won't work either.
if i add more images like 800*400 or ... it will have white space
so where is problem where I do wrong.
try using android:src in place of app:srcCompat
<ImageView
android:id="#+id/imageView18"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:src="#drawable/sunbow100" />

MapView in lite mode causes RecyclerView to not scroll correctly

I'm building a chat app in Android Studio with the abitily to send routes on a map. I've implemented this by using a RecyclerView and ViewHolders, which hold the necessary UI with MapViews in lite mode (map:liteMode="true"). Thing is, when I add a map UI element to the recyclerView and scroll to the end by using scrollToPosition(adapter.getItemCount() - 1), the scrolling has trouble following the views and is always slightly off, as seen on the screenshot
(https://i.postimg.cc/BvMzrHJL/Screenshot-20190526-005535.png).
Moreover, the keyboard gets confused about the height of the views as well when clicked (https://i.postimg.cc/Hs6BsHfR/Screenshot-20190526-011647.png).
I have tried switching lite mode off, but it makes the scrolling laggy and handling lifecycle events becomes an issue since my MapViews are in ViewHolders, not in Activities or Fragments, see official documentation:
Users of this class [MapView] must forward all the life cycle methods from the
Activity or Fragment containing this view to the corresponding ones in
this class.
I have also tried changing the height of the layout from android:layout_height="wrap_content" to android:layout_height="250dp", but that also didn't work at all.
Also, scrolling works just fine with Views containing only text or an empty RelativeLayout istead of MapView.
I used this sample from Google's developer documentation https://github.com/googlemaps/android-samples/blob/master/ApiDemos/java/app/src/main/java/com/example/mapdemo/LiteListDemoActivity.java
So here is my ViewHolder (one of two):
private class SentRouteViewHolder extends RecyclerView.ViewHolder implements OnMapReadyCallback
{
MapView sentMap;
TextView routeSentTime;
GoogleMap map;
public SentRouteViewHolder(#NonNull View itemView) {
super(itemView);
sentMap = itemView.findViewById(R.id.sent_map);
routeSentTime = itemView.findViewById(R.id.route_sent_time);
sentMap.onCreate(null);
sentMap.onResume();
sentMap.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
MapsInitializer.initialize(getApplicationContext());
map = googleMap;
setMapRoute();
}
void bind(Message message)
{
sentMap.setTag(message);
setMapRoute();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
routeSentTime.setText(simpleDateFormat.format(message.getTime()));
}
void setMapRoute()
{
if(map == null) return;
Message message = (Message) sentMap.getTag();
if(message==null) return;
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
}
}
And adding the item to the RecyclerView:
activeCollection.add(newMessage).addOnSuccessListener(documentReference -> {
documentReference.get().addOnSuccessListener(documentSnapshot -> {
adapter.addMessage(documentSnapshot);
adapter.notifyItemInserted(adapter.getItemCount());
chatReycler.scrollToPosition(adapter.getItemCount()-1);
});
});
The onBindViewHolder:
SentRouteViewHolder routeViewHolder = (SentRouteViewHolder) viewHolder;
routeViewHolder.bind(message);
The onCreateViewHolder:
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.route_sent,parent,false);
Log.v("measure",String.valueOf(v.getMeasuredHeight()));
return new SentRouteViewHolder(v);
RecyclerView configuration:
manager.setStackFromEnd(true);
chatReycler.setLayoutManager(manager);
chatReycler.setAdapter(adapter);
chatReycler.setHasFixedSize(false);
chatReycler.setRecyclerListener(viewHolder -> {
if(viewHolder.getItemViewType()==ChatRecyclerViewAdapter.VIEW_TYPE_ROUTE_RECEIVED)
{
ChatRecyclerViewAdapter.ReceivedRouteViewHolder holder = (ChatRecyclerViewAdapter.ReceivedRouteViewHolder) viewHolder;
if(holder.map!=null)
{
holder.map.clear();
holder.map.setMapType(GoogleMap.MAP_TYPE_NONE);
}
}
else if (viewHolder.getItemViewType()==ChatRecyclerViewAdapter.VIEW_TYPE_ROUTE_SENT)
{
ChatRecyclerViewAdapter.SentRouteViewHolder holder = (ChatRecyclerViewAdapter.SentRouteViewHolder) viewHolder;
if(holder.map!=null)
{
holder.map.clear();
holder.map.setMapType(GoogleMap.MAP_TYPE_NONE);
}
}
});
The ViewHolder XML file
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:paddingBottom="3dp"
android:layout_marginBottom="13dp">
<ImageView
android:id="#+id/route_received_background"
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_marginStart="15dp"
android:src="#drawable/message_received_background"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.gms.maps.MapView
xmlns:map="http://schemas.android.com/apk/res-auto"
android:id="#+id/received_map"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_margin="9dp"
app:layout_constraintBottom_toBottomOf="#+id/route_received_background"
app:layout_constraintEnd_toEndOf="#+id/route_received_background"
app:layout_constraintStart_toStartOf="#+id/route_received_background"
app:layout_constraintTop_toTopOf="#+id/route_received_background"
map:mapType="normal"
map:liteMode="true"
/>
<TextView
android:id="#+id/route_received_time"
style="#style/TextAppearance.MaterialComponents.Caption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:textSize="13sp"
app:layout_constraintBottom_toBottomOf="#+id/route_received_background"
app:layout_constraintStart_toEndOf="#+id/route_received_background"
tools:text="11:50" />
</android.support.constraint.ConstraintLayout>
I want the RecyclerView to scroll to the bottom of the sent map, and not to the middle of it. How can I make that happen?
I had a similar problem with scrolling and checked that the parent layout was 0dp high. I changed it to match_parent and it worked.
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"

How to make ActionBar Movable in "Accessibility Services"

I am new in the Topic "Accessibility Services".I am able to Scroll for button clicks, and able to switch off phone and many More things,
but i want to make my layout(action_bar.xml) Movable
So,
can anybody tell me please How to Make action_bar Movable
Here is my
action_bar.xml::
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/power"
android:layout_weight="1"
android:text="#string/power"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="#+id/volume_up"
android:text="#string/volume"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:layout_weight="1"
android:id="#+id/scroll"
android:text="#string/scroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="#+id/swipe"
android:text="#string/swipe"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
And ActionBarService.Java ,Where i Have Used it:
#Override
protected void onServiceConnected() {
// Create an overlay and display the action bar
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
mLayout = new FrameLayout(this);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
lp.format = PixelFormat.TRANSLUCENT;
lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.TOP;
LayoutInflater inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.action_bar, mLayout);
wm.addView(mLayout, lp);
}
The answer by #fishbone is mostly correct, EXCEPT for the little part where overlays in Accessibility Services are NOT the same. Certainly, making this assumption simplifies things, but it is ultimately false. There are very important considerations specific to accessibility services, and In most ways they behave exactly like activities, but the ways that Accessibility Services launch overlays is very important and different from the ways most views behave, particularly in how they intercept touch events. You have to be very careful with touch events. Ultimately you want the view to be touchable, BUT NOT, take up the whole window. The two types you can play around with for this would be:
TYPE_ACCESSIBILITY_OVERLAY
or
TYPE_APPLICATION_OVERLAY
These two behave similarly, but not. The latter may help you if you're stuck on receiving touch events in your actual view.
The core problem is, that the layout parameters available for WindowManager only allow you to either completely intercept touch events or to not do so at all. You can't have it do so for this part of your view, and not for others. The logic for attempting to pass events past your window through to a window that you don't own... just don't go there.
As such, what you have to do, is NOT have a complete layout view. You have to add your view as Touchable, but have your view ONLY take up the part of the screen that it actually has to overlay. This should obviously be as minimal as possible (becuase touch events won't be able to go beind this view). THEN you'll have to do a custom hold touch listener, and do the touch and drag logic to move your view around manually.
You could potentially use the touch/drag view ONLY for replacement. As in, have a button that enables "drag mode" to replace it. And have that by the only time the entire layout is added to the window, remove the layout, and just add the smaller, non-layout version that is just your toolbar view.
Unfortunately there is no simple answer here. This is not something that Accessibility APIs are intended to do. I would also feel obligated to warn you, that the new expectations for Accessibility Services that Google is mulling around would almost certainly result in an Accessibility Service that does something like this being removed/not allowed in the Google Play Store.
Overlays work by the same rules as the usual View on the Activity or Fragment. There is no magic property such android:movable="true" that can make an overlay movable. You should make it by yourself.
Here is my example of a movable View:
action_bar.xml (Here I replace LinearLayout with custom DraggableLayout)
<?xml version="1.0" encoding="utf-8"?>
<your.package.name.DraggableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="#+id/power"
android:layout_weight="1"
android:text="Power"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="#+id/volume_up"
android:text="Volume"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:layout_weight="1"
android:id="#+id/scroll"
android:text="Scroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="#+id/swipe"
android:text="Swipe"
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</your.package.name.DraggableLayout>
DraggableLayout.class
public class DraggableLayout extends LinearLayout implements View.OnDragListener {
GestureDetector mLongClickDetector;
Point mPickPoint;
public DraggableLayout(Context context) {
this(context, null, 0);
}
public DraggableLayout(Context context, #Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public DraggableLayout(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// When user performs a long press, we begin dragging
mLongClickDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
public void onLongPress(MotionEvent e) {
mPickPoint = new Point((int) e.getX(), (int) e.getY());
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(DraggableLayout.this) {
#Override
public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
outShadowSize.set(getWidth(), getHeight());
outShadowTouchPoint.set(mPickPoint.x, mPickPoint.y);
}
};
startDrag(null, shadowBuilder, null, 0);
}
});
}
#Override
protected void onAttachedToWindow() {
// We should register this class as OnDragListener to parent view to catch DROP events from it
((ViewGroup) getParent()).setOnDragListener(this);
super.onAttachedToWindow();
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//This is also an important point: we must intercept touch events before the child elements (Buttons and so on)
return mLongClickDetector.onTouchEvent(ev);
}
#Override
public boolean onDragEvent(DragEvent event) {
if (event.getAction() == DragEvent.ACTION_DROP) {
// And when user performs drop we change position of view
setX(event.getX() - mPickPoint.x);
setY(event.getY() - mPickPoint.y);
return true;
}
return false;
}
#Override
public boolean onDrag(View v, DragEvent event) {
return onDragEvent(event);
}
}
ActionBarService.Java
#Override
protected void onServiceConnected() {
// Create an overlay and display the action bar
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
mLayout = new FrameLayout(this);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
WindowManager.LayoutParams.MATCH_PARENT, // Overlay must be full screen otherwise my trick will not work
WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, // Allow another windows to receive touch events
PixelFormat.TRANSLUCENT);
LayoutInflater inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.action_bar, mLayout);
wm.addView(mLayout, lp);
}
It seems to be working, let me know if not that.

How to get `ListView` item to wrap_content starting from right side of the screen?

I have a ListView that has a custom adapter to provide a customized View. Each list item "changes" the side of the screen it is on (as if you flipped it around a vertical axis). Here's an example of what I'm talking about:
The darker gray boxes in the photo cover up a ProfilePictureView and a TextView containing a users name and photo. No name and photo if the user is not logged in (as you can see in the second list item in the photo). As you can see from the photo, the background image wraps around the content in the view for the first and third item (starting from the left and ending at the right).The problem is: the items facing the other way are ignoring my "wrap_content" call and are "matching" the parent view (as you can see in item two). I believe it is correctly wrapping the content but is there any way to start from the right of the screen and wrap content to the left?
Here's the XML code for that items view:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right|center_vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentRight="true"
android:gravity="right" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.namespace.RobotoTextView
android:id="#+id/list_item_user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="#color/white"
custom:typeface="roboto_light"/>
<com.namespace.RobotoTextView
android:id="#+id/list_item_user_score"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="36sp"
android:textStyle="bold"
android:textColor="#color/waf_warm_yellow_orange"
custom:typeface="roboto_bold"/>
</LinearLayout>
<com.facebook.widget.ProfilePictureView
android:id="#+id/list_item_user_image"
android:layout_width="69dp"
android:layout_height="69dp"
android:layout_margin="10dp" />
</LinearLayout>
So, how can I align the view correctly to the right and have the background image correctly wrap around its content?
Create a separate list item layout for left and right. In your adapter...
#Override
public int getViewTypeCount() {
return 2;
}
#Override
public int getItemViewType(int position) {
return position % 2;
}
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
int layoutRes = viewType == 0 ? R.layout.list_item_left : R.layout.list_item_right;
View row = inflater.inflate(layoutRes);
/* ... */
}
Basically, your adapter reports two different view types and your getView alternates between them. (If there's some other logic to determine left vs. right, implement it in getItemViewType().)
The answer to my problem was quite simple, inside my custom adapter I was setting the background image resource depending on whether it was an even or odd listview item. Instead of doing that I just had to make an imageview and set that image resource to the background image and set it to the correct side of the screen with the android:layout_alignParentRight="true and `android:layout_alignParentLeft="true" attributes.

Categories