Dynamically add items in listview - android

I have an adapter which loads items from the List<> tempList.
At first, the tempList has 10 items. When users scroll to the bottom, 10 more items are added to tempList automatically, by getting items from another List propertyDetailsList.
for (int i = 0; i < 10; i++) {
tempList.add(propertyDetailsList.get(i));
}
propertyDetailsInstantAdapter.notifyDataSetChanged();
However, the result is that only the item at 0 (propertyDetailsList.get(0)) is added to tempList, and it is added 10 times instead....
Whats wrong with my code?
More code:
private ListView propertyList;
private List<PropertyDetails> tempList;
private List<PropertyDetails> propertyDetailsList;
......
propertyDetailsList = getList();
tempList = propertyDetailsList.subList(0, 10);
......
public void showPropertyList() {
propertyList.setAdapter(buildPropertyList());
mIsLoading = false;
propertyList.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (!mIsLoading && mMoreDataAvailable) {
if (totalItemCount - visibleItemCount - AUTOLOAD_THRESHOLD <= firstVisibleItem) {
mIsLoading = true;
for (int i = 0; i < 10; i++) {
tempList.add(propertyDetailsList.get(10 + i));
}
propertyDetailsInstantAdapter.notifyDataSetChanged();
mIsLoading = false;
}
}
}
});
}
public InstantAdapter<PropertyDetails> buildPropertyList() {
propertyDetailsInstantAdapter = new InstantAdapter<PropertyDetails>(
this, R.layout.property_list_item, PropertyDetails.class, tempList) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
PropertyListItem propertyListItem;
Context context = parent.getContext();
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.property_list_item, parent, false);
propertyListItem = new PropertyListItem();
propertyListItem.propertyImage = (ImageView) convertView.findViewById(R.id.propertyListImage);
propertyListItem.propertyAddress = (TextView) convertView.findViewById(R.id.propertyListAddress);
propertyListItem.propertyName = (TextView) convertView.findViewById(R.id.propertyListName);
propertyListItem.propertyDetails = this.getItem(position);
convertView.setTag(propertyListItem);
} else {
propertyListItem = (PropertyListItem) convertView.getTag();
}
final PropertyDetails propertyDetails = this.getItem(position);
Transformation transformation = new Transformation() {
#Override
public Bitmap transform(Bitmap source) {
int targetWidth = sp.getInt("deviceWidth", 0);
double aspectRatio = (double) source.getHeight() / (double) source.getWidth();
int targetHeight = (int) (targetWidth * aspectRatio);
Bitmap result = Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
if (result != source) {
// Same bitmap is returned if sizes are the same
source.recycle();
}
return result;
}
#Override
public String key() {
return "transformation" + " desiredWidth";
}
};
if (propertyDetails.getImg_link() != null) {
Picasso.with(context)
.load(Uri.parse(propertyDetails.getImg_link()))
.transform(transformation)
.into(propertyListItem.propertyImage);
}
propertyListItem.propertyAddress.setText(propertyDetails.getPropertyAddress());
propertyListItem.propertyName.setText(propertyDetails.getPropertyName());
return convertView;
}
};
return propertyDetailsInstantAdapter;
}

Related

Scroll a ImageView on scroll of the RecyclerView

My requirement is scrolling a ImageView left and right on top of a list of data in the Recyclerview. When Recyclerview is scrolled up the ImageView will move towards right until list reaches to the end and vice versa.
I have tried but facing few complexity any suggestions and reference will be very helpful.Or any logic will also be appreciated.
The problem what I facing now is that not able to handle the values in the addOnScrollListener
Sharing my code in the github: Github Link
MainActivity Code:
Sharing few lines of code:
public class MainActivity extends AppCompatActivity implements View.OnClickListener, ClickEventLisener {
HorizontalScrollView v_scroll;
Button btn_left, btn_right;
int pos = 0;
int temppos = 0;
int initialpos = 0;
RecyclerView rv_recycler;
UserApapter adapter;
List<Users> user = new ArrayList<>();
Context mContext;
boolean isFirsttime = true;
ImageView iv_image;
String imageurl = "https://www.isometrix.com/wp-content/uploads/2017/03/featured-images-about.jpg";
int screenwidth = 0, imagewidth = 0;
int scroolby_val = 0;
#SuppressLint("ClickableViewAccessibility")
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
iv_image = findViewById(R.id.iv_image);
v_scroll = findViewById(R.id.v_scroll);
btn_left = findViewById(R.id.btn_left);
btn_right = findViewById(R.id.btn_right);
rv_recycler = findViewById(R.id.rv_recycler);
btn_left.setOnClickListener(this);
btn_right.setOnClickListener(this);
v_scroll.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
filllist();
getScreenSize();
setupimage();
getleftscroll();
// when scrolled to the leftmost position the variables are initialized
v_scroll.setOnScrollChangeListener(new View.OnScrollChangeListener() {
#Override
public void onScrollChange(View view, int i, int i1, int i2, int i3) {
initialpos = i;
if (i == 0) {
temppos = 0;
} else {
}
}
});
///not able to understand how to handle the values
//handling the scroll
rv_recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
getleftscroll();
if (dy > 0) {
temppos = temppos + scroolby_val;
v_scroll.scrollTo(temppos, 0);
Log.d("Scroll", "ScrollUp");
Log.d("temppos", "" + temppos);
} else {
if (initialpos != 0) {
temppos = temppos - scroolby_val;
v_scroll.scrollTo(temppos, 0);
Log.d("temppos1", "" + temppos);
Log.d("Scroll", "ScrollDown");
}
}
}
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
// Do something
} else if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
// Do something
} else {
// Do something
}
}
});
}
private void getScreenSize() {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int height = displayMetrics.heightPixels;
int width = displayMetrics.widthPixels;
Log.d("ScreenWidth", "" + width);
screenwidth = width;
}
private void setupimage() {
Glide.with(mContext)
.asBitmap()
.load(imageurl)
.into(new SimpleTarget<Bitmap>() {
#Override
public void onResourceReady(Bitmap bitmap, Transition<? super Bitmap> transition) {
int w = bitmap.getWidth();
int h = bitmap.getHeight();
Log.d("ImageWitdh", "" + w);
iv_image.setImageBitmap(bitmap);
imagewidth = w;
}
});
}
/*
Logic I have implemented:calculated Imagewidth and screenwidth. Then minus it (imagewidth > screenwidth) and then divide it by the number of values in the array.
if the value is 0 then scrolling it by 1 per scroll or if the returned value is 3 then scrolling it by 3.
IOS team have done this way and working good for them but I am facing a minor issue here.
*/
private void getleftscroll() {
imagewidth = 2000;
if (imagewidth > screenwidth) {
int leftoutscreen = imagewidth - screenwidth;
scroolby_val = leftoutscreen / user.size();
if (scroolby_val == 0) {
scroolby_val = 1;
}
// temppos = 0;
Log.d("scroolby_val", "" + scroolby_val);
}
}
///button is just for demo purpose///
#Override
public void onClick(View v) {
if (v == btn_left) {
if (initialpos != 0) {
temppos = temppos - pos--;
v_scroll.scrollTo(temppos, 0);
Log.d("temppos", "" + temppos);
}
} else if (v == btn_right) {
temppos = temppos + pos++;
v_scroll.scrollTo(temppos, -temppos);
Log.d("temppos", "" + temppos);
}
}
private void filllist() {
user.clear();
for (int i = 0; i <= 300; i++) {
user.add(new Users(String.valueOf(i + 1), "name " + i));
}
inflateadapter();
}
private void inflateadapter() {
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
adapter = new UserApapter(this, R.layout.row_users, user, this);
rv_recycler.setLayoutManager(mLayoutManager);
rv_recycler.setAdapter(adapter);
}
#Override
public void Currentposition(int position) {
Log.d("Currentposition", "" + position);
if (position == user.size() - 1) {
if (scroolby_val == 1) {
Log.d("scroolby_val", "" + scroolby_val);
Log.d("Inside", "Inside");
// v_scroll.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
// temppos = 1;
}
} else if (position == 0) {
temppos = 0;
}
pos = position;
}
#Override
public void ClickEventLisener(View view, int position) {
Toast.makeText(mContext, "" + position, Toast.LENGTH_SHORT).show();
}
}
Few things you may want to consider-
Don't use dy values from onScrolled callback directly to set scroll of v_scroll. There should be a logic to map scroll state of recycler view to the required scroll in v_scroll.
Don't use dy at all. Logic to set scroll of v_scroll should be based on the number of items in the list and the first/last visible child in it. (RecyclerView provides methods to get that.) You can run that logic from onScrolled callback.

How to design spannable gridview using recyclerview (SpannableGridLayoutManager)

I want to design grid view like below image provided. The first item should be bigger than the rest.
Currently I am using RelativeLayout with GridLayoutManager check below code
RecyclerView recyclerView = (RecyclerView)
findViewById(R.id.recycler_view1);
RecyclerView.LayoutManager recyclerViewLayoutManager = new
GridLayoutManager(context, 3);
recyclerView.setLayoutManager(recyclerViewLayoutManager);
recyclerView_Adapter = new RecyclerViewAdapter(context,numbers);
recyclerView.setAdapter(recyclerView_Adapter);
Dummy array for demo
String[] numbers = {
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"ten",
"eleven",
};
Adapter Class
public class RecyclerViewAdapter extends
RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder>{
String[] values;
Context context1;
public RecyclerViewAdapter(Context context2,String[] values2){
values = values2;
context1 = context2;
}
public static class ViewHolder extends RecyclerView.ViewHolder{
public TextView textView;
public ViewHolder(View v){
super(v);
textView = (TextView) v.findViewById(R.id.textview1);
}
}
#Override
public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType){
View view1 = LayoutInflater.from(context1).inflate(R.layout.recycler_view_items,parent,false);
ViewHolder viewHolder1 = new ViewHolder(view1);
return viewHolder1;
}
#Override
public void onBindViewHolder(ViewHolder Vholder, int position){
Vholder.textView.setText(values[position]);
Vholder.textView.setBackgroundColor(Color.CYAN);
Vholder.textView.setTextColor(Color.BLUE);
}
#Override
public int getItemCount(){
return values.length;
} }
I have implemented the SpannableGridLayoutManager for this and its working perfectly for me. Please check the following solution.
Activity Code
SpannableGridLayoutManager gridLayoutManager = new
SpannableGridLayoutManager(new SpannableGridLayoutManager.GridSpanLookup() {
#Override
public SpannableGridLayoutManager.SpanInfo getSpanInfo(int position)
{
if (position == 0) {
return new SpannableGridLayoutManager.SpanInfo(2, 2);
//this will count of row and column you want to replace
} else {
return new SpannableGridLayoutManager.SpanInfo(1, 1);
}
}
}, 3, 1f); // 3 is the number of coloumn , how nay to display is 1f
recyclerView.setLayoutManager(gridLayoutManager);
In adapter write following Code
public MyViewHolder(View itemView) {
super(itemView);
GridLayoutManager.LayoutParams layoutParams = new
GridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
float margin = DimensionUtils.convertDpToPixel(5);
layoutParams.setMargins((int) margin, (int) margin, (int) margin,
(int) margin);
itemView.setLayoutParams(layoutParams);
}
SpannableGridLayoutManager custom class
public class SpannableGridLayoutManager extends RecyclerView.LayoutManager {
private GridSpanLookup spanLookup;
private int columns = 1;
private float cellAspectRatio = 1f;
private int cellHeight;
private int[] cellBorders;
private int firstVisiblePosition;
private int lastVisiblePosition;
private int firstVisibleRow;
private int lastVisibleRow;
private boolean forceClearOffsets;
private SparseArray<GridCell> cells;
private List<Integer> firstChildPositionForRow; // key == row, val == first child position
private int totalRows;
private final Rect itemDecorationInsets = new Rect();
public SpannableGridLayoutManager(GridSpanLookup spanLookup, int columns, float cellAspectRatio) {
this.spanLookup = spanLookup;
this.columns = columns;
this.cellAspectRatio = cellAspectRatio;
setAutoMeasureEnabled(true);
}
#Keep /* XML constructor, see RecyclerView#createLayoutManager */
public SpannableGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SpannableGridLayoutManager, defStyleAttr, defStyleRes);
columns = a.getInt(R.styleable.SpannableGridLayoutManager_android_orientation, 1);
parseAspectRatio(a.getString(R.styleable.SpannableGridLayoutManager_aspectRatio));
int orientation = a.getInt(R.styleable.SpannableGridLayoutManager_android_orientation, RecyclerView.VERTICAL);
a.recycle();
setAutoMeasureEnabled(true);
}
public interface GridSpanLookup {
SpanInfo getSpanInfo(int position);
}
public void setSpanLookup(#NonNull GridSpanLookup spanLookup) {
this.spanLookup = spanLookup;
}
public static class SpanInfo {
public int columnSpan;
public int rowSpan;
public SpanInfo(int columnSpan, int rowSpan) {
this.columnSpan = columnSpan;
this.rowSpan = rowSpan;
}
public static final SpanInfo SINGLE_CELL = new SpanInfo(1, 1);
}
public static class LayoutParams extends RecyclerView.LayoutParams {
int columnSpan;
int rowSpan;
public LayoutParams(Context c, AttributeSet attrs) {
super(c, attrs);
}
public LayoutParams(int width, int height) {
super(width, height);
}
public LayoutParams(ViewGroup.MarginLayoutParams source) {
super(source);
}
public LayoutParams(ViewGroup.LayoutParams source) {
super(source);
}
public LayoutParams(RecyclerView.LayoutParams source) {
super(source);
}
}
#Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
calculateWindowSize();
calculateCellPositions(recycler, state);
if (state.getItemCount() == 0) {
detachAndScrapAttachedViews(recycler);
firstVisibleRow = 0;
resetVisibleItemTracking();
return;
}
// TODO use orientationHelper
int startTop = getPaddingTop();
int scrollOffset = 0;
if (forceClearOffsets) { // see #scrollToPosition
startTop = -(firstVisibleRow * cellHeight);
forceClearOffsets = false;
} else if (getChildCount() != 0) {
scrollOffset = getDecoratedTop(getChildAt(0));
startTop = scrollOffset - (firstVisibleRow * cellHeight);
resetVisibleItemTracking();
}
detachAndScrapAttachedViews(recycler);
int row = firstVisibleRow;
int availableSpace = getHeight() - scrollOffset;
int lastItemPosition = state.getItemCount() - 1;
while (availableSpace > 0 && lastVisiblePosition < lastItemPosition) {
availableSpace -= layoutRow(row, startTop, recycler, state);
row = getNextSpannedRow(row);
}
layoutDisappearingViews(recycler, state, startTop);
}
#Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
#Override
public RecyclerView.LayoutParams generateLayoutParams(Context c, AttributeSet attrs) {
return new LayoutParams(c, attrs);
}
#Override
public RecyclerView.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
if (lp instanceof ViewGroup.MarginLayoutParams) {
return new LayoutParams((ViewGroup.MarginLayoutParams) lp);
} else {
return new LayoutParams(lp);
}
}
#Override
public boolean checkLayoutParams(RecyclerView.LayoutParams lp) {
return lp instanceof LayoutParams;
}
#Override
public void onAdapterChanged(RecyclerView.Adapter oldAdapter, RecyclerView.Adapter newAdapter) {
removeAllViews();
reset();
}
#Override
public boolean supportsPredictiveItemAnimations() {
return true;
}
#Override
public boolean canScrollVertically() {
return true;
}
#Override
public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, RecyclerView.State state) {
if (getChildCount() == 0 || dy == 0) return 0;
int scrolled;
int top = getDecoratedTop(getChildAt(0));
if (dy < 0) { // scrolling content down
if (firstVisibleRow == 0) { // at top of content
int scrollRange = -(getPaddingTop() - top);
scrolled = Math.max(dy, scrollRange);
} else {
scrolled = dy;
}
if (top - scrolled >= 0) { // new top row came on screen
int newRow = firstVisibleRow - 1;
if (newRow >= 0) {
int startOffset = top - (firstVisibleRow * cellHeight);
layoutRow(newRow, startOffset, recycler, state);
}
}
int firstPositionOfLastRow = getFirstPositionInSpannedRow(lastVisibleRow);
int lastRowTop = getDecoratedTop(
getChildAt(firstPositionOfLastRow - firstVisiblePosition));
if (lastRowTop - scrolled > getHeight()) { // last spanned row scrolled out
recycleRow(lastVisibleRow, recycler, state);
}
} else { // scrolling content up
int bottom = getDecoratedBottom(getChildAt(getChildCount() - 1));
if (lastVisiblePosition == getItemCount() - 1) { // is at end of content
int scrollRange = Math.max(bottom - getHeight() + getPaddingBottom(), 0);
scrolled = Math.min(dy, scrollRange);
} else {
scrolled = dy;
}
if ((bottom - scrolled) < getHeight()) { // new row scrolled in
int nextRow = lastVisibleRow + 1;
if (nextRow < getSpannedRowCount()) {
int startOffset = top - (firstVisibleRow * cellHeight);
layoutRow(nextRow, startOffset, recycler, state);
}
}
int lastPositionInRow = getLastPositionInSpannedRow(firstVisibleRow, state);
int bottomOfFirstRow =
getDecoratedBottom(getChildAt(lastPositionInRow - firstVisiblePosition));
if (bottomOfFirstRow - scrolled < 0) { // first spanned row scrolled out
recycleRow(firstVisibleRow, recycler, state);
}
}
offsetChildrenVertical(-scrolled);
return scrolled;
}
#Override
public void scrollToPosition(int position) {
if (position >= getItemCount()) position = getItemCount() - 1;
firstVisibleRow = getRowIndex(position);
resetVisibleItemTracking();
forceClearOffsets = true;
removeAllViews();
requestLayout();
}
#Override
public void smoothScrollToPosition(
RecyclerView recyclerView, RecyclerView.State state, int position) {
if (position >= getItemCount()) position = getItemCount() - 1;
LinearSmoothScroller scroller = new LinearSmoothScroller(recyclerView.getContext()) {
#Override
public PointF computeScrollVectorForPosition(int targetPosition) {
final int rowOffset = getRowIndex(targetPosition) - firstVisibleRow;
return new PointF(0, rowOffset * cellHeight);
}
};
scroller.setTargetPosition(position);
startSmoothScroll(scroller);
}
#Override
public int computeVerticalScrollRange(RecyclerView.State state) {
// TODO update this to incrementally calculate
return getSpannedRowCount() * cellHeight + getPaddingTop() + getPaddingBottom();
}
#Override
public int computeVerticalScrollExtent(RecyclerView.State state) {
return getHeight();
}
#Override
public int computeVerticalScrollOffset(RecyclerView.State state) {
if (getChildCount() == 0) return 0;
return getPaddingTop() + (firstVisibleRow * cellHeight) - getDecoratedTop(getChildAt(0));
}
#Override
public View findViewByPosition(int position) {
if (position < firstVisiblePosition || position > lastVisiblePosition) return null;
return getChildAt(position - firstVisiblePosition);
}
public int getFirstVisibleItemPosition() {
return firstVisiblePosition;
}
private static class GridCell {
final int row;
final int rowSpan;
final int column;
final int columnSpan;
GridCell(int row, int rowSpan, int column, int columnSpan) {
this.row = row;
this.rowSpan = rowSpan;
this.column = column;
this.columnSpan = columnSpan;
}
}
/**
* This is the main layout algorithm, iterates over all items and places them into [column, row]
* cell positions. Stores this layout info for use later on. Also records the adapter position
* that each row starts at.
* <p>
* Note that if a row is spanned, then the row start position is recorded as the first cell of
* the row that the spanned cell starts in. This is to ensure that we have sufficient contiguous
* views to layout/draw a spanned row.
*/
private void calculateCellPositions(RecyclerView.Recycler recycler, RecyclerView.State state) {
final int itemCount = state.getItemCount();
cells = new SparseArray<>(itemCount);
firstChildPositionForRow = new ArrayList<>();
int row = 0;
int column = 0;
recordSpannedRowStartPosition(row, column);
int[] rowHWM = new int[columns]; // row high water mark (per column)
for (int position = 0; position < itemCount; position++) {
SpanInfo spanInfo;
int adapterPosition = recycler.convertPreLayoutPositionToPostLayout(position);
if (adapterPosition != RecyclerView.NO_POSITION) {
spanInfo = spanLookup.getSpanInfo(adapterPosition);
} else {
// item removed from adapter, retrieve its previous span info
// as we can't get from the lookup (adapter)
spanInfo = getSpanInfoFromAttachedView(position);
}
if (spanInfo.columnSpan > columns) {
spanInfo.columnSpan = columns; // or should we throw?
}
// check horizontal space at current position else start a new row
// note that this may leave gaps in the grid; we don't backtrack to try and fit
// subsequent cells into gaps. We place the responsibility on the adapter to provide
// continuous data i.e. that would not span column boundaries to avoid gaps.
if (column + spanInfo.columnSpan > columns) {
row++;
recordSpannedRowStartPosition(row, position);
column = 0;
}
// check if this cell is already filled (by previous spanning cell)
while (rowHWM[column] > row) {
column++;
if (column + spanInfo.columnSpan > columns) {
row++;
recordSpannedRowStartPosition(row, position);
column = 0;
}
}
// by this point, cell should fit at [column, row]
cells.put(position, new GridCell(row, spanInfo.rowSpan, column, spanInfo.columnSpan));
// update the high water mark book-keeping
for (int columnsSpanned = 0; columnsSpanned < spanInfo.columnSpan; columnsSpanned++) {
rowHWM[column + columnsSpanned] = row + spanInfo.rowSpan;
}
// if we're spanning rows then record the 'first child position' as the first item
// *in the row the spanned item starts*. i.e. the position might not actually sit
// within the row but it is the earliest position we need to render in order to fill
// the requested row.
if (spanInfo.rowSpan > 1) {
int rowStartPosition = getFirstPositionInSpannedRow(row);
for (int rowsSpanned = 1; rowsSpanned < spanInfo.rowSpan; rowsSpanned++) {
int spannedRow = row + rowsSpanned;
recordSpannedRowStartPosition(spannedRow, rowStartPosition);
}
}
// increment the current position
column += spanInfo.columnSpan;
}
totalRows = rowHWM[0];
for (int i = 1; i < rowHWM.length; i++) {
if (rowHWM[i] > totalRows) {
totalRows = rowHWM[i];
}
}
}
private SpanInfo getSpanInfoFromAttachedView(int position) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (position == getPosition(child)) {
LayoutParams lp = (LayoutParams) child.getLayoutParams();
return new SpanInfo(lp.columnSpan, lp.rowSpan);
}
}
// errrrr?
return SpanInfo.SINGLE_CELL;
}
private void recordSpannedRowStartPosition(final int rowIndex, final int position) {
if (getSpannedRowCount() < (rowIndex + 1)) {
firstChildPositionForRow.add(position);
}
}
private int getRowIndex(final int position) {
return position < cells.size() ? cells.get(position).row : -1;
}
private int getSpannedRowCount() {
return firstChildPositionForRow.size();
}
private int getNextSpannedRow(int rowIndex) {
int firstPositionInRow = getFirstPositionInSpannedRow(rowIndex);
int nextRow = rowIndex + 1;
while (nextRow < getSpannedRowCount()
&& getFirstPositionInSpannedRow(nextRow) == firstPositionInRow) {
nextRow++;
}
return nextRow;
}
private int getFirstPositionInSpannedRow(int rowIndex) {
return firstChildPositionForRow.get(rowIndex);
}
private int getLastPositionInSpannedRow(final int rowIndex, RecyclerView.State state) {
int nextRow = getNextSpannedRow(rowIndex);
return (nextRow != getSpannedRowCount()) ? // check if reached boundary
getFirstPositionInSpannedRow(nextRow) - 1
: state.getItemCount() - 1;
}
/**
* Lay out a given 'row'. We might actually add more that one row if the requested row contains
* a row-spanning cell. Returns the pixel height of the rows laid out.
* <p>
* To simplify logic & book-keeping, views are attached in adapter order, that is child 0 will
* always be the earliest position displayed etc.
*/
private int layoutRow(
int rowIndex, int startTop, RecyclerView.Recycler recycler, RecyclerView.State state) {
int firstPositionInRow = getFirstPositionInSpannedRow(rowIndex);
int lastPositionInRow = getLastPositionInSpannedRow(rowIndex, state);
boolean containsRemovedItems = false;
int insertPosition = (rowIndex < firstVisibleRow) ? 0 : getChildCount();
for (int position = firstPositionInRow;
position <= lastPositionInRow;
position++, insertPosition++) {
View view = recycler.getViewForPosition(position);
LayoutParams lp = (LayoutParams) view.getLayoutParams();
containsRemovedItems |= lp.isItemRemoved();
GridCell cell = cells.get(position);
addView(view, insertPosition);
// TODO use orientation helper
int wSpec = getChildMeasureSpec(
cellBorders[cell.column + cell.columnSpan] - cellBorders[cell.column],
View.MeasureSpec.EXACTLY, 0, lp.width, false);
int hSpec = getChildMeasureSpec(cell.rowSpan * cellHeight,
View.MeasureSpec.EXACTLY, 0, lp.height, true);
measureChildWithDecorationsAndMargin(view, wSpec, hSpec);
int left = cellBorders[cell.column] + lp.leftMargin;
int top = startTop + (cell.row * cellHeight) + lp.topMargin;
int right = left + getDecoratedMeasuredWidth(view);
int bottom = top + getDecoratedMeasuredHeight(view);
layoutDecorated(view, left, top, right, bottom);
lp.columnSpan = cell.columnSpan;
lp.rowSpan = cell.rowSpan;
}
if (firstPositionInRow < firstVisiblePosition) {
firstVisiblePosition = firstPositionInRow;
firstVisibleRow = getRowIndex(firstVisiblePosition);
}
if (lastPositionInRow > lastVisiblePosition) {
lastVisiblePosition = lastPositionInRow;
lastVisibleRow = getRowIndex(lastVisiblePosition);
}
if (containsRemovedItems) return 0; // don't consume space for rows with disappearing items
GridCell first = cells.get(firstPositionInRow);
GridCell last = cells.get(lastPositionInRow);
return (last.row + last.rowSpan - first.row) * cellHeight;
}
/**
* Remove and recycle all items in this 'row'. If the row includes a row-spanning cell then all
* cells in the spanned rows will be removed.
*/
private void recycleRow(
int rowIndex, RecyclerView.Recycler recycler, RecyclerView.State state) {
int firstPositionInRow = getFirstPositionInSpannedRow(rowIndex);
int lastPositionInRow = getLastPositionInSpannedRow(rowIndex, state);
int toRemove = lastPositionInRow;
while (toRemove >= firstPositionInRow) {
int index = toRemove - firstVisiblePosition;
removeAndRecycleViewAt(index, recycler);
toRemove--;
}
if (rowIndex == firstVisibleRow) {
firstVisiblePosition = lastPositionInRow + 1;
firstVisibleRow = getRowIndex(firstVisiblePosition);
}
if (rowIndex == lastVisibleRow) {
lastVisiblePosition = firstPositionInRow - 1;
lastVisibleRow = getRowIndex(lastVisiblePosition);
}
}
private void layoutDisappearingViews(
RecyclerView.Recycler recycler, RecyclerView.State state, int startTop) {
// TODO
}
private void calculateWindowSize() {
// TODO use OrientationHelper#getTotalSpace
int cellWidth =
(int) Math.floor((getWidth() - getPaddingLeft() - getPaddingRight()) / columns);
cellHeight = (int) Math.floor(cellWidth * (1f / cellAspectRatio));
calculateCellBorders();
}
private void reset() {
cells = null;
firstChildPositionForRow = null;
firstVisiblePosition = 0;
firstVisibleRow = 0;
lastVisiblePosition = 0;
lastVisibleRow = 0;
cellHeight = 0;
forceClearOffsets = false;
}
private void resetVisibleItemTracking() {
// maintain the firstVisibleRow but reset other state vars
// TODO make orientation agnostic
int minimumVisibleRow = getMinimumFirstVisibleRow();
if (firstVisibleRow > minimumVisibleRow) firstVisibleRow = minimumVisibleRow;
firstVisiblePosition = getFirstPositionInSpannedRow(firstVisibleRow);
lastVisibleRow = firstVisibleRow;
lastVisiblePosition = firstVisiblePosition;
}
private int getMinimumFirstVisibleRow() {
int maxDisplayedRows = (int) Math.ceil((float) getHeight() / cellHeight) + 1;
if (totalRows < maxDisplayedRows) return 0;
int minFirstRow = totalRows - maxDisplayedRows;
// adjust to spanned rows
return getRowIndex(getFirstPositionInSpannedRow(minFirstRow));
}
/* Adapted from GridLayoutManager */
private void calculateCellBorders() {
cellBorders = new int[columns + 1];
int totalSpace = getWidth() - getPaddingLeft() - getPaddingRight();
int consumedPixels = getPaddingLeft();
cellBorders[0] = consumedPixels;
int sizePerSpan = totalSpace / columns;
int sizePerSpanRemainder = totalSpace % columns;
int additionalSize = 0;
for (int i = 1; i <= columns; i++) {
int itemSize = sizePerSpan;
additionalSize += sizePerSpanRemainder;
if (additionalSize > 0 && (columns - additionalSize) < sizePerSpanRemainder) {
itemSize += 1;
additionalSize -= columns;
}
consumedPixels += itemSize;
cellBorders[i] = consumedPixels;
}
}
private void measureChildWithDecorationsAndMargin(View child, int widthSpec, int heightSpec) {
calculateItemDecorationsForChild(child, itemDecorationInsets);
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams();
widthSpec = updateSpecWithExtra(widthSpec, lp.leftMargin + itemDecorationInsets.left,
lp.rightMargin + itemDecorationInsets.right);
heightSpec = updateSpecWithExtra(heightSpec, lp.topMargin + itemDecorationInsets.top,
lp.bottomMargin + itemDecorationInsets.bottom);
child.measure(widthSpec, heightSpec);
}
private int updateSpecWithExtra(int spec, int startInset, int endInset) {
if (startInset == 0 && endInset == 0) {
return spec;
}
int mode = View.MeasureSpec.getMode(spec);
if (mode == View.MeasureSpec.AT_MOST || mode == View.MeasureSpec.EXACTLY) {
return View.MeasureSpec.makeMeasureSpec(
View.MeasureSpec.getSize(spec) - startInset - endInset, mode);
}
return spec;
}
/* Adapted from ConstraintLayout */
private void parseAspectRatio(String aspect) {
if (aspect != null) {
int colonIndex = aspect.indexOf(':');
if (colonIndex >= 0 && colonIndex < aspect.length() - 1) {
String nominator = aspect.substring(0, colonIndex);
String denominator = aspect.substring(colonIndex + 1);
if (nominator.length() > 0 && denominator.length() > 0) {
try {
float nominatorValue = Float.parseFloat(nominator);
float denominatorValue = Float.parseFloat(denominator);
if (nominatorValue > 0 && denominatorValue > 0) {
cellAspectRatio = Math.abs(nominatorValue / denominatorValue);
return;
}
} catch (NumberFormatException e) {
// Ignore
}
}
}
}
throw new IllegalArgumentException("Could not parse aspect ratio: '" + aspect + "'");
}}
add following code to attr file
<declare-styleable name="SpannableGridLayoutManager">
<attr name="android:orientation" />
<attr name="spanCount" />
<attr name="aspectRatio" format="string" />
</declare-styleable>

Not working Notifydatasetchange on RecyclerView with center selection Horizontal Scrollview?

Auto Scrolling is issue & also move to some specific position using code is difficult.
I am making two recyclerView dependent to each other with the Horizontal Scroll and center selection.
So my problem is using the method of Notifydatasetchanged and reseting recyclerView postion to 0 and it's scrolling selection range because it's returning wrong index...
When i want to get center selection index after changing data.
I am using below example to achieve this with some edits.
Get center visible item of RecycleView when scrolling
I need to change the data on scroll of First recyclerView Adapter to second recyclerView Adapter with data change.
But scrollview set the position in first position
I tried the notifyItemRangeChanged(int, int)
notifyItemRangeInserted(int, int) methods...
Detail Explanation : I am changing the type and reset the value of Look scrollview. I need to change the selected position of bottom scrollview. Specially I can't get the center position by changing data. Means I if i am notifying the adapter than index will remain as it is. I need to do work it like normal adapter after reset data.
Thanks in advance.
public void getRecyclerview_Type() {
final RecyclerView recyclerView_Type = (RecyclerView) findViewById(R.id.recycleView);
if (recyclerView_Type != null) {
recyclerView_Type.postDelayed(new Runnable() {
#Override
public void run() {
setTypeValue();
}
}, 300);
recyclerView_Type.postDelayed(new Runnable() {
#Override
public void run() {
// recyclerView_Type.smoothScrollToPosition(Type_Adapter.getItemCount() - 1);
setTypeValue();
}
}, 5000);
}
ViewTreeObserver treeObserver = recyclerView_Type.getViewTreeObserver();
treeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
recyclerView_Type.getViewTreeObserver().removeOnPreDrawListener(this);
finalWidthDate = recyclerView_Type.getMeasuredWidth();
itemWidthDate = getResources().getDimension(R.dimen.item_dob_width_padding);
paddingDate = (finalWidthDate - itemWidthDate) / 2;
firstItemWidthDate = paddingDate;
allPixelsDate = 0;
final LinearLayoutManager dateLayoutManager = new LinearLayoutManager(getApplicationContext());
dateLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView_Type.setLayoutManager(dateLayoutManager);
recyclerView_Type.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
synchronized (this) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
calculatePositionAndScroll_Type(recyclerView);
}
}
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
allPixelsDate += dx;
}
});
if (mTypeBeanArrayList == null) {
mTypeBeanArrayList = new ArrayList<>();
}
getMedicationType();
Type_Adapter = new Medication_Type_RecyclerAdapter(Add_Reminder_medicationlook_Activity.this, mTypeBeanArrayList, (int) firstItemWidthDate);
recyclerView_Type.setAdapter(Type_Adapter);
Type_Adapter.setSelecteditem(Type_Adapter.getItemCount() - 1);
return true;
}
});
}
private void getMedicationType() {
for (int i = 0; i < mTypeBeanArrayList.size(); i++) {
Medication_TypeBean medication_typeBean = mTypeBeanArrayList.get(i);
Log.print("Image name :" +medication_typeBean.getType_image_name());
if (i == 0 || i == (mTypeBeanArrayList.size() - 1)) {
medication_typeBean.setType(VIEW_TYPE_PADDING);
} else {
medication_typeBean.setType(VIEW_TYPE_ITEM);
}
mTypeBeanArrayList.set(i, medication_typeBean);
}
}
/* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/
private void calculatePositionAndScroll_Type(RecyclerView recyclerView) {
int expectedPositionDate = Math.round((allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate);
if (expectedPositionDate == -1) {
expectedPositionDate = 0;
} else if (expectedPositionDate >= recyclerView.getAdapter().getItemCount() - 2) {
expectedPositionDate--;
}
scrollListToPosition_Type(recyclerView, expectedPositionDate);
}
/* this if most important, if expectedPositionDate < 0 recyclerView will return to nearest item*/
private void scrollListToPosition_Type(RecyclerView recyclerView, int expectedPositionDate) {
float targetScrollPosDate = expectedPositionDate * itemWidthDate + firstItemWidthDate - paddingDate;
float missingPxDate = targetScrollPosDate - allPixelsDate;
if (missingPxDate != 0) {
recyclerView.smoothScrollBy((int) missingPxDate, 0);
}
setTypeValue();
}
private void setTypeValue() {
int expectedPositionDateColor = Math.round((allPixelsDate + paddingDate - firstItemWidthDate) / itemWidthDate);
int setColorDate = expectedPositionDateColor + 1;
Type_Adapter.setSelecteditem(setColorDate);
mTxt_type_name.setText(mTypeBeanArrayList.get(setColorDate).getMedication_type_name());
mSELECTED_TYPE_ID = setColorDate;
//NotifyLookChangetoType(setColorDate);
}
//Type Adapter
public class Medication_Type_RecyclerAdapter extends RecyclerView.Adapter<Medication_Type_RecyclerAdapter.ViewHolder> {
private ArrayList<Medication_TypeBean> medication_typeBeanArrayList;
private static final int VIEW_TYPE_PADDING = 1;
private static final int VIEW_TYPE_ITEM = 2;
private int paddingWidthDate = 0;
private Context mContext;
private int selectedItem = -1;
public Medication_Type_RecyclerAdapter(Context context, ArrayList<Medication_TypeBean> dateData, int paddingWidthDate) {
this.medication_typeBeanArrayList = dateData;
this.paddingWidthDate = paddingWidthDate;
this.mContext = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_ITEM) {
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_medication_type,
parent, false);
return new ViewHolder(view);
} else {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_medication_type,
parent, false);
RecyclerView.LayoutParams layoutParams = (RecyclerView.LayoutParams) view.getLayoutParams();
layoutParams.width = paddingWidthDate;
view.setLayoutParams(layoutParams);
return new ViewHolder(view);
}
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Medication_TypeBean medication_typeBean = mTypeBeanArrayList.get(position);
if (getItemViewType(position) == VIEW_TYPE_ITEM) {
// holder.mTxt_Type.setText(medication_typeBean.getMedication_type_name());
//holder.mTxt_Type.setVisibility(View.VISIBLE);
holder.mImg_medication.setVisibility(View.VISIBLE);
int d = R.drawable.ic_type_pill;
try {
//Due to Offline requirements we do code like this get the images from our res folder
if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_pill")) {
d = R.drawable.ic_type_pill;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_patch")) {
d = R.drawable.ic_type_patch;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_capsule")) {
d = R.drawable.ic_type_capsule;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_ring")) {
d = R.drawable.ic_type_ring;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_inhaler")) {
d = R.drawable.ic_type_inhaler;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_spray")) {
d = R.drawable.ic_type_spray;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_bottle")) {
d = R.drawable.ic_type_bottle;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_drop")) {
d = R.drawable.ic_type_drop;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_pessaries")) {
d = R.drawable.ic_type_pessaries;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_sachets")) {
d = R.drawable.ic_type_sachets;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_tube")) {
d = R.drawable.ic_type_tube;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_suppository")) {
d = R.drawable.ic_type_suppository;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_injaction")) {
d = R.drawable.ic_type_injaction;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_spoon")) {
d = R.drawable.ic_type_spoon;
} else if (medication_typeBean.getType_image_name().equalsIgnoreCase("ic_type_powder")) {
d = R.drawable.ic_type_powder;
} else {
d = R.drawable.ic_type_pill;
}
Bitmap icon = BitmapFactory.decodeResource(mContext.getResources(),
d);
holder.mImg_medication.setImageBitmap(icon);
} catch (Exception e) {
Log.print(e);
}
// BitmapDrawable ob = new BitmapDrawable(mContext.getResources(), icon);
// img.setBackgroundDrawable(ob);
// holder.mImg_medication.setBackground(ob);
// Log.print("Type Adapter", "default " + position + ", selected " + selectedItem);
if (position == selectedItem) {
Log.print("Type adapter", "center" + position);
// holder.mTxt_Type.setTextColor(Color.parseColor("#76FF03"));
//holder.mImg_medication.setColorFilter(Color.GREEN);
// holder.mTxt_Type.setTextSize(35);
holder.mImg_medication.getLayoutParams().height = (int) mContext.getResources().getDimension(R.dimen.item_dob_width) + 10;
holder.mImg_medication.getLayoutParams().width = (int) mContext.getResources().getDimension(R.dimen.item_dob_width) + 10;
} else {
holder.mImg_medication.getLayoutParams().height = (int) mContext.getResources().getDimension(R.dimen.item_dob_width) - 10;
holder.mImg_medication.getLayoutParams().width = (int) mContext.getResources().getDimension(R.dimen.item_dob_width) - 10;
// holder.mTxt_Type.setTextColor(Color.WHITE);
//holder.mImg_medication.setColorFilter(null);
// holder.mTxt_Type.setVisibility(View.INVISIBLE);
// holder.mTxt_Type.setTextSize(18);
// holder.mImg_medication.getLayoutParams().height = 70;
// holder.mImg_medication.getLayoutParams().width = 70;
}
} else {
holder.mImg_medication.getLayoutParams().height = (int) mContext.getResources().getDimension(R.dimen.item_dob_width) - 10;
holder.mImg_medication.getLayoutParams().width = (int) mContext.getResources().getDimension(R.dimen.item_dob_width) - 10;
// holder.mTxt_Type.setVisibility(View.INVISIBLE);
holder.mImg_medication.setVisibility(View.INVISIBLE);
}
}
public void setSelecteditem(int selecteditem) {
this.selectedItem = selecteditem;
notifyDataSetChanged();
if (medication_lookBeanArrayList != null && Look_Adapter != null) {
NotifyLookChangetoType(selecteditem);
}
}
public int getSelecteditem() {
return selectedItem;
}
#Override
public int getItemCount() {
return medication_typeBeanArrayList.size();
}
#Override
public int getItemViewType(int position) {
Medication_TypeBean medication_typeBean = medication_typeBeanArrayList.get(position);
if (medication_typeBean.getType() == VIEW_TYPE_PADDING) {
return VIEW_TYPE_PADDING;
} else {
return VIEW_TYPE_ITEM;
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
//public TextView mTxt_Type;
public ImageView mImg_medication;
public ViewHolder(View itemView) {
super(itemView);
// mTxt_Type = (TextView) itemView.findViewById(R.id.mTxt);
mImg_medication = (ImageView) itemView.findViewById(R.id.mImg_medication);
}
}
}
//Type Adapter ends ************************************************
I am not sure I get you properly but you want to change the data of one recyclerview and reset the value of other recyclerview
Try using recyclerView.scrollToPosition(INDEX_YOU_WANT_TO_SCROLL_TO);
IF YOU WANT TO ACHIEVE THE CENTER POSTION OF THE DATA USE
recyclerview.scrollToPosition(arraylist.size()/2);
arrayList in which your drawable data is stored

color of ActionBar not changing

i have created an app in which there are 4 tabs in the action bar .
i have used a manuelpeinado.fadingactionbar .
while scrolling ,it works for the first tab but when i shift to second tab color is not changing .
i looked in to logcat and find that values of "mActionBarBackgroundDrawable.setAlpha(newAlpha);"
is changing but color is not changing.
its my 1st question on stackoverflow if i missed something then sorry for that .
thanks in ADV.
public class FadingActionBarHelper {
protected static final String TAG = "FadingActionBarHelper";
private Drawable mActionBarBackgroundDrawable;
private FrameLayout mHeaderContainer;
private int mActionBarBackgroundResId;
private int mHeaderLayoutResId;
private View mHeaderView;
private int mContentLayoutResId;
private View mContentView;
private ActionBar mActionBar;
private LayoutInflater mInflater;
private boolean mLightActionBar;
private boolean mUseParallax = true;
private int mLastDampedScroll;
private int mLastHeaderHeight = -1;
private ViewGroup mContentContainer;
private ViewGroup mScrollView;
private boolean mFirstGlobalLayoutPerformed;
private View mMarginView;
private View mListViewBackgroundView;
private double speed = 0;
public FadingActionBarHelper actionBarBackground(int drawableResId) {
mActionBarBackgroundResId = drawableResId;
return this;
}
public FadingActionBarHelper actionBarBackground(Drawable drawable) {
mActionBarBackgroundDrawable = drawable;
return this;
}
public FadingActionBarHelper headerLayout(int layoutResId) {
mHeaderLayoutResId = layoutResId;
return this;
}
public FadingActionBarHelper headerView(View view) {
mHeaderView = view;
return this;
}
public FadingActionBarHelper contentLayout(int layoutResId) {
mContentLayoutResId = layoutResId;
return this;
}
public FadingActionBarHelper contentView(View view) {
mContentView = view;
return this;
}
public FadingActionBarHelper lightActionBar(boolean value) {
mLightActionBar = value;
return this;
}
public FadingActionBarHelper parallax(boolean value) {
mUseParallax = value;
return this;
}
public double getSpeed(){
return speed;
}
public View createView(Context context) {
return createView(LayoutInflater.from(context));
}
public View createView(LayoutInflater inflater) {
//
// Prepare everything
mInflater = inflater;
if (mContentView == null) {
mContentView = inflater.inflate(mContentLayoutResId, null);
}
if (mHeaderView == null) {
mHeaderView = inflater.inflate(mHeaderLayoutResId, mHeaderContainer, false);
}
//
// See if we are in a ListView or ScrollView scenario
ListView listView = (ListView) mContentView.findViewById(android.R.id.list);
View root;
if (listView != null) {
root = createListView(listView);
} else {
root = createScrollView();
}
// Use measured height here as an estimate of the header height, later on after the layout is complete
// we'll use the actual height
int widthMeasureSpec = MeasureSpec.makeMeasureSpec(LayoutParams.MATCH_PARENT, MeasureSpec.EXACTLY);
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY);
mHeaderView.measure(widthMeasureSpec, heightMeasureSpec);
updateHeaderHeight(mHeaderView.getMeasuredHeight());
root.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
int headerHeight = mHeaderContainer.getHeight();
if (!mFirstGlobalLayoutPerformed && headerHeight != 0) {
updateHeaderHeight(headerHeight);
mFirstGlobalLayoutPerformed = true;
}
}
});
return root;
}
public void initActionBar(Activity activity) {
mActionBar = getActionBar(activity);
if (mActionBarBackgroundDrawable == null) {
mActionBarBackgroundDrawable = activity.getResources().getDrawable(mActionBarBackgroundResId);
}
mActionBar.setBackgroundDrawable(mActionBarBackgroundDrawable);
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {
mActionBarBackgroundDrawable.setCallback(mDrawableCallback);
Toast.makeText(activity, "Inside initActionBar version less than jellybean", Toast.LENGTH_SHORT);
}
Toast.makeText(activity, " Inside initActionBar ", Toast.LENGTH_SHORT);
mActionBarBackgroundDrawable.setAlpha(0);
}
protected ActionBar getActionBar(Activity activity) {
return activity.getActionBar();
}
private Drawable.Callback mDrawableCallback = new Drawable.Callback() {
#Override
public void invalidateDrawable(Drawable who) {
mActionBar.setBackgroundDrawable(who);
}
#Override
public void scheduleDrawable(Drawable who, Runnable what, long when) {
}
#Override
public void unscheduleDrawable(Drawable who, Runnable what) {
}
};
private View createScrollView() {
mScrollView = (ViewGroup) mInflater.inflate(R.layout.fab__scrollview_container, null);
NotifyingScrollView scrollView = (NotifyingScrollView) mScrollView.findViewById(R.id.fab__scroll_view);
scrollView.setOnScrollChangedListener(mOnScrollChangedListener);
mContentContainer = (ViewGroup) mScrollView.findViewById(R.id.fab__container);
mContentContainer.addView(mContentView);
mHeaderContainer = (FrameLayout) mScrollView.findViewById(R.id.fab__header_container);
initializeGradient(mHeaderContainer);
mHeaderContainer.addView(mHeaderView, 0);
mMarginView = mContentContainer.findViewById(R.id.fab__content_top_margin);
return mScrollView;
}
private NotifyingScrollView.OnScrollChangedListener mOnScrollChangedListener = new NotifyingScrollView.OnScrollChangedListener() {
public void onScrollChanged(ScrollView who, int l, int t, int oldl, int oldt) {
onNewScroll(t);
}
};
private View createListView(ListView listView) {
mContentContainer = (ViewGroup) mInflater.inflate(R.layout.fab__listview_container, null);
mContentContainer.addView(mContentView);
mHeaderContainer = (FrameLayout) mContentContainer.findViewById(R.id.fab__header_container);
initializeGradient(mHeaderContainer);
mHeaderContainer.addView(mHeaderView, 0);
mMarginView = new View(listView.getContext());
mMarginView.setLayoutParams(new AbsListView.LayoutParams(LayoutParams.MATCH_PARENT, 0));
listView.addHeaderView(mMarginView, null, false);
// Make the background as high as the screen so that it fills regardless of the amount of scroll.
mListViewBackgroundView = mContentContainer.findViewById(R.id.fab__listview_background);
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mListViewBackgroundView.getLayoutParams();
params.height = Utils.getDisplayHeight(listView.getContext());
mListViewBackgroundView.setLayoutParams(params);
listView.setOnScrollListener(new CustomScrollListener());
return mContentContainer;
}
private class CustomScrollListener implements OnScrollListener{
private int previousFirstVisibleItem = 0;
private long previousEventTime = 0, currTime, timeToScrollOneElement;
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
View topChild = null;
topChild = view.getChildAt(0);
if (topChild == null) {
onNewScroll(0);
} else if (topChild != mMarginView) {
onNewScroll(mHeaderContainer.getHeight());
} else {
onNewScroll(-topChild.getTop());
}
if (previousFirstVisibleItem != firstVisibleItem) {
currTime = System.currentTimeMillis();
timeToScrollOneElement = currTime - previousEventTime;
speed = ((double) 1 / timeToScrollOneElement) * 1000;
previousFirstVisibleItem = firstVisibleItem;
previousEventTime = currTime;
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
}
private int mLastScrollPosition ;
private void onNewScroll(int scrollPosition) {
if (mActionBar == null) {
return;
}
int currentHeaderHeight = mHeaderContainer.getHeight();
if (currentHeaderHeight != mLastHeaderHeight) {
updateHeaderHeight(currentHeaderHeight); // to make position of header at its default pos.
}
int headerHeight = currentHeaderHeight - mActionBar.getHeight();
float ratio = (float) Math.min(Math.max(scrollPosition, 0), headerHeight) / headerHeight;
int newAlpha = (int) (ratio * 255);
Log.d(" Inside onNewScroll() ", ""+newAlpha);
mActionBarBackgroundDrawable.setAlpha(newAlpha);
// addParallaxEffect(scrollPosition);
}
private void addParallaxEffect(int scrollPosition) {
float damping = mUseParallax ? 0.5f : 1.0f;
int dampedScroll = (int) (scrollPosition * damping);
int offset = mLastDampedScroll - dampedScroll;
Log.d(" Inside addParallaxEffect() ", ""+offset);
mHeaderContainer.offsetTopAndBottom(offset);
if (mListViewBackgroundView != null) {
offset = mLastScrollPosition - scrollPosition;
mListViewBackgroundView.offsetTopAndBottom(offset);
}
if (mFirstGlobalLayoutPerformed) {
mLastScrollPosition = scrollPosition;
mLastDampedScroll = dampedScroll;
}
}
private void updateHeaderHeight(int headerHeight) {
ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) mMarginView.getLayoutParams();
params.height = headerHeight;
mMarginView.setLayoutParams(params);
if (mListViewBackgroundView != null) {
FrameLayout.LayoutParams params2 = (FrameLayout.LayoutParams) mListViewBackgroundView.getLayoutParams();
params2.topMargin = headerHeight;
mListViewBackgroundView.setLayoutParams(params2);
}
mLastHeaderHeight = headerHeight;
}
private void initializeGradient(ViewGroup headerContainer) {
View gradientView = headerContainer.findViewById(R.id.fab__gradient);
int gradient = R.drawable.fab__gradient;
if (mLightActionBar) {
gradient = R.drawable.fab__gradient_light;
}
gradientView.setBackgroundResource(gradient);
}
}

Android mergeAdapter ListView + HorizontalScrollView

I have been using mergeAdapter to merge together multiple list view without any problem. And right now, i'd like to use it to merge together a list view at the top, a horizontalscrollview in the middle and another list view at the bottom, but so far... i couldn't figure out how to do it. It would be great if someone could give me a hand...
Below is my existing code.
MyActivity
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.listview_a);
lv = (ListView) findViewById(R.id.list_all);
adapter=new MergeAdapter();
infoArray = new ArrayList<Infos>();
photoArray = new ArrayList<Photos>();
commentArray = new ArrayList<Comments>();
infoAdapter = new InfoAdapter(MyActivity.this, R.layout.info_list_layout, infoArray);
/// photoAdapter = new PhotoAdapter(MyActivity.this, R.layout.photo_hscroll_layout, photoArray); /// STUCK
commentAdapter = new CommentAdapter(MyActivity.this, R.layout.comment_list_layout, commentArray);
lv.setTextFilterEnabled(true);
adapter.addAdapter(infoAdapter);
/// adapter.addAdapter(photoAdapter); //// STUCK
adapter.addAdapter(commentAdapter);
lv.setAdapter(adapter);
try {
new stuffSync().execute("http://www.StuckForDays.com/json");
} catch(Exception e) {}
}
private class stuffSync extends AsyncTask<String, Integer, stuffDetail> {
protected stuffDetail doInBackground(String... urls) {
stuffDetail list = null;
int count = urls.length;
for (int i = 0; i < count; i++) {
try {
//rest client
RestClient client = new RestClient(urls[i]);
try {
client.Execute(RequestMethod.GET);
} catch (Exception e) {
e.printStackTrace();
}
String json = client.getResponse();
list = new Gson().fromJson(json, stuffDetail.class);
//
} catch(Exception e) {}
}
return list;
}
protected void onProgressUpdate(Integer... progress) {
}
protected void onPostExecute(stuffDetail list) {
List<Infos> info = list.getInfo();
for (Infos info2 : info) {
infoArray.add(info2);
}
List<Photos> photos = list.getPhotos();
for (Photos photo : photos) {
photoArray.add(photo);
System.out.println(photo);
}
List<Comments> comments = list.getComments();
for (Comments comment : comments) {
commentArray.add(comment);
}
infoAdapter.notifyDataSetChanged();
// photoAdapter.notifyDataSetChanged(); //// STUCK
commentAdapter.notifyDataSetChanged();
}
}
infoAdapter and commentAdapter (pretty much the same)
public class InfoAdapter extends ArrayAdapter<Infos> {
int resource;
String response;
Context context;
private LayoutInflater dInflater;
public InfoAdapter(Context context, int resource, List<Infos> objects) {
super(context, resource, objects);
this.resource = resource;
dInflater = LayoutInflater.from(context);
}
static class ViewHolder {
TextView realname;
TextView nickname;
}
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder holder;
Infos lm = (Infos) getItem(position);
//Inflate the view
if(convertView==null)
{
convertView = dInflater.inflate(R.layout.info_list_layout, null);
holder = new ViewHolder();
holder.realname = (TextView) convertView.findViewById(R.id.realname);
holder.nickname = (TextView) convertView.findViewById(R.id.nickname);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder) convertView.getTag();
}
holder.realname.setText(lm.getRealName());
holder.nickname.setText(lm.getNickname());
return convertView;
}
}
my photo json
{
"photos" : [
{
"thumbnail" : "http://www.myserver.com/01.jpg"
},
{
"thumbnail" : "http://www.myserver.com/02.jpg"
},
{
"thumbnail" : "http://www.myserver.com/03.jpg"
}
]}
And now i am stuck on how to get the photoArray to create the middle section horizontal scroll view... i could get the json and add them to the photoArray, just don't know how to extract, create the view and show it.
thanks all in advance
i think problem solve with horizontal scroll view.. this is a custom control..
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Queue;
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.Scroller;
public class HorizontalListView extends AdapterView<ListAdapter> {
public boolean mAlwaysOverrideTouch = true;
protected ListAdapter mAdapter;
private int mLeftViewIndex = -1;
private int mRightViewIndex = 0;
protected int mCurrentX;
protected int mNextX;
private int mMaxX = Integer.MAX_VALUE;
private int mDisplayOffset = 0;
protected Scroller mScroller;
private GestureDetector mGesture;
private Queue<View> mRemovedViewQueue = new LinkedList<View>();
private OnItemSelectedListener mOnItemSelected;
private OnItemClickListener mOnItemClicked;
private OnItemLongClickListener mOnItemLongClicked;
private boolean mDataChanged = false;
private boolean mMeasureHeightForVisibleOnly = true;
public HorizontalListView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private synchronized void initView() {
mLeftViewIndex = -1;
mRightViewIndex = 0;
mDisplayOffset = 0;
mCurrentX = 0;
mNextX = 0;
mMaxX = Integer.MAX_VALUE;
mScroller = new Scroller(getContext());
mGesture = new GestureDetector(getContext(), mOnGesture);
}
#Override
public void setOnItemSelectedListener(AdapterView.OnItemSelectedListener listener) {
mOnItemSelected = listener;
}
#Override
public void setOnItemClickListener(AdapterView.OnItemClickListener listener){
mOnItemClicked = listener;
}
#Override
public void setOnItemLongClickListener(AdapterView.OnItemLongClickListener listener) {
mOnItemLongClicked = listener;
}
private DataSetObserver mDataObserver = new DataSetObserver() {
#Override
public void onChanged() {
synchronized(HorizontalListView.this){
mDataChanged = true;
}
invalidate();
requestLayout();
}
#Override
public void onInvalidated() {
reset();
invalidate();
requestLayout();
}
};
#Override
public ListAdapter getAdapter() {
return mAdapter;
}
#Override
public View getSelectedView() {
//TODO: implement
return null;
}
#Override
public void setAdapter(ListAdapter adapter) {
if(mAdapter != null) {
mAdapter.unregisterDataSetObserver(mDataObserver);
}
mAdapter = adapter;
mAdapter.registerDataSetObserver(mDataObserver);
reset();
}
/**
* #param visibleOnly - If set to true, then height is calculated
* only using visible views. If set to false then height is
* calculated using _all_ views in adapter. Default is true.
* Be very careful when passing false, as this may result in
* significant performance hit for larger number of views.
*/
public void setHeightMeasureMode(boolean visibleOnly) {
if(mMeasureHeightForVisibleOnly != visibleOnly) {
mMeasureHeightForVisibleOnly = visibleOnly;
requestLayout();
}
}
private synchronized void reset(){
initView();
removeAllViewsInLayout();
requestLayout();
}
#Override
public void setSelection(int position) {
//TODO: implement
}
private void addAndMeasureChild(final View child, int viewPos) {
LayoutParams params = child.getLayoutParams();
if(params == null) {
params = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
}
addViewInLayout(child, viewPos, params, true);
child.measure(MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(getHeight(), MeasureSpec.AT_MOST));
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(MeasureSpec.getMode(heightMeasureSpec) != MeasureSpec.EXACTLY) {
int height = 0;
if(mMeasureHeightForVisibleOnly) {
int childCount = getChildCount();
for(int i = 0; i < childCount; i++) {
View v = getChildAt(i);
v.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
if(v.getMeasuredHeight() > height) {
height = v.getMeasuredHeight();
}
}
} else {
/* Traverses _all_ views! Bypasses view recycler! */
HashMap<Integer, View> mRecycler = new HashMap<Integer, View>();
int childCount = getAdapter().getCount();
for(int i = 0; i < childCount; i++) {
int type = getAdapter().getItemViewType(i);
View convertView = mRecycler.get(type);
View v = getAdapter().getView(i, convertView, this);
mRecycler.put(type, v);
v.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
if(v.getMeasuredHeight() > height) {
height = v.getMeasuredHeight();
}
}
}
if(MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
int maxHeight = MeasureSpec.getSize(heightMeasureSpec);
if(maxHeight < height) {
height = maxHeight;
}
}
setMeasuredDimension(getMeasuredWidth(), height);
}
}
#Override
protected synchronized void onLayout(boolean changed, int left, int top,
int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if(mAdapter == null){
return;
}
if(mDataChanged){
int oldCurrentX = mCurrentX;
initView();
removeAllViewsInLayout();
mNextX = oldCurrentX;
mDataChanged = false;
}
if(mScroller.computeScrollOffset()){
int scrollx = mScroller.getCurrX();
mNextX = scrollx;
}
if(mNextX <= 0){
mNextX = 0;
mScroller.forceFinished(true);
}
if(mNextX >= mMaxX) {
mNextX = mMaxX;
mScroller.forceFinished(true);
}
int dx = mCurrentX - mNextX;
removeNonVisibleItems(dx);
fillList(dx);
positionItems(dx);
mCurrentX = mNextX;
if(!mScroller.isFinished()){
post(new Runnable(){
public void run() {
requestLayout();
}
});
}
}
private void fillList(final int dx) {
int edge = 0;
View child = getChildAt(getChildCount()-1);
if(child != null) {
edge = child.getRight();
}
fillListRight(edge, dx);
edge = 0;
child = getChildAt(0);
if(child != null) {
edge = child.getLeft();
}
fillListLeft(edge, dx);
}
private void fillListRight(int rightEdge, final int dx) {
while(rightEdge + dx < getWidth() && mRightViewIndex < mAdapter.getCount()) {
View child = mAdapter.getView(mRightViewIndex, mRemovedViewQueue.poll(), this);
addAndMeasureChild(child, -1);
rightEdge += child.getMeasuredWidth();
if(mRightViewIndex == mAdapter.getCount()-1) {
mMaxX = mCurrentX + rightEdge - getWidth();
}
if (mMaxX < 0) {
mMaxX = 0;
}
mRightViewIndex++;
}
}
private void fillListLeft(int leftEdge, final int dx) {
while(leftEdge + dx > 0 && mLeftViewIndex >= 0) {
View child = mAdapter.getView(mLeftViewIndex, mRemovedViewQueue.poll(), this);
addAndMeasureChild(child, 0);
leftEdge -= child.getMeasuredWidth();
mLeftViewIndex--;
mDisplayOffset -= child.getMeasuredWidth();
}
}
private void removeNonVisibleItems(final int dx) {
View child = getChildAt(0);
while(child != null && child.getRight() + dx <= 0) {
mDisplayOffset += child.getMeasuredWidth();
mRemovedViewQueue.offer(child);
removeViewInLayout(child);
mLeftViewIndex++;
child = getChildAt(0);
}
child = getChildAt(getChildCount()-1);
while(child != null && child.getLeft() + dx >= getWidth()) {
mRemovedViewQueue.offer(child);
removeViewInLayout(child);
mRightViewIndex--;
child = getChildAt(getChildCount()-1);
}
}
private void positionItems(final int dx) {
if(getChildCount() > 0){
mDisplayOffset += dx;
int left = mDisplayOffset;
for(int i=0;i<getChildCount();i++){
View child = getChildAt(i);
int childWidth = child.getMeasuredWidth();
child.layout(left, 0, left + childWidth, child.getMeasuredHeight());
left += childWidth;
}
}
}
public synchronized void scrollTo(int x) {
mScroller.startScroll(mNextX, 0, x - mNextX, 0);
requestLayout();
}
#Override
public boolean dispatchTouchEvent(MotionEvent ev) {
boolean handled = super.dispatchTouchEvent(ev);
handled |= mGesture.onTouchEvent(ev);
return handled;
}
protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
synchronized(HorizontalListView.this){
mScroller.fling(mNextX, 0, (int)-velocityX, 0, 0, mMaxX, 0, 0);
}
requestLayout();
return true;
}
protected boolean onDown(MotionEvent e) {
mScroller.forceFinished(true);
return true;
}
private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onDown(MotionEvent e) {
return HorizontalListView.this.onDown(e);
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return HorizontalListView.this.onFling(e1, e2, velocityX, velocityY);
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
synchronized(HorizontalListView.this){
mNextX += (int)distanceX;
}
requestLayout();
return true;
}
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Rect viewRect = new Rect();
for(int i=0;i<getChildCount();i++){
View child = getChildAt(i);
int left = child.getLeft();
int right = child.getRight();
int top = child.getTop();
int bottom = child.getBottom();
viewRect.set(left, top, right, bottom);
if(viewRect.contains((int)e.getX(), (int)e.getY())){
if(mOnItemClicked != null){
mOnItemClicked.onItemClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));
}
if(mOnItemSelected != null){
mOnItemSelected.onItemSelected(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId( mLeftViewIndex + 1 + i ));
}
break;
}
}
return true;
}
#Override
public void onLongPress(MotionEvent e) {
Rect viewRect = new Rect();
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
int left = child.getLeft();
int right = child.getRight();
int top = child.getTop();
int bottom = child.getBottom();
viewRect.set(left, top, right, bottom);
if (viewRect.contains((int) e.getX(), (int) e.getY())) {
if (mOnItemLongClicked != null) {
mOnItemLongClicked.onItemLongClick(HorizontalListView.this, child, mLeftViewIndex + 1 + i, mAdapter.getItemId(mLeftViewIndex + 1 + i));
}
break;
}
}
}
};
}
and you can set data in this same as a custom listadapter in listview.
here is the custom adapter
private class ListAdapter extends ArrayAdapter<bin> { // --CloneChangeRequired
private ArrayList<bin> mList; // --CloneChangeRequired
ImageView img;
TextView title;
String id;
public ListAdapter(Context context, int textViewResourceId,
ArrayList<bin> list) { // --CloneChangeRequired
super(context, textViewResourceId, list);
this.mList = list;
imageLoader = new ImageLoader(YoutubeplayerActivity.this
.getApplicationContext());
}
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = convertView;
try {
if (view == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = vi.inflate(R.layout.cuslistview, null); // --CloneChangeRequired(list_item)
}
img = (ImageView) view.findViewById(R.id.imageView1);
title = (TextView) view.findViewById(R.id.textView1);
final bin listItem = mList.get(position);
// --CloneChangeRequired
if (listItem != null) {
id = listItem.getId();
imageLoader.DisplayImage(listItem.getThumbnail(), img);
title.setText(listItem.getTitle());
rlv.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
}
});
}
} catch (Exception e) {
Log.v("log", "" + e.toString());
}
return view;
}
}
you can bind data in horizontal listview
HorizonatlListView hv = (HorizontalListView) findviewbyId(R.id.hv1);
hv.setadater(new ListAdapter(getApplicationContext,R.id.hv1,ArrayList<bin>));

Categories

Resources