I am currently trying to draw a graph within an Android application. The library I found is called GraphView (http://www.jjoe64.com/p/graphview-library.html). I am currently using version 2, which is available on GitHub.
Drawing graphs works really nicely. The code necessary to get a graph is the following:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Map<String,List<GraphEntry>> graphData = (...)
if (graphData != null) {
List<GraphEntry> entries = graphData.get("temperature");
GraphView.GraphViewData[] data = new GraphView.GraphViewData[entries.size()];
int i = 0;
for (GraphEntry entry : entries) {
data[i++] = new GraphView.GraphViewData(entry.getDate().getTime(), entry.getValue());
}
GraphView.GraphViewSeries graphViewSeries = new GraphView.GraphViewSeries("temperature", 0xffff0000, data);
LineGraphView graphView = new LineGraphView(this, "temperature");
graphView.addSeries(graphViewSeries);
graphView.setShowLegend(true);
LinearLayout graphLayout = (LinearLayout) findViewById(R.id.layout);
graphLayout.addView(graphView);
}
}
This will produce a normal graph. Unfortunately, all kinds of labels are missing. The documentation tells that for the normal use case, one does not have to care about labels, as the library does this automatically. What am I doing wrong? I only get the plain graph, without any labels.
For the completeness, I am adding the graph to a linear layout. The appropriate layout file has the following contents:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:padding="5dp"
android:id="#+id/layout"
android:orientation="vertical"
></LinearLayout>
The GraphEntry class is only a container with a java.util.Date attribute and a double value attribute.
Thank you very much for any help,
Matthias
I switched to another charting engine: AChartEngine. This one works out of the box.
I had the same problem. This can be solved by removing the following line from the manifest file.
android:theme="#style/AppTheme"
I know this is quite vague, but worked for me. I don't the exact reason why this happens. If u guys come across the better solution please do share it.
You should use the latest version from github and include that in your project. This will allow you to set various colours using
graphView.getGraphViewStyle().setGridColor(Color.GREEN);
graphView.getGraphViewStyle().setHorizontalLabelsColor(Color.YELLOW);
graphView.getGraphViewStyle().setVerticalLabelsColor(Color.RED);
Related
I am working on a React Native implementation of the Bitmovin player using their Android SDK. At this stage, I'm not sure how specific this is to the Bitmovin player, but as they don't officially support React Native at this stage, I want to ask about this on SO first. This is a React Native UI Component with a custom view, using a layout file. I am trying to present a subtitle view on top of a player view, and I have based my layout on Bitmovin's simple examples. In fact I have simplified the layout even further:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<com.bitmovin.player.PlayerView
android:id="#+id/bitmovinPlayerView"
app:shutter_background_color="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/bootsplash_background">
<com.bitmovin.player.SubtitleView
android:id="#+id/bitmovinSubtitleView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:foregroundGravity="center" />
</com.bitmovin.player.PlayerView>
</LinearLayout>
This presents the SubtitleView at the top of the screen. Nothing I have tried so far presents the SubtitleView at the bottom of the screen in the more common position. I have experimented with every single parameter on all of these elements, as far as I can tell. Here is the code that initialises the view:
public void init() {
inflate(context, R.layout.player_container, this);
StyleConfig styleConfig = new StyleConfig();
styleConfig.setUiEnabled(false);
PlayerConfig playerConfig = new PlayerConfig();
playerConfig.setStyleConfig(styleConfig);
playerView = findViewById(R.id.bitmovinPlayerView);
player = Player.create(context, playerConfig);
playerView.setPlayer(player);
player.on(SourceEvent.Loaded.class, this::onLoad);
player.on(PlayerEvent.Playing.class, this::onPlay);
player.on(PlayerEvent.Paused.class, this::onPause);
player.on(PlayerEvent.Seek.class, this::onSeek);
player.on(PlayerEvent.TimeChanged.class, this::onTimeChanged);
player.on(PlayerEvent.Destroy.class, this::onDestroy);
player.on(PlayerEvent.Seeked.class, this::onSeeked);
player.on(PlayerEvent.PlaybackFinished.class, this::onPlaybackFinished);
player.on(PlayerEvent.Ready.class, this::onReady);
player.on(SourceEvent.Error.class, this::onError);
player.on(SourceEvent.SubtitleChanged.class, this::onSubtitleChanged);
player.on(PlayerEvent.Error.class, this::onError);
subtitleView = findViewById(R.id.bitmovinSubtitleView);
subtitleView.setPlayer(player);
player.setVolume(100);
}
I have read that React Native styles the top-level view of a UI Component, so this is my only clue at this stage. I'm unsure how to respond to that info however...
EDIT: The problem is likely to be that dynamically updating view layouts in Android in React Native is not straightforward. This has been discussed at length here.
EDIT 2: I have tried to listen for global layout changes, which is one of the proposed workarounds for view layout issues:
getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
requestLayout();
}
});
This is called as expected, but has no effect on the subtitleView, which still displays at the top of the player, which seems to be because it has a height of 0.
EDIT 3: Another suggested solution that didn't work for me:
private void setupLayoutHack() {
Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
#Override
public void doFrame(long frameTimeNanos) {
manuallyLayoutChildren();
getViewTreeObserver().dispatchOnGlobalLayout();
Choreographer.getInstance().postFrameCallback(this);
}
});
}
private void manuallyLayoutChildren() {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
}
}
I called setupLayoutHack() in the constructor but saw no difference after applying those changes either :(
EDIT 4: My final attempt at fixing the SubtitleView layout was experimenting with measuring and laying out in various ways:
private void refreshViewChildrenLayout(View view){
view.measure(
View.MeasureSpec.makeMeasureSpec(view.getMeasuredWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(view.getMeasuredHeight(), View.MeasureSpec.EXACTLY));
view.layout(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
}
However, the height in all cases that I tried was 0, which meant nothing was altered. There is a solution mentioned in the above RN issue that suggests that the shadow node for the subtitle view should be overridden. So one way forward could be to build a new subtitle view that has that included.
However, at this stage it seems to me an easier approach to respond to subtitle cues in React Native and perform all display and styling there.
(There is also a lesser issue of how to make the background on either side of the text transparent, but the layout issue is far more important at this stage).
Disclaimer: I'm not very familiar with React Native and how it influences layout creation if at all.
However looking at your layout file, it indicates that the SubtitleView is the top child of the PlayerView, which is a FrameLayout, thus gets added at the top (left). By specifying android:layout_height="wrap_content" on the SubtitleView it will only take up space that is required by the view. In the Bitmovin sample, it is generated in code and therefore should inherit the attributes from the parent, which is a RelativeLayout with android:layout_weight="1" which results in stretching it's height to the space available.
Long story short, try setting the height of your SubtitleView to match_parent
I am having trouble trying to create an adapter for a TwoWayView from lucasar.
https://github.com/lucasr/twoway-view
What I want is a facebook-style display for images. Sort of like this.
facebook style image structure
I am currently trying to convert the LayoutAdapter.java file in the github repo under the sample folder into an Adapter that I can use in my project, but I think I need some more information on what exactly this adapter is doing.
Here is the xml for the TwoWayView grid.
<org.lucasr.twowayview.widget.TwoWayView
android:id="#+id/twvGrid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/white"
android:orientation="vertical"
app:twowayview_layoutManager="SpannableGridLayoutManager"
app:twowayview_numColumns="3"
app:twowayview_numRows="3"
android:layout_below="#+id/youtubeVidImage"
android:layout_gravity="center"
android:fitsSystemWindows="true"
android:layout_marginTop="35dp"/>
Each Item in the layout (GalleryItem) is essentially just a url of an image to be displayed. And I want to be able to add these images to the layout in the Activity that set up the TwoWayView. Something like this for the code in the Activity that initializes the mPhotos array.
private void initImagesRecyclerView(){
Log.d(TAG, "initImagesRecyclerView: init Recyclerview");
imagesRecyclerView = findViewById(R.id.twvGrid);
mPhotos = new ArrayList<GalleryItem>();
//mImagePostsAdapter = new ImagePostsAdapter(this,mPhotos);
//imagesRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.HORIZONTAL));
mImagePostsAdapter = new TwoWayViewAdapter(this,imagesRecyclerView,R.layout.layout_staggered_grid);
imagesRecyclerView.setAdapter(mImagePostsAdapter);
}
Can anyone give me some advice on how to implement the TwoWayView? Anything on how to make the adapter and how to set it to the TwoWayView reference in the Activity would be great.
Thanks
I am new to android development and I am working on an android project where I have to integrate QR scanner. So I thought I would integrate Zxing QR scanner and came across this library https://github.com/dm77/barcodescanner, Following the instructions provided I have successfully integrated and scanned a QR as well.
Now I want to customise the camera view. The problem is there is no documentation on how to get access to the camera layout. Since I am new I might be missing something.
I have read through many Zxing related threads but I din find any solution.
Any help will be greatly appreciated either by letting me know on how I can get access to the camera view or pointing me out to some articles. Once I know how then I can complete the rest.
I would be happy to provide any further information.
Thanks in advance.
Update:
public class QrScanActivity extends BaseActivity implements ZXingScannerView.ResultHandler {
private ZXingScannerView mScannerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_scan);
// Programmatically initialize the scanner view
mScannerView = new ZXingScannerView(this);
// Set the scanner view as the content view
setContentView(mScannerView);
}
mScannerView is the view from the library. I want to get access to that view. I have a view called as activity_my_scan. I can add custom layout to that and use that but I don't know how to bypass the layout being used by the library.
Instead of just adding this lib as a jar using gradle's
compile 'me.dm7.barcodescanner:zxing:1.6.3'
you could clone the project from github or download a zip and uzip it and integrate to your project as a lib project. And then make any desired changes in its sources and its layouts.
ZXingScannerView extends BarcodeScannerView. You can access this by going to the declaration of ZXingScannerView (in Android Studio Ctrl+B).
public class ZXingScannerView extends BarcodeScannerView {
private MultiFormatReader mMultiFormatReader;
public static final List<BarcodeFormat> ALL_FORMATS = new ArrayList();
private List<BarcodeFormat> mFormats;
private ZXingScannerView.ResultHandler mResultHandler;
If you go the declaration of BarcodeScannerView, you'll notice a method called setupLayout() which formats the layout:
public void setupLayout() {
this.mPreview = new CameraPreview(this.getContext());
this.mViewFinderView = new ViewFinderView(this.getContext());
RelativeLayout relativeLayout = new RelativeLayout(this.getContext());
relativeLayout.setGravity(17);
relativeLayout.setBackgroundColor(-16777216);
relativeLayout.addView(this.mPreview);
this.addView(relativeLayout);
this.addView(this.mViewFinderView);
}
By going to the declaration of "CameraPreview" you'll be able to get more info for how the camera is laid out and you could maybe extend ZXingScannerView to edit the layout.
Hope this helps!
Cheers!
Well in your case i would try to include the layout into another layout, maybe it helps:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width=”match_parent”
android:layout_height=”match_parent”
android:background="#color/app_bg"
android:gravity="center_horizontal">
<include layout="#layout/titlebar"/>
<TextView android:layout_width=”match_parent”
android:layout_height="wrap_content"
android:text="#string/hello"
android:padding="10dp" />
...
</LinearLayout>
And of course there is information about that here ;)
In Android project I'm trying to add databindings using CrossLight part of MvvmCross.
Bindings to standard TextView/Buttons work great. But simplest markup with Mvx.Control:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android">
<Mvx.MvxListView />
</LinearLayout>
Gives an error
"Binary XML file line #1: Error inflating class Mvx.MvxListView"
The same thing is with Mvx.Spinner.
However, when instantiating it from code in Activity.OnCreate:
_bindingContext = new MvxAndroidBindingContext(this, new LayoutInflaterProvider(LayoutInflater), _viewModel);
var view = (LinearLayout)_bindingContext.BindingInflate(Resource.Layout.Main, null);
SetContentView(view);
var spinner = new MvxSpinner(this, null, new MvxAdapter(this, _bindingContext));
view.AddView(spinner);
Everything works great (including bindings). What am I doing wrong? Is this scenario supported in general?
Or maybe I should reference anything else except nuget MvvmCross.HotTuna.CrossCore?
P.S. Haven't found any samples with custom controls and CrossLight neither on github, nor on N+1 videos
If you want to use namespace abbreviations within your non-MvvmCross application, then you'll need to add those abbreviations. This can be done using a custom binding builder or using a 'light' setup step like:
var viewResolver = Mvx.Resolve<IMvxAxmlNameViewTypeResolver>();
viewResolver.ViewNamespaceAbbreviations["Mvx"] = "Cirrious.MvvmCross.Binding.Droid.Views";
viewResolver.ViewNamespaceAbbreviations["MyApp"] = "MyApp.Controls";
When doing this within a full MvvmCross application, then you can override the Setup property ViewNamespaceAbbreviations
protected override IDictionary<string, string> ViewNamespaceAbbreviations
{
get
{
var toReturn = base.ViewNamespaceAbbreviations;
toReturn["MyApp"] = "MyApp.UI.Droid.Controls";
return toReturn;
}
}
When markup was changed to using the full namespace and layout_width and layout_height attribute was added it started to work!
<Cirrious.MvvmCross.Binding.Droid.Views.MvxSpinner
android:id="#+id/MySpinner"
android:layout_width="fill_parent"
android:layout_height="20dp"
/>
It was found when I switched to default Android inflater and it was complaining about missing layout_width in Exceptions.
My application requires graph library and I am using achartengine graph library. My app requires graph to be only 50% of the screen and other part is used to display some other information.
Is it possible have xml resource file for achartengine's graph APIs and how to do it?
I tried to find an example but didn't find it. Is it supported or not?
This is a FAQ for AChartEngine.
The AChartEngine demo application is available for download here: AChartEngine demo
In the demo source code you can see an example on how to embed a chart into an existing view.
Basically, in the activity descriptor .xml file, we have defined the following as a placeholder for the chart. Of course, other user interface components go together with this layout:
ChartDemo/layout/xy_chart.xml near Line 27
<LinearLayout
android:id="#+id/chart"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal" />
We define a local variable:
ChartDemo/src/org.achartengine.chartdemo.demo.chart/XYChartBuilder.java near Line 68
private GraphicalView mChartView;
We instantiate it on the onResume() method of the activity:
ChartDemo/src/org.achartengine.chartdemo.demo.chart/XYChartBuilder.java near Line 163
protected void onResume() {
super.onResume();
if (mChartView == null) {
LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
mChartView = ChartFactory.getLineChartView(this, mDataset,
mRenderer);
layout.addView(mChartView, new LayoutParams
(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
...
} else {
mChartView.repaint();
}
}
Whenever new data is added (when the user presses the "Add" button in our case, a new point is added in the current series and:
ChartDemo/src/org.achartengine.chartdemo.demo.chart/XYChartBuilder.java near Line 147
if (mChartView != null) {
mChartView.repaint();
}
There are two sets of APIs in ChartFactory. For eg. getLineChartView() and getLineChartIntent(). So former is used to get a graphical view which can be added to customized layout and later is used to get the intent. In above example Dan has used getLineChartView() API which returns a GraphicalView.
You can write your xml like this...
<LinearLayout
android:layout_below="#+id/btn"
android:id="#+id/chart" android:orientation="horizontal"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_weight="1">
</LinearLayout>
and the java code snippet is
protected void onResume() {
super.onResume();
if (mChartView == null) {
LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
mChartView = ChartFactory.getBarChartView(this,getBarDemoDataset(values),renderer,Type.DEFAULT);
layout.addView(mChartView);
} else {
mChartView.repaint();
}
}
So here is a self sufficient place to find all about AChartEngine. Which includes link to download,
achartengine-1.1.0-demo-source.zip The AChartEngine 1.1.0 demo project source code. May 15 May 15 168 KB 8149
achartengine-1.1.0-javadocs.zip The AChartEngine 1.1.0 javadoc documentation. May 15 May 15 374 KB 3610
achartengine-1.1.0.jar The AChartEngine 1.1.0 binary build library. May 15 May 15 117 KB 5264
Which are latest for now(while posting this answer). Now follow these easy steps in order to add new chart file:
Download and add achartengine-1.1.0.jar to your project's lib section
Now right click on file and add it to build path, like in image
Now as define in previous answers, add following code to your class:
private GraphicalView mChartView;
private XYMultipleSeriesDataset dataset;
private XYMultipleSeriesRenderer renderer;
private BarChart.Type type;
protected void onResume() {
super.onResume();
if (mChartView == null) {
LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
/*getBarChartView(android.content.Context context, XYMultipleSeriesDataset dataset, XYMultipleSeriesRenderer renderer, BarChart.Type type)
Creates a bar chart view.*/
mChartView = ChartFactory.getBarChartView(this, dataset, renderer, type);//tView(this,getBarDemoDataset(values),renderer,Type.DEFAULT);
layout.addView(mChartView);
} else {
mChartView.repaint();
}
}
To get detail about any class of AChartEngineAPI, download achartengine-1.1.0-javadocs.zip and open by clicking in index.html
achartengine-1.1.0-demo-source.zip will be helpful during further deepar development where you can take reference for all charts