let me explain my problem.
I'm using a GridView with a custom adapter, and everything works fine. As the title says the problem comes when I scroll fast.
Scrolling slow works perfectly, but when I scroll fast and reach end I've got like a "kickback" to the middle of the grid, but this problem doesn't apear when I scroll fast from the back to the top.
I'm coding for 2.3.3 using 4.2 sdk version.
I'm testing on a 2.3.3 real phone and on a 4.2 emulator, same results.
Thanks for your futur answer ! (Sorry for my poor written English)
Here you are the code of my adapter.
import java.util.ArrayList;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
#SuppressWarnings("unused")
public class RadioAdapter extends BaseAdapter {
private Context context;
private final ArrayList<Radio> radios;
private LayoutInflater inflater;
public RadioAdapter(Context context, ArrayList<Radio> radios) {
this.context = context;
this.radios = radios;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return radios.size();
}
#Override
public Radio getItem(int position) {
// TODO Auto-generated method stub
return null;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
Radio radio = radios.get(position);
if (convertView == null) {
convertView = inflater.inflate(R.layout.item, null);
holder = new ViewHolder();
holder.textView = (TextView) convertView.findViewById(R.id.grid_item_label);
holder.imageView = (ImageView) convertView.findViewById(R.id.grid_item_cover);
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(radio.getName());
holder.imageView.setImageResource(radio.getThumbnail());
return convertView;
}
public static class ViewHolder {
TextView textView;
ImageView imageView;
}
}
EDIT3:
After some more research I've found this : https://github.com/Prototik/HoloEverywhere/issues/282
Are you using android:overScrollMode="never"? There is a bug in
scroller implementation in Gingerbread: http://code.google.com/p/android/issues/detail?id=15860
So the problem I have is normal on Gingerbread, damn.
I've tested with a 4.0.3 phone and it works normally. Problem solved.
EDIT2:
I've detected that the problem comes with
android:overScrollMode="never"
EDIT:
Here you are my layout :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".MainActivity" >
<ImageView
android:id="#+id/imageView1"
android:scaleType="fitStart"
android:adjustViewBounds="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:src="#drawable/top_bar" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="#string/app_name"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#color/White"
android:layout_alignLeft="#+id/imageView1"
android:layout_alignTop="#+id/imageView1"
android:layout_alignRight="#+id/imageView1"
android:layout_alignBottom="#+id/imageView1"
android:gravity="center" />
<censored.RadioView
android:layout_below="#id/imageView1"
android:id="#+id/gridView1"
android:numColumns="auto_fit"
android:columnWidth="100dp"
android:stretchMode="spacingWidthUniform"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:listSelector="#drawable/grid_selector"
android:drawSelectorOnTop="false"
android:overScrollMode="never"
android:fadingEdge="none"
android:scrollbars="none">
</censored.RadioView>
</RelativeLayout>
And the code of my RadioView
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.GridView;
public class RadioView extends GridView{
private Bitmap background;
public RadioView(Context context) {
super(context);
init();
}
public RadioView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public RadioView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
protected void init() {
background = BitmapFactory.decodeResource(getResources(), R.drawable.shelfcell_bgr);
}
#Override
protected void dispatchDraw(Canvas canvas) {
int top = getChildCount() > 0 ? getChildAt(0).getTop() : 0;
for (int y = top; y < getHeight(); y += background.getHeight()){
for (int x = 0; x < getWidth(); x += background.getWidth()){
canvas.drawBitmap(background, x, y, null);
}
}
super.dispatchDraw(canvas);
}
}
After some more research I've found this :
https://github.com/Prototik/HoloEverywhere/issues/282
Are you using android:overScrollMode="never"? There is a bug in
scroller implementation in Gingerbread:
http://code.google.com/p/android/issues/detail?id=15860
So the problem I have is normal on Gingerbread, damn.
I've tested with a 4.0.3 phone and it works normally. Problem solved.
Related
I'm trying to figure out why my images within class CustomPagerAdapter mResources are NOT showing up once the VerticalViewPager widget appears -- nothing on start and nothing during vertical swipe.
I've been at it for a couple days but just cant crack it. Doesnt help the documentation on ViewPager / Adapters isnt very clear.
Using - Nexus 6 AVD, minSdkVersion = 19
When i attempt to scroll up (single click from the bottom and swipe up all the way to the top) i then receive this error message...
*AndroidRuntime: FATAL EXCEPTION: main
Process: sparktic.com.verticalviewpager, PID: 19242
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:3562)*
AFAIK i'm adding and removing pager_item correctly.
java/ MainActivity.java
package sparktic.com.verticalviewpager;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity
{
VerticalViewPager mPager;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPager = findViewById(R.id.viewpager);
CustomPagerAdapter adapter = new CustomPagerAdapter(this);
mPager.setAdapter(adapter);
}
class CustomPagerAdapter extends PagerAdapter
{
Context mContext;
public LayoutInflater mLayoutInflater;
int[] mResources = {
R.drawable.first, // Dload: https://i.imgur.com/suvAa9x.jpg
R.drawable.second, // Dload: https://i.imgur.com/c2f0Hvy.jpg
R.drawable.third // Dload: https://i.imgur.com/0GAs8qp.jpg
};
public CustomPagerAdapter(Context context)
{
mContext = context;
mLayoutInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount()
{
return mResources.length;
}
#Override
public boolean isViewFromObject(View view, Object object)
{
return view == ((LinearLayout) object);
}
#Override
public Object instantiateItem(ViewGroup container, int position)
{
View itemView = mLayoutInflater.inflate(R.layout.pager_item, container, false);
ImageView imageView = (ImageView) itemView.findViewById(R.id.imageView);
imageView.setImageResource(mResources[position]);
container.addView(imageView);
return itemView;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object)
{
container.removeView((LinearLayout) object);
}
}
}
layout/ activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="sparktic.com.verticalviewpager.MainActivity">
<sparktic.com.verticalviewpager.VerticalViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
layout/ pager_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/imageView" />
</LinearLayout>
java/ VerticalViewPager.java
package sparktic.com.verticalviewpager;
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class VerticalViewPager extends ViewPager
{
public VerticalViewPager(Context context)
{
this(context, null);
}
public VerticalViewPager(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
#Override
public boolean canScrollHorizontally(int direction)
{
return false;
}
#Override
public boolean canScrollVertically(int direction)
{
return super.canScrollHorizontally(direction);
}
private void init()
{
setPageTransformer(true, new VerticalPageTransformer());
setOverScrollMode(View.OVER_SCROLL_NEVER);
}
#Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
final boolean toIntercept = super.onInterceptTouchEvent(flipXY(ev));
flipXY(ev);
return toIntercept;
}
#Override
public boolean onTouchEvent(MotionEvent ev)
{
final boolean toHandle = super.onTouchEvent(flipXY(ev));
flipXY(ev);
return toHandle;
}
private MotionEvent flipXY(MotionEvent ev)
{
final float width = getWidth();
final float height = getHeight();
final float x = (ev.getY() / height) * width;
final float y = (ev.getX() / width) * height;
ev.setLocation(x, y);
return ev;
}
private static final class VerticalPageTransformer implements ViewPager.PageTransformer
{
#Override
public void transformPage(View view, float position)
{
final int pageWidth = view.getWidth();
final int pageHeight = view.getHeight();
if (position < -1)
{
view.setAlpha(0);
}
else if (position <= 1)
{
view.setAlpha(1);
view.setTranslationX(pageWidth * -position);
float yPosition = position * pageHeight;
view.setTranslationY(yPosition);
}
else
{
view.setAlpha(0);
}
}
}
}
Solved my own problem. In case it helps someone else...
the issue was within "instantiateItem" method.
container.addView(imageView); should have been container.addView(itemView);
I still dont have a solid grasp as to what is happening within the PageAdapter overrides but it works so i'll take the win and move on.
I'm trying to draw a rectangle over camera2 textureview, when i run the code I see the usual camera screen with moving square , and when I Click (touch) it, app crashes with the error in topic. I also not sure I implemented the custom view correctly, Here are all the relevant parts, Would love some help (I'm not sure I have a good layout xml, I added ViewGroup code under OnCrearte, not sure i even need to touch xml)
-------CameraActivity.java:
package com.example.android.camera2video;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.ViewGroup;
public class CameraActivity extends Activity {
private Context context;
CustomView customview;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
customview = new CustomView(this);
final ViewGroup viewGroup = (ViewGroup) ((ViewGroup) this.findViewById(android.R.id.content)).getChildAt(0);
viewGroup.addView(new CustomView(this));
if (null == savedInstanceState) {
getFragmentManager().beginTransaction()
.replace(R.id.container, Camera2VideoFragment.newInstance())
.commit();
}
}
}
-------CustomView.java
package com.example.android.camera2video;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CustomView extends SurfaceView {
private Paint paint;
private SurfaceHolder mHolder;
private Context context;
public CustomView(Context context) {
super(context);
mHolder = getHolder();
mHolder.setFormat(PixelFormat.TRANSPARENT);
this.context = context;
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.STROKE);
}
public CustomView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// real work here
}
private void doAdditionalConstructorWork() {
// init variables etc.
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
invalidate();
if (mHolder.getSurface().isValid()) {
final Canvas canvas = mHolder.lockCanvas();
Log.d("touch", "touchRecieved by camera");
System.err.println("EXIT 1");
if (canvas != null) {
Log.d("touch", "touchRecieved CANVAS STILL Not Null");
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
canvas.drawColor(Color.TRANSPARENT);
canvas.drawCircle(event.getX(), event.getY(), 100, paint);
mHolder.unlockCanvasAndPost(canvas);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Canvas canvas1 = mHolder.lockCanvas();
if(canvas1 !=null){
canvas1.drawColor(0, PorterDuff.Mode.CLEAR);
mHolder.unlockCanvasAndPost(canvas1);
}
}
}, 1000);
}
mHolder.unlockCanvasAndPost(canvas);
}
}
return false;
}
}
-----fragment_camera2_video.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.android.camera2video.AutoFitTextureView
android:id="#+id/texture"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
android:layout_below="#id/texture"
android:background="#4285f4">
<Button
android:id="#+id/video"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="#string/record" />
<ImageButton
android:id="#+id/info"
android:contentDescription="#string/description_info"
style="#android:style/Widget.Material.Light.Button.Borderless"
android:layout_width="4dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|right"
android:padding="20dp"
android:src="#drawable/ic_action_info" />
</FrameLayout>
</RelativeLayout>
Only one thing can be drawing to a View at a time; once the SurfaceView is connected to the camera, you're not able to lock it for drawing yourself.
Your crash is probably because you're calling mHolder.unlockCanvasAndPost(canvas); outside of the null check.
If you want to draw over the cameara preview, you need a second View positioned on top of the SurfaceView.
After extending the ScrollView class I was able to easily be notified of the scrolling in realtime.
Now I need to capture the content of this scrollview in a very specific part.
Let's say I want to capture the top of the screen (matching parent width and a defined height, like 100dp). But only the content of the ScrollView and not the rest, if there is anything else on the top but not as part of the ScrollView.
I tried using on the scrollview :
setDrawingCacheEnabled(true);
getDrawingCache(true);
setDrawingCacheEnabled(false);
Then I tried to crop so that I get the part I want :
Bitmap.createBitmap(complete, 0, 0, width, height);
Results are very far from what I want to achieve and performance are very very poor and at some point I would get either a SIGENV or getDrawingCache(true) tries to use a recycled bitmap...
So how can I easily capture the content in the desired area without too much performance hit ?
Note: this process must be done as I am scrolling the content, so inside ScrollView's onScrollChanged(final int x, final int y).
Thanks !
Since the problem was fun I implemented it, it seems to work fine. I guess that you are recreating a Bitmap each time that's why goes slow.
The idea is like this, you create an area in the ScrollView that you want to copy (see Rect cropRect and Bitmap screenshotBitmap), it's full width and you just need to set the height. The view automatically set a scroll listener on itself and on every scroll it will copy that area. Note that setDrawingCacheEanbled(true) is called just once when the view is instantiated, it basically tells the view that you will call getDrawingCache(), which will return the Bitmap on which the view is drawing itself. It then copy the area of interest on screenshotBitmap and that's the Bitmap that you might want to use.
ScreenshottableScrollView.java
package com.example.lelloman.screenshottablescrollview;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.os.Build;
import android.util.AttributeSet;
import android.view.ViewTreeObserver;
import android.widget.ScrollView;
/**
* Created by lelloman on 16-2-16.
*/
public class ScreenshottableScrollView extends ScrollView implements ViewTreeObserver.OnScrollChangedListener {
public interface OnNewScreenshotListener {
void onNewScreenshot(Bitmap bitmap);
}
private Bitmap screenshotBitmap = null;
private Canvas screenshotCanvas = null;
private int screenshotHeightPx = 0;
private OnNewScreenshotListener listener = null;
private Rect cropRect;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public ScreenshottableScrollView(Context context) {
super(context);
init();
}
public ScreenshottableScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ScreenshottableScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public ScreenshottableScrollView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init(){
setDrawingCacheEnabled(true);
getViewTreeObserver().addOnScrollChangedListener(this);
}
public void setOnNewScreenshotListener(OnNewScreenshotListener listener){
this.listener = listener;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if(screenshotHeightPx != 0)
makeScrenshotBitmap(w,h);
}
public void setScreenshotHeightPx(int q){
screenshotHeightPx = q;
makeScrenshotBitmap(getWidth(), getHeight());
}
private void makeScrenshotBitmap(int width, int height){
if(screenshotBitmap != null) screenshotBitmap.recycle();
if(width == 0 || height == 0) return;
screenshotBitmap = Bitmap.createBitmap(width, screenshotHeightPx, Bitmap.Config.ARGB_8888);
screenshotCanvas = new Canvas(screenshotBitmap);
cropRect = new Rect(0,0,width,screenshotHeightPx);
}
#Override
public void onScrollChanged() {
if(listener == null) return;
Bitmap bitmap = getDrawingCache();
screenshotCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
screenshotCanvas.drawBitmap(bitmap,cropRect, cropRect,paint);
listener.onNewScreenshot(screenshotBitmap);
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.lelloman.screenshottablescrollview.MainActivity">
<com.example.lelloman.screenshottablescrollview.ScreenshottableScrollView
android:id="#+id/scrollView"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp">
<TextView
android:id="#+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</com.example.lelloman.screenshottablescrollview.ScreenshottableScrollView>
<View
android:layout_width="match_parent"
android:layout_height="20dp"
android:background="#ff000000"/>
<ImageView
android:id="#+id/imageView"
android:layout_width="match_parent"
android:layout_height="100dp" />
</LinearLayout>
MainActivity.java
package com.example.lelloman.screenshottablescrollview;
import android.graphics.Bitmap;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StringBuilder builder = new StringBuilder();
Random random = new Random();
String AB = "abcdefghijklmnopqrstuvwxyz ";
for(int i=0;i<100;i++){
builder.append("\n\n"+Integer.toString(i)+"\n\n");
for(int j =0;j<1000;j++){
builder.append(AB.charAt(random.nextInt(AB.length())));
}
}
((TextView) findViewById(R.id.textView)).setText(builder.toString());
final ImageView imageView = (ImageView) findViewById(R.id.imageView);
ScreenshottableScrollView scrollView = (ScreenshottableScrollView) findViewById(R.id.scrollView);
scrollView.setScreenshotHeightPx((int) (getResources().getDisplayMetrics().density * 100));
scrollView.setOnNewScreenshotListener(new ScreenshottableScrollView.OnNewScreenshotListener() {
#Override
public void onNewScreenshot(Bitmap bitmap) {
Log.d("MainActivity","onNewScreenshot");
imageView.setImageBitmap(bitmap);
}
});
}
}
I'm creating my Cell view by extending LinearLayout, it's creating parent, but not showing children. I really couldn't find the problem?
Cell cell = new Cell(ctx);
cell.setLetterAndPosition(new Point(1,1), new Letter("A");
import android.content.Context;
import android.graphics.Color;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import pe.kor.kelime.Model.Letter;
import pe.kor.kelime.R;
/**
* Created by me on 7/29/15.
*/
public class Cell extends LinearLayout {
private Letter letter;
private Point position; /* 0-3 / 0-3 based position*/
private TextView text;
private boolean touched = false;
public Cell(Context context) {
super(context);
init(context);
}
public Cell(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public Cell(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
public void setLetterAndPosition(Point position, Letter letter) {
this.letter = letter;
this.position = position;
this.text.setText(letter.getLetter());
}
void init(Context context) {
LayoutInflater.from(context).inflate(R.layout.view_cell, this);
text = (TextView) this.findViewById(R.id.text);
this.setBackgroundColor(Color.parseColor("#ffffff"));
}
public Letter getLetterObject() {
return letter;
}
public void setTouched(boolean e) {
this.touched = e;
if(this.touched) {
this.setBackgroundColor(Color.parseColor("#ff0000"));
}
else {
this.setBackgroundColor(Color.parseColor("#ffffff"));
}
}
public boolean isTouched() {
return touched;
}
public Point getPositionInBoard() {
return position;
}
}
View_cell.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5.5dp"
android:clickable="true">
<TextView
android:id="#+id/text"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="#ff0369"
android:baselineAligned="false"
android:clickable="true"
android:gravity="center|center_vertical"
android:includeFontPadding="false"
android:text="A"
android:textColor="#000"
android:textSize="36sp"
android:textStyle="bold"/>
</LinearLayout>
I had to override onLayout method.
onLayout(boolean paramBoolean, int left, int top, int right, int bottom)
#Override
protected void onLayout(boolean paramBoolean, int left, int top, int right, int bottom)
{
int widthOfCell = right - left;
getChildAt(0)
.layout(1,
1,
widthOfCell,
widthOfCell
);
}
I think that the problem is your Textview. You have not added the textview to your linearlayout.
Change your method init
void init(Context context) {
LayoutInflater.from(context).inflate(R.layout.view_cell, this);
text = (TextView) this.findViewById(R.id.text);
this.addView(text);
this.setBackgroundColor(Color.parseColor("#ffffff"));
}
I'm trying to create a custom view with two TextViews inside a vertical LinearLayout, but am totally confused as to how it all works.
Currently nothing is appearing as I my onDraw method isn't being called. I think this is due to the fact that my view (the LinearLayout?) has a width and height of both 0.
I think I should be overwriting my onMeasure, but after trying setMeasuredDimension(100,100) this still isn't working.
I am trying to inflate an xml inside the view and use the two TextViews in that.
An explanation would also be great so I can hopefully get my head around how this all works.
Thanks
size_button.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="#+id/sizeButtonSizeText"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
<TextView
android:id="#+id/sizeButtonSlugText"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
SizeButton.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View.MeasureSpec;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.nap.library.NapApplication;
import com.nap.library.R;
public class SizeButton extends LinearLayout {
private TextView mSize;
private TextView mSlug;
private String mSizeText;
private String mSlugText;
private Paint mPaint;
private boolean mSoldOut;
private Context mContext;
/*
public SizeButton(Context context) {
super(context);
setup();
}
public SizeButton(Context context, AttributeSet attrs) {
super(context, attrs);
setup();
}
*/
public SizeButton(Context context, String size, String slug) {
super(context);
mContext = context;
mSizeText = size;
mSlugText = slug;
setup();
}
public void setSoldOut(){
this.mSoldOut = true;
}
public boolean isSoldOut(){
return mSoldOut;
}
public void setSizeText(String size){
mSize.setText(size);
}
public void setSlugText(String slug){
mSlug.setText(slug);
}
public void setup(){
mPaint = new Paint();
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout buttonLayout = (LinearLayout) inflater.inflate(R.layout.size_button, null);
mSize = (TextView) buttonLayout.findViewById(R.id.sizeButtonSizeText);
mSize.setGravity(Gravity.CENTER);
mSize.setTextColor(Color.BLACK);
mSize.setText(mSizeText);
mSize.setTypeface(NapApplication.mPorter);
mSize.setWidth(10);
mSlug = (TextView) buttonLayout.findViewById(R.id.sizeButtonSlugText);
mSlug.setGravity(Gravity.CENTER);
mSlug.setTextColor(Color.BLACK);
mSlug.setText(mSlugText);
mSlug.setTypeface(NapApplication.mPorter);
invalidate();
requestLayout();
LinearLayout.LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
mSize.setLayoutParams(layoutParams);
mSlug.setLayoutParams(layoutParams);
Log.i("button","in setup");
Log.i("button","width = "+this.getWidth()+" height = "+this.getHeight());
Log.i("button","width = "+mSize.getWidth()+" sizeheight = "+mSize.getHeight());
Log.i("button","width = "+mSlug.getWidth()+" slugheight = "+mSlug.getHeight());
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.i("button","in onMeasure");
setMeasuredDimension(100,100);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i("button","in ondraw");
}
}
ProductFragment.java - where the button is added to the fragment
for (int i = 0; i < mItem.getSizes().length; i++) {
final SizeButton sizeButton = new SizeButton(getActivity(),mItem.getSizes()[i],"hello");
// Each size button has a sku set as its tag
sizeButton.setTag(mItem.getSkus()[i]);
sizeButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if(mItem.getSizes().length > 1) {
boolean selected = !sizeButton.isSelected();
if (selected) {
mCurrentSku = (String) v.getTag();
} else {
mCurrentSku = null;
}
}
configureButtons();
}
});
Log.e("button","Adding button to view");
mSizesWrapper.addView(sizeButton);
}
As your are extending a ViewGroup, you should override dispatchDraw(), not onDraw()